From 3966f46024ad785e6f242d021b1742259655572a Mon Sep 17 00:00:00 2001 From: Matthew Ellison Date: Fri, 28 Apr 2023 20:01:09 -0400 Subject: [PATCH] Updated more tests --- .../polysubstitution/Columnar.java | 35 +- .../cipherstream/polysubstitution/Hill.java | 184 ++- .../cipherstream/polysubstitution/Morse.java | 1 + .../polysubstitution/Playfair.java | 276 ++-- .../monosubstitution/TestBaconian.java | 12 +- .../monosubstitution/TestBaseX.java | 16 +- .../monosubstitution/TestBeaufort.java | 10 +- .../monosubstitution/TestCaesar.java | 4 +- .../monosubstitution/TestOneTimePad.java | 2 +- .../monosubstitution/TestPorta.java | 10 +- .../monosubstitution/TestSubstitution.java | 8 +- .../monosubstitution/TestVigenere.java | 8 +- .../polysubstitution/TestColumnar.java | 1348 ++++++++++------ .../polysubstitution/TestHill.java | 1198 +++++++++------ .../polysubstitution/TestPlayfair.java | 1355 +++++++++++------ 15 files changed, 2861 insertions(+), 1606 deletions(-) diff --git a/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Columnar.java b/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Columnar.java index 1a5efe1..1fe8e19 100644 --- a/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Columnar.java +++ b/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Columnar.java @@ -1,7 +1,7 @@ //MattrixwvWebsite/src/main/java/com/mattrixwv/CipherStreamJava/polySubstitution/Columnar.java //Mattrixwv // Created: 01-16-22 -//Modified: 07-09-22 +//Modified: 04-26-23 package com.mattrixwv.cipherstream.polysubstitution; @@ -18,7 +18,7 @@ import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; public class Columnar{ - protected static final Logger logger = LoggerFactory.getLogger(Columnar.class); + protected static Logger logger = LoggerFactory.getLogger(Columnar.class); //Fields protected String inputString; //The message that needs to be encoded/decoded @@ -108,7 +108,7 @@ public class Columnar{ inputString = inputString.replaceAll("\\s", ""); } if(!preserveSymbols){ - logger.debug("Remoing symbols"); + logger.debug("Removing symbols"); inputString = inputString.replaceAll("[^a-zA-Z\\s]", ""); } @@ -158,7 +158,7 @@ public class Columnar{ if(!preserveWhitespace){ logger.debug("Removing whitespace"); - inputString = inputString.replaceAll("[\\s]", ""); + inputString = inputString.replaceAll("\\s", ""); } if(!preserveSymbols){ logger.debug("Removing symbols"); @@ -271,8 +271,8 @@ public class Columnar{ } //Save and return the output - logger.debug("Output string '{}'", output); outputString = output.toString(); + logger.debug("Output string '{}'", output.toString()); } protected void createOutputStringFromRows(){ logger.debug("Creating output string for decoding"); @@ -315,15 +315,22 @@ public class Columnar{ continue; } + logger.debug("Working character {}", gridOutput.charAt(outputLoc)); if(Character.isUpperCase(inputChar)){ + logger.debug("Adding upper case"); + output.append(Character.toUpperCase(gridOutput.charAt(outputLoc++))); ++row; } else if(Character.isLowerCase(inputChar)){ + logger.debug("Adding lower case"); + output.append(Character.toLowerCase(gridOutput.charAt(outputLoc++))); ++row; } else{ + logger.debug("Adding symbol"); + output.append(inputChar); } @@ -334,20 +341,21 @@ public class Columnar{ } //Save and return the output - logger.debug("Decoded output string '{}'", output); outputString = output.toString(); + logger.debug("Decoded output string '{}'", outputString); } //Strips invalid characters from the keyword and creates the grid protected void setKeyword(String keyword) throws InvalidKeywordException{ //Ensure the keyword isn't null if(keyword == null){ - throw new NullPointerException("Keyword cannot be null"); + throw new InvalidKeywordException("Keyword cannot be null"); } logger.debug("Original keyword {}", keyword); //Strip all non-letter characters and change them to uppercase - this.keyword = keyword.toUpperCase().replaceAll("[^A-Z]", ""); + keyword = keyword.toUpperCase().replaceAll("[^A-Z]", ""); + this.keyword = keyword; logger.debug("Cleaned keyword {}", keyword); @@ -362,15 +370,14 @@ public class Columnar{ throw new InvalidCharacterException("Character to add must be a letter"); } - logger.debug("Setting character to add"); + logger.debug("Setting character to add {}", characterToAdd); if(!preserveCapitals){ - this.characterToAdd = Character.toUpperCase(characterToAdd); - } - else{ - this.characterToAdd = characterToAdd; + characterToAdd = Character.toUpperCase(characterToAdd); } + this.characterToAdd = characterToAdd; + logger.debug("Character to add for padding {}", characterToAdd); } //Returns a list of integers that represents the location of the characters of the keyword in alphabetic order @@ -409,7 +416,7 @@ public class Columnar{ } //Returning the locations - logger.debug("Array of keyword letters {}", orderedLocations); + logger.debug("Array of keyword letters {}", originalOrder); return originalOrder; } //Rearanges the grid based on the list of numbers given diff --git a/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Hill.java b/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Hill.java index ef48317..988c0d9 100644 --- a/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Hill.java +++ b/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Hill.java @@ -1,12 +1,15 @@ //CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/polySubstitution/Hill.java //Mattrixwv // Created: 01-31-22 -//Modified: 02-17-22 +//Modified: 04-27-23 package com.mattrixwv.cipherstream.polysubstitution; import java.util.ArrayList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.mattrixwv.cipherstream.exceptions.InvalidCharacterException; import com.mattrixwv.cipherstream.exceptions.InvalidInputException; import com.mattrixwv.cipherstream.exceptions.InvalidKeyException; @@ -16,28 +19,34 @@ import com.mattrixwv.matrix.exceptions.InvalidScalarException; public class Hill{ - private boolean preserveCapitals; - private boolean preserveWhitespace; - private boolean preserveSymbols; - private boolean removePadding; - private String inputString; - private String outputString; - private char characterToAdd; - private int charsAdded; - private ModMatrix key; + protected static Logger logger = LoggerFactory.getLogger(Hill.class); + + + protected boolean preserveCapitals; + protected boolean preserveWhitespace; + protected boolean preserveSymbols; + protected String inputString; + protected String outputString; + protected char characterToAdd; + protected ModMatrix key; + + protected void setKey(ModMatrix key) throws InvalidKeyException{ + logger.debug("Setting key"); - private void setKey(ModMatrix key) throws InvalidKeyException{ //Make sure the mod is correct + logger.debug("Testing mod"); if(key.getMod() != 26){ throw new InvalidKeyException("This algorithm uses the english alphabet, so the mod for the key must be 26"); } //Make sure the matrix is square + logger.debug("Testing square"); if(!key.isSquare()){ throw new InvalidKeyException("The key must be a square matrix"); } //Make sure the matrix is invertable + logger.debug("Testing invertable"); try{ key.inverse(); } @@ -46,25 +55,37 @@ public class Hill{ } //Set the key + logger.debug("key = {}", key); this.key = new ModMatrix(key); } - private void setInputString(String inputString) throws InvalidInputException{ - //Remove anything that needs removed + protected void setInputStringEncode(String inputString) throws InvalidInputException{ + logger.debug("Setting input string for encoding"); + if(inputString == null){ throw new InvalidInputException("Input must not be null"); } + logger.debug("Original input string '{}'", inputString); + + //Remove anything that needs removed if(!preserveCapitals){ + logger.debug("Removing capitals"); + inputString = inputString.toUpperCase(); } if(!preserveWhitespace){ + logger.debug("Removing whitespace"); + inputString = inputString.replaceAll("[\\s]", ""); } if(!preserveSymbols){ + logger.debug("Removing symbols"); + inputString = inputString.replaceAll("[^a-zA-Z\\s]", ""); } //Make sure the input is correct length + logger.debug("Checking length"); this.inputString = inputString; int cleanLength = getCleanInputString().length(); int charsToAdd = (cleanLength % key.getNumRows()); @@ -73,12 +94,13 @@ public class Hill{ if(charsToAdd != 0){ charsToAdd = key.getNumRows() - charsToAdd; } + logger.debug("Adding {} characters", charsToAdd); for(int cnt = 0;cnt < charsToAdd;++cnt){ inputStringBuilder.append(characterToAdd); } - charsAdded = charsToAdd; inputString = inputStringBuilder.toString(); + logger.debug("Cleaned input string '{}'", inputString); this.inputString = inputString; //Make sure the input isn't blank @@ -86,10 +108,51 @@ public class Hill{ throw new InvalidInputException("Input cannot be blank"); } } - private String getCleanInputString(){ - return inputString.toUpperCase().replaceAll("[^A-Z]", ""); + protected void setInputStringDecode(String inputString) throws InvalidInputException{ + logger.debug("Setting input string for decoding"); + + if(inputString == null){ + throw new InvalidInputException("Input must not be null"); + } + + logger.debug("Original input string '{}'", inputString); + + //Remove anything that needs removed + if(!preserveCapitals){ + logger.debug("Removing capitals"); + + inputString = inputString.toUpperCase(); + } + if(!preserveWhitespace){ + logger.debug("Removing whitespace"); + + inputString = inputString.replaceAll("[\\s]", ""); + } + if(!preserveSymbols){ + logger.debug("Removing symbols"); + + inputString = inputString.replaceAll("[^a-zA-Z\\s]", ""); + } + + logger.debug("Cleaned input string '{}'", inputString); + this.inputString = inputString; + + logger.debug("Checking length"); + if(getCleanInputString().isBlank() || ((getCleanInputString().length() % key.getNumRows()) != 0)){ + throw new InvalidInputException("Length of input string must be a multiple of the number of rows in the key"); + } } - private void setCharacterToAdd(char characterToAdd) throws InvalidCharacterException{ + protected String getCleanInputString(){ + logger.debug("Cleaning inputString"); + + String cleanInputString = inputString.toUpperCase().replaceAll("[^A-Z]", ""); + logger.debug("Clean input string '{}'", cleanInputString); + + return cleanInputString; + } + protected void setCharacterToAdd(char characterToAdd) throws InvalidCharacterException{ + logger.debug("Setting character to add {}", characterToAdd); + //Make sure the character is a letter if(!Character.isAlphabetic(characterToAdd)){ throw new InvalidCharacterException("Character to add must be a letter"); @@ -97,37 +160,45 @@ public class Hill{ //Save the characterToAdd if(!preserveCapitals){ - this.characterToAdd = Character.toUpperCase(characterToAdd); - } - else{ - this.characterToAdd = characterToAdd; + logger.debug("Removing capitals"); + + characterToAdd = Character.toUpperCase(characterToAdd); } + + logger.debug("Cleaned character {}", characterToAdd); + this.characterToAdd = characterToAdd; } - private String polishOutputString(){ + protected String polishOutputString(){ + logger.debug("Polishing output string"); + //Add the extra characters back to the output and remove the added characters int outputCnt = 0; StringBuilder outputBuilder = new StringBuilder(); for(char ch : inputString.toCharArray()){ + logger.debug("Current char {}", ch); if(Character.isUpperCase(ch)){ + logger.debug("Uppercase"); + outputBuilder.append(Character.toUpperCase(outputString.charAt(outputCnt++))); } else if(Character.isLowerCase(ch)){ + logger.debug("Lowercase"); + outputBuilder.append(Character.toLowerCase(outputString.charAt(outputCnt++))); } else{ + logger.debug("Symbol"); + outputBuilder.append(ch); } } - if(removePadding){ - String tempString = outputBuilder.substring(0, outputBuilder.length() - charsAdded); - outputBuilder = new StringBuilder(); - outputBuilder.append(tempString); - } - + logger.debug("Polished string '{}'", outputBuilder.toString()); return outputBuilder.toString(); } - private ArrayList getInputVectors(){ + protected ArrayList getInputVectors(){ + logger.debug("Generating input vectors"); + //Get the number of columns in the key int numCols = key.getNumCols(); @@ -139,6 +210,7 @@ public class Hill{ for(int cnt = 0;cnt < cleanInput.length();cnt += numCols){ String subString = cleanInput.substring(cnt, cnt + numCols); int[] grid = new int[numCols]; + logger.debug("Current substring '{}'", subString); //Subtract 65 from each character so that A=0, B=1, ... for(int subCnt = 0;subCnt < subString.length();++subCnt){ @@ -148,6 +220,7 @@ public class Hill{ //Create a vector from the new values ModMatrix vector = new ModMatrix(26); vector.addCol(grid); + logger.debug("Current vector {}", vector); //Add the vector to the array vectors.add(vector); @@ -156,10 +229,14 @@ public class Hill{ //Return the array of vectors return vectors; } - private String getOutputFromVectors(ArrayList outputVectors){ + protected String getOutputFromVectors(ArrayList outputVectors){ + logger.debug("Turning vectors into a string"); + //Go through each element in the vector StringBuilder outputBuilder = new StringBuilder(); for(ModMatrix vector : outputVectors){ + logger.debug("Current vector {}", vector); + //Add 65 to each element and add it to the string for(int cnt = 0;cnt < vector.getNumRows();++cnt){ outputBuilder.append((char)(vector.get(cnt, 0) + 65)); @@ -167,16 +244,24 @@ public class Hill{ } //Return the new string - return outputBuilder.toString(); + String convertedString = outputBuilder.toString(); + logger.debug("Converted string '{}'", convertedString); + return convertedString; } - private String encode(){ + protected void encode(){ + logger.debug("Encoding"); + //Get an array of vectors that we are going to encode ArrayList inputVectors = getInputVectors(); //Multiply the key by each vector and add the result to a new vector + logger.debug("Multiplying vectors"); ArrayList outputVectors = new ArrayList<>(); for(ModMatrix inputVector : inputVectors){ + logger.debug("Current input vector {}", inputVector); ModMatrix outputVector = key.multiply(inputVector); + + logger.debug("Multiplied vector {}", outputVector); outputVectors.add(outputVector); } @@ -185,19 +270,23 @@ public class Hill{ //Add the extra characters back to the output and remove the added characters outputString = polishOutputString(); - - //Save the output - return outputString; } - private String decode(){ + protected void decode(){ + logger.debug("Decoding"); + //Get the array of vectors that we are going to decode ArrayList inputVectors = getInputVectors(); //Multiply the inverse of the key by each vector and add the result to a new vector + logger.debug("Getting inverse of key"); ModMatrix inverseKey = key.inverse(); + logger.debug("Inverse of key {}", inverseKey); ArrayList outputVectors = new ArrayList<>(); for(ModMatrix inputVector : inputVectors){ + logger.debug("Current input vector {}", inputVector); ModMatrix outputVector = inverseKey.multiply(inputVector); + + logger.debug("Multiplied vector {}", outputVector); outputVectors.add(outputVector); } @@ -206,32 +295,26 @@ public class Hill{ //Add the extra characters back to the output and remove the added characters outputString = polishOutputString(); - - //Save the output - return outputString; } public Hill() throws InvalidCharacterException{ preserveCapitals = false; preserveWhitespace = false; preserveSymbols = false; - removePadding = false; setCharacterToAdd('x'); reset(); } - public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, boolean removePadding) throws InvalidCharacterException{ + public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{ this.preserveCapitals = preserveCapitals; this.preserveWhitespace = preserveWhitespace; this.preserveSymbols = preserveSymbols; - this.removePadding = removePadding; setCharacterToAdd('x'); reset(); } - public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, boolean removePadding, char characterToAdd) throws InvalidCharacterException{ + public Hill(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, char characterToAdd) throws InvalidCharacterException{ this.preserveCapitals = preserveCapitals; this.preserveWhitespace = preserveWhitespace; this.preserveSymbols = preserveSymbols; - this.removePadding = removePadding; setCharacterToAdd(characterToAdd); reset(); } @@ -241,22 +324,25 @@ public class Hill{ } public String encode(ModMatrix key, String inputString) throws InvalidKeyException, InvalidInputException{ setKey(key); - setInputString(inputString); - return encode(); + setInputStringEncode(inputString); + encode(); + return outputString; } public String decode(int[][] key, String inputString) throws InvalidKeyException, InvalidInputException{ return decode(new ModMatrix(key, 26), inputString); } public String decode(ModMatrix key, String inputString) throws InvalidKeyException, InvalidInputException{ setKey(key); - setInputString(inputString); - return decode(); + setInputStringDecode(inputString); + decode(); + return outputString; } public void reset(){ + logger.debug("Resetting fields"); + inputString = ""; outputString = ""; key = new ModMatrix(26); - charsAdded = 0; } public String getInputString(){ return inputString; diff --git a/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Morse.java b/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Morse.java index 0ca9e5a..32a6def 100644 --- a/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Morse.java +++ b/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Morse.java @@ -6,6 +6,7 @@ package com.mattrixwv.cipherstream.polysubstitution; public class Morse{ + //TODO: This needs updated to match new standards //Holds the Morse representation of the alphanumeric characters private static final String[] code = { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", //A-L diff --git a/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Playfair.java b/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Playfair.java index fed1fdc..2ae2fca 100644 --- a/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Playfair.java +++ b/src/main/java/com/mattrixwv/cipherstream/polysubstitution/Playfair.java @@ -1,7 +1,7 @@ //CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/polySubstitution/Playfair.java //Matthew Ellison // Created: 07-30-21 -//Modified: 07-09-22 +//Modified: 04-28-23 package com.mattrixwv.cipherstream.polysubstitution; @@ -12,15 +12,16 @@ import org.slf4j.LoggerFactory; import com.mattrixwv.cipherstream.exceptions.InvalidCharacterException; import com.mattrixwv.cipherstream.exceptions.InvalidInputException; +import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; public class Playfair{ - private static final Logger logger = LoggerFactory.getLogger(Playfair.class); + protected static Logger logger = LoggerFactory.getLogger(Playfair.class); //A class representing the location of a character in the grid - private class CharLocation{ - private int x; - private int y; + protected class CharLocation{ + protected int x; + protected int y; public CharLocation(int x, int y){ this.x = x; this.y = y; @@ -34,23 +35,122 @@ public class Playfair{ } //Fields - private boolean preserveCapitals; //Whether to respect captials in the output string - private boolean preserveWhitespace; //Whether to respect whitespace in the output string - private boolean preserveSymbols; //Whether to respect symbols in the output string - private char replaced; //The letter that will need to be replaced in the grid and any input string or keyword - private char replacer; //The letter that replaced replaced in the input string or keyword - private char doubled; //The letter that will be placed between double letters in the input string if necessary or to make the string length even - private String inputString; //The message that needs to be encoded/decoded - private String outputString; //The encoded/decoded message - private String keyword; //The keyword used to create the grid - private char[][] grid; //The grid used to encode/decode the message + protected boolean preserveCapitals; //Whether to respect captials in the output string + protected boolean preserveWhitespace; //Whether to respect whitespace in the output string + protected boolean preserveSymbols; //Whether to respect symbols in the output string + protected char replaced; //The letter that will need to be replaced in the grid and any input string or keyword + protected char replacer; //The letter that replaced replaced in the input string or keyword + protected char doubled; //The letter that will be placed between double letters in the input string if necessary or to make the string length even + protected String inputString; //The message that needs to be encoded/decoded + protected String outputString; //The encoded/decoded message + protected String keyword; //The keyword used to create the grid + protected char[][] grid; //The grid used to encode/decode the message + + + //Set the doubled character + protected void setDoubled(char doubled) throws InvalidCharacterException{ + logger.debug("Setting doubled"); + logger.debug("Original character {}", doubled); + + //Make sure the character is a letter + logger.debug("Checking letter"); + if(!Character.isAlphabetic(doubled)){ + throw new InvalidCharacterException("The double letter replacement must be a letter"); + } + + //Make sure the 2 replacers are the same + logger.debug("Checking same as replacer"); + if(doubled == replacer){ + throw new InvalidCharacterException("The double letter replacement cannot be the same as the regular replacer"); + } + + //Make sure the double letter replacement isn't the same as the letter being replaced + logger.debug("Checking same as replaced"); + if(doubled == replaced){ + throw new InvalidCharacterException("The double letter replacement cannot be the same as the letter replaced"); + } + + if(!preserveCapitals){ + logger.debug("Removing capitals"); + + doubled = Character.toUpperCase(doubled); + } + + logger.debug("Setting doubled to {}", doubled); + this.doubled = doubled; + } + //Set the replacer character + protected void setReplacer(char replacer) throws InvalidCharacterException{ + logger.debug("Setting replacer"); + logger.debug("Original character {}", replacer); + + //Make sure the character is a letter + logger.debug("Checking letter"); + if(!Character.isAlphabetic(replacer)){ + throw new InvalidCharacterException("The replacer must be a letter"); + } + + //Make sure the character isn't the same as what it is supposed to replace + logger.debug("Checking same as replaced"); + if(replacer == replaced){ + throw new InvalidCharacterException("The replacer cannot be the same letter as what it is replacing"); + } + + //Make sure the replacer isn't the same as the double letter replacer + logger.debug("Checking same as doubled"); + if(replacer == doubled){ + throw new InvalidCharacterException("The replacer cannot be the same as the double letter replacer"); + } + + if(!preserveCapitals){ + logger.debug("Removing capitals"); + + replacer = Character.toUpperCase(replacer); + } + + logger.debug("Setting replacer to {}", replacer); + this.replacer = replacer; + } + //Set the replaced character + protected void setReplaced(char replaced) throws InvalidCharacterException{ + logger.debug("Setting replaced"); + logger.debug("Original character {}", replaced); + + //Make sure the character is a letter + logger.debug("Checking letter"); + if(!Character.isAlphabetic(replaced)){ + throw new InvalidCharacterException("The replaced character must be a letter"); + } + + //Make sure the character isn't the same as what is replacing it + logger.debug("Checking same as replacer"); + if(replaced == replacer){ + throw new InvalidCharacterException("The replaced letter cannot be the same as the replacing letter"); + } + + //Make sure the replacer isn't the same as the double letter replacer + logger.debug("Checking same as doubled"); + if(replaced == doubled){ + throw new InvalidCharacterException("The replaced letter cannot be the same as the replacing letter"); + } + + if(!preserveCapitals){ + logger.debug("Removing capitals"); + + replaced = Character.toUpperCase(replaced); + } + + logger.debug("Setting replaced to {}", replaced); + this.replaced = replaced; + } //Create the grid from the keyword - private void createGrid(){ + protected void createGrid(){ logger.debug("Creating grid from keyword"); for(int row = 0;row < 5;++row){ for(int col = 0;col < 5;++col){ char letter = keyword.charAt((5 * row) + col); + logger.debug("Letter {} going to position [{}] [{}]", letter, row, col); grid[row][col] = letter; } } @@ -58,10 +158,12 @@ public class Playfair{ logger.debug("Grid\n{}", getGrid()); } //Strips invalid characters from the string that needs encoded/decoded - private void setInputString(String inputString, boolean encoding) throws InvalidCharacterException, InvalidInputException{ + protected void setInputString(String inputString, boolean encoding) throws InvalidCharacterException, InvalidInputException{ + logger.debug("Setting input string"); + //Make sure the input string is not null if(inputString == null){ - throw new NullPointerException("The input string cannot be null"); + throw new InvalidInputException("The input string cannot be null"); } logger.debug("Original input string {}", inputString); @@ -83,18 +185,14 @@ public class Playfair{ inputString = inputString.replaceAll("[^a-zA-Z\\s]", ""); } - //Make replace all of the replacers with replaced - logger.debug("Replacing all {} with {}", replaced, replacer); - inputString = inputString.replace(Character.toString(replaced), Character.toString(replacer)); - //If there is nothing in the input string throw an exception if(inputString.isBlank()){ - throw new InvalidCharacterException("The input string cannot be blank"); + throw new InvalidInputException("The input string cannot be blank"); } //If this is encoding parse it and clean up any problems if(encoding){ - setEncodingInputString(inputString); + setInputStringEncode(inputString); } //If this is decoding just add it without parsing it else{ @@ -105,20 +203,28 @@ public class Playfair{ logger.debug("Clean input string '{}'", inputString); this.inputString = inputString; + + if((getPreparedInputString().length() % 2) == 1){ + throw new InvalidInputException("Input length must be even"); + } } - if(this.inputString.isBlank() || getPreparedInputString().isBlank()){ + if(getPreparedInputString().isBlank()){ throw new InvalidInputException("Input must have at least 1 letter"); } } - private void setEncodingInputString(String inputString){ + protected void setInputStringEncode(String inputString){ + logger.debug("Cleaning up input string for encoding"); + //Replace characters that need replaced + logger.debug("Replacing all {} with {}", replaced, replacer); inputString = inputString.replace(Character.toString(replaced), Character.toString(replacer)); //Check if there are any doubled characters StringBuilder cleanInput = new StringBuilder(); int letterCount = 0; for(int cnt = 0;cnt < inputString.length();){ + logger.debug("Starting at character {}", cnt); //Advance until you find a letter, saving the input for inclusion StringBuilder prepend = new StringBuilder(); while((cnt < inputString.length()) && !Character.isAlphabetic(inputString.charAt(cnt))){ @@ -151,6 +257,7 @@ public class Playfair{ } //Add all of the gathered input to the cleaned up input + logger.debug("Adding to clean input: {} {} {} {}", prepend, firstLetter, middle, secondLetter); cleanInput.append(prepend); cleanInput.append(firstLetter); cleanInput.append(middle); @@ -160,7 +267,9 @@ public class Playfair{ } //Check if there are an odd number of characters + logger.debug("Checking odd characters"); if((letterCount % 2) == 1){ + logger.debug("Adding final character to make even"); int lastLetterLocation = cleanInput.length() - 1; while(!Character.isAlphabetic(cleanInput.charAt(lastLetterLocation))){ --lastLetterLocation; @@ -173,11 +282,11 @@ public class Playfair{ } } - logger.debug("Cleaned input string '{}'", cleanInput); this.inputString = cleanInput.toString(); + logger.debug("Cleaned input string '{}'", this.inputString); } //Returns the input string ready for encoding - private String getPreparedInputString(){ + protected String getPreparedInputString(){ logger.debug("Getting input string ready for encoding"); String cleanString = inputString.toUpperCase(); @@ -188,9 +297,11 @@ public class Playfair{ return cleanString; } //Strips invalid characters from the keyword and creates the grid - private void setKeyword(String keyword){ + protected void setKeyword(String keyword) throws InvalidKeywordException{ + logger.debug("Setting keyword"); + if(keyword == null){ - throw new NullPointerException("Keyword cannot be null"); + throw new InvalidKeywordException("Keyword cannot be null"); } logger.debug("Original keyword {}", keyword); @@ -209,19 +320,20 @@ public class Playfair{ //Replace all replaced characters logger.debug("Replacing {} with {}", replaced, replacer); - keyword = keyword.replaceAll(Character.toString(replaced), Character.toString(replacer)); + keyword = keyword.replaceAll(Character.toString(Character.toUpperCase(replaced)), Character.toString(Character.toUpperCase(replacer))); //Remove all duplicate chatacters - logger.debug("Removing duplicated characters"); + logger.debug("Removing duplicate characters"); StringBuilder uniqueKey = new StringBuilder(); keyword.chars().distinct().forEach(c -> uniqueKey.append((char)c)); this.keyword = uniqueKey.toString(); + logger.debug("Cleaned keyword {}", this.keyword); //Create the grid from the sanitized keyword createGrid(); } //Returns the location of the given character in the grid - private CharLocation findChar(char letter) throws InvalidInputException{ + protected CharLocation findChar(char letter) throws InvalidInputException{ logger.debug("Finding character in grid {}", letter); for(int row = 0;row < grid.length;++row){ @@ -238,7 +350,7 @@ public class Playfair{ throw new InvalidInputException("The character '" + letter + "' was not found in the grid"); } //Returns the location in the grid of x and y, adjusting for out of bounds - private char getGridChar(int x, int y){ + protected char getGridChar(int x, int y){ logger.debug("Getting character from grid[{}][{}]", x, y); if(x < 0){ @@ -253,7 +365,7 @@ public class Playfair{ return letter; } //Adds characters that aren't letters to the output - private void addCharactersToCleanString(String cleanString){ + protected void addCharactersToCleanString(String cleanString){ logger.debug("Formatting output string"); int outputCnt = 0; @@ -262,27 +374,27 @@ public class Playfair{ logger.debug("Working character {}", inputString.charAt(inputCnt)); if(Character.isUpperCase(inputString.charAt(inputCnt))){ - logger.debug("Adjusting uppercase"); + logger.debug("Appending uppercase"); fullOutput.append(cleanString.charAt(outputCnt++)); } else if(Character.isLowerCase(inputString.charAt(inputCnt))){ - logger.debug("Adjusting lowercase"); + logger.debug("Appending lowercase"); fullOutput.append(Character.toLowerCase(cleanString.charAt(outputCnt++))); } else{ - logger.debug("Inserting symbol"); + logger.debug("Appending symbol"); fullOutput.append(inputString.charAt(inputCnt)); } } - logger.debug("Formatted output '{}'", fullOutput); outputString = fullOutput.toString(); + logger.debug("Formatted output '{}'", outputString); } //Encodes inputString using the Playfair cipher and stores the result in outputString - private String encode() throws InvalidInputException{ + protected void encode() throws InvalidInputException{ logger.debug("Encoding"); StringBuilder output = new StringBuilder(); @@ -324,12 +436,9 @@ public class Playfair{ //Add other characters to the output string addCharactersToCleanString(output.toString()); - - //Return the output string - return outputString; } //Decodes inputString using the Playfair cipher and stores the result in outputString - private String decode() throws InvalidInputException{ + protected void decode() throws InvalidInputException{ logger.debug("Decoding"); StringBuilder output = new StringBuilder(); @@ -348,17 +457,17 @@ public class Playfair{ //Decode the letters if(firstLocation.getX() == secondLocation.getX()){ - logger.debug("Decoding row"); + logger.debug("Row decoding"); firstLetter = getGridChar(firstLocation.getX(), firstLocation.getY() - 1); secondLetter = getGridChar(secondLocation.getX(), secondLocation.getY() - 1); } else if(firstLocation.getY() == secondLocation.getY()){ - logger.debug("Decoding col"); + logger.debug("Column decoding"); firstLetter = getGridChar(firstLocation.getX() - 1, firstLocation.getY()); secondLetter = getGridChar(secondLocation.getX() - 1, secondLocation.getY()); } else{ - logger.debug("Decoding corners"); + logger.debug("Corner decoding"); firstLetter = getGridChar(firstLocation.getX(), secondLocation.getY()); secondLetter = getGridChar(secondLocation.getX(), firstLocation.getY()); } @@ -371,9 +480,6 @@ public class Playfair{ //Add other characters to the output string addCharactersToCleanString(output.toString()); - - //Return the output string - return outputString; } public Playfair() throws InvalidCharacterException{ @@ -381,18 +487,18 @@ public class Playfair{ preserveCapitals = false; preserveWhitespace = false; preserveSymbols = false; - setReplaced('J'); - setReplacer('I'); - setDoubled('X'); + setReplaced('j'); + setReplacer('i'); + setDoubled('x'); } public Playfair(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols) throws InvalidCharacterException{ reset(); this.preserveCapitals = preserveCapitals; this.preserveWhitespace = preserveWhitespace; this.preserveSymbols = preserveSymbols; - setReplaced('J'); - setReplacer('I'); - setDoubled('X'); + setReplaced('j'); + setReplacer('i'); + setDoubled('x'); } public Playfair(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols, char replaced, char replacer, char doubled) throws InvalidCharacterException{ reset(); @@ -408,14 +514,16 @@ public class Playfair{ reset(); setKeyword(keyword); setInputString(input, true); - return encode(); + encode(); + return outputString; } //Sets the keyword and inputString and decodes the message public String decode(String keyword, String input) throws InvalidCharacterException, InvalidInputException{ reset(); setKeyword(keyword); setInputString(input, false); - return decode(); + decode(); + return outputString; } //Makes sure all variables are empty @@ -431,64 +539,12 @@ public class Playfair{ public char getReplaced(){ return replaced; } - public void setReplaced(char replaced) throws InvalidCharacterException{ - if(!Character.isAlphabetic(replaced)){ - throw new InvalidCharacterException("The replaced character must be a letter"); - } - - if(replaced == replacer){ - throw new InvalidCharacterException("The replaced letter cannot be the same as the replacing letter"); - } - - if(replaced == doubled){ - throw new InvalidCharacterException("The replaced letter cannot be the same as the replacing letter"); - } - - this.replaced = Character.toUpperCase(replaced); - } public char getReplacer(){ return replacer; } - public void setReplacer(char replacer) throws InvalidCharacterException{ - //Make sure the character is a letter - if(!Character.isAlphabetic(replacer)){ - throw new InvalidCharacterException("The replacer must be a letter"); - - } - - //Make sure the character isn't the same as what it is supposed to replace - if(replacer == replaced){ - throw new InvalidCharacterException("The replacer cannot be the same letter as what it is replacing"); - } - - //Make sure the replacer isn't the same as the double letter replacer - if(replacer == doubled){ - throw new InvalidCharacterException("The replacer cannot be the same as the double letter replacer"); - } - - this.replacer = Character.toUpperCase(replacer); - } public char getDoubled(){ return doubled; } - public void setDoubled(char doubled) throws InvalidCharacterException{ - //Make sure the character is a letter - if(!Character.isAlphabetic(doubled)){ - throw new InvalidCharacterException("The double letter replacement must be a letter"); - } - - //Make sure the 2 replacers are the same - if(doubled == replacer){ - throw new InvalidCharacterException("The double letter replacement cannot be the same as the regular replacer"); - } - - //Make sure the double letter replacement isn't the same as the letter being replaced - if(doubled == replaced){ - throw new InvalidCharacterException("The double letter replacement cannot be the same as the letter replaced"); - } - - this.doubled = Character.toUpperCase(doubled); - } public String getKeyword(){ return keyword; } diff --git a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBaconian.java b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBaconian.java index 85dc491..0a97244 100644 --- a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBaconian.java +++ b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBaconian.java @@ -96,7 +96,7 @@ public class TestBaconian{ assertThrows(InvalidInputException.class, () -> { cipher.setInputStringEncode(""); - }, "Input must contain at least 1 letter"); + }); assertEquals("", cipher.inputString); verify(logger, times(1)).debug("Setting input string for encoding '{}'", ""); @@ -112,7 +112,7 @@ public class TestBaconian{ assertThrows(InvalidInputException.class, () -> { cipher.setInputStringEncode(null); - }, "Input cannot be null"); + }); assertEquals("", cipher.inputString); verify(logger, never()).debug(anyString()); @@ -159,7 +159,7 @@ public class TestBaconian{ assertThrows(InvalidCharacterException.class, () -> { cipher.setInputStringDecode("a"); - }, "All Baconian letters contain exactly 5 characters: a"); + }); assertEquals("", cipher.inputString); verify(logger, times(1)).debug("Setting input string for decoding '{}'", "a"); @@ -178,7 +178,7 @@ public class TestBaconian{ assertThrows(InvalidCharacterException.class, () -> { cipher.setInputStringDecode("ccccc"); - }, "Baconian letters contain only a's and b's: ccccc"); + }); assertEquals("", cipher.inputString); verify(logger, times(1)).debug("Setting input string for decoding '{}'", "ccccc"); @@ -197,7 +197,7 @@ public class TestBaconian{ assertThrows(InvalidInputException.class, () -> { cipher.setInputStringDecode(""); - }, "Input cannot be empty"); + }); assertEquals("", cipher.inputString); verify(logger, never()).debug("Setting input string for decoding '{}'", ""); @@ -216,7 +216,7 @@ public class TestBaconian{ assertThrows(InvalidInputException.class, () -> { cipher.setInputStringDecode(null); - }, "Input cannot be null"); + }); assertEquals("", cipher.inputString); verify(logger, never()).debug(anyString()); diff --git a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBaseX.java b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBaseX.java index 81ec8b6..86f48a8 100644 --- a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBaseX.java +++ b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBaseX.java @@ -76,7 +76,7 @@ public class TestBaseX{ public void testSetInputStringEncode_blank(){ assertThrows(InvalidInputException.class, () -> { cipher.setInputStringEncode(""); - }, "Input must contain at least 1 letter"); + }); assertEquals("", cipher.inputString); verify(logger, times(1)).debug("Setting input string for encoding '{}'", ""); @@ -88,7 +88,7 @@ public class TestBaseX{ public void testSetInputStringEncode_null(){ assertThrows(InvalidInputException.class, () -> { cipher.setInputStringEncode(null); - }, "Input cannot be null"); + }); assertEquals("", cipher.inputString); verify(logger, never()).debug("Setting input string for encoding '{}'", decodedString); @@ -116,7 +116,7 @@ public class TestBaseX{ assertThrows(InvalidCharacterException.class, () -> { cipher.setInputStringDecode("G"); - }, "inputString cannot contain anything except numbers 0-15, and whitespace"); + }); assertEquals("", cipher.inputString); verify(logger, times(1)).debug("Setting input string for decoding '{}'", "G"); @@ -132,7 +132,7 @@ public class TestBaseX{ assertThrows(InvalidInputException.class, () -> { cipher.setInputStringDecode(""); - }, "Input must contain at least 1 letter"); + }); assertEquals("", cipher.inputString); verify(logger, times(1)).debug("Setting input string for decoding '{}'", ""); @@ -148,7 +148,7 @@ public class TestBaseX{ assertThrows(InvalidInputException.class, () -> { cipher.setInputStringDecode(null); - }, "Input cannot be null"); + }); assertEquals("", cipher.inputString); verify(logger, never()).debug(eq("Setting input string for decoding '{}'"), anyString()); @@ -172,7 +172,7 @@ public class TestBaseX{ public void testSetBase_min(){ assertThrows(InvalidBaseException.class, () -> { cipher.setBase(Character.MIN_RADIX - 1); - }, "Base cannot be less than " + Character.MIN_RADIX); + }); assertEquals(2, cipher.base); verify(logger, never()).debug(eq("Setting base {}"), anyInt()); @@ -184,7 +184,7 @@ public class TestBaseX{ public void testSetBase_max(){ assertThrows(InvalidBaseException.class, () -> { cipher.setBase(Character.MAX_RADIX + 1); - }, "Base cannot be larger than " + Character.MAX_RADIX); + }); assertEquals(2, cipher.base); verify(logger, never()).debug(eq("Setting base {}"), anyInt()); @@ -227,7 +227,7 @@ public class TestBaseX{ assertThrows(InvalidCharacterException.class, () -> { cipher.decode(); - }, "The base 16 string FFF is not a valid ASCII character"); + }); verify(logger, times(1)).debug("Decoding"); verify(logger, times(1)).debug("Current number {}", "FFF"); diff --git a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBeaufort.java b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBeaufort.java index 2d90e7b..38f15c4 100644 --- a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBeaufort.java +++ b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestBeaufort.java @@ -208,7 +208,7 @@ public class TestBeaufort{ assertThrows(InvalidInputException.class, () -> { cipher.setInputString(""); - }, "Input must contain at least 1 letter"); + }); assertEquals("", cipher.inputString); verify(logger, times(1)).debug("Original input string '{}'", ""); @@ -224,7 +224,7 @@ public class TestBeaufort{ public void testSetInputString_null(){ assertThrows(InvalidInputException.class, () -> { cipher.setInputString(null); - }, "Input must conatin at least 1 letter"); + }); assertEquals("", cipher.inputString); verify(logger, never()).debug(eq("Original input string '{}'"), anyString()); @@ -266,7 +266,7 @@ public class TestBeaufort{ public void testSetKeyword_blank(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword(""); - }, "Keyword must contain at least 2 letters"); + }); assertEquals("", cipher.keyword); verify(logger, times(1)).debug("Original keyword '{}'", ""); @@ -281,7 +281,7 @@ public class TestBeaufort{ public void testSetKeyword_short(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword("A"); - }, "Keyword must contain at least 2 letters"); + }); assertEquals("A", cipher.keyword); verify(logger, times(1)).debug("Original keyword '{}'", "A"); @@ -296,7 +296,7 @@ public class TestBeaufort{ public void testSetKeyword_null(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword(null); - }, "Keyword cannot be null"); + }); assertEquals("", cipher.keyword); verify(logger, never()).debug(eq("Original keyword '{}'"), anyString()); diff --git a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestCaesar.java b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestCaesar.java index cf2ac72..de5f409 100644 --- a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestCaesar.java +++ b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestCaesar.java @@ -190,7 +190,7 @@ public class TestCaesar{ assertThrows(InvalidInputException.class, () -> { cipher.setInputString(""); - }, "Input must contain at least 1 letter"); + }); assertEquals("", cipher.inputString); verify(logger, times(1)).debug("Original input string '{}'", ""); @@ -208,7 +208,7 @@ public class TestCaesar{ assertThrows(InvalidInputException.class, () -> { cipher.setInputString(null); - }, "Input must contain at least 1 letter"); + }); assertEquals("", cipher.inputString); verify(logger, never()).debug("Original input string '{}'", ""); diff --git a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestOneTimePad.java b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestOneTimePad.java index c8a3455..8109616 100644 --- a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestOneTimePad.java +++ b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestOneTimePad.java @@ -137,7 +137,7 @@ public class TestOneTimePad{ assertThrows(InvalidKeywordException.class, () -> { cipher.encode("keyword", decodedString); - }, "Key must be at least as long as the input"); + }); assertEquals("", cipher.inputString); assertEquals("", cipher.keyword); diff --git a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestPorta.java b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestPorta.java index c25510e..75cf9f1 100644 --- a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestPorta.java +++ b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestPorta.java @@ -107,7 +107,7 @@ public class TestPorta{ public void testSetKeyword_blank(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword(""); - }, "Keyword must contain at least 2 letters"); + }); assertEquals("", cipher.keyword); verify(logger, times(1)).debug("Original keyword '{}'", ""); @@ -120,7 +120,7 @@ public class TestPorta{ public void testSetKeyword_short(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword("a"); - }, "Keyword must contain at least 2 letters"); + }); assertEquals("A", cipher.keyword); verify(logger, times(1)).debug("Original keyword '{}'", "a"); @@ -133,7 +133,7 @@ public class TestPorta{ public void testSetKeyword_null(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword(null); - }, "Keyword cannot be null"); + }); assertEquals("", cipher.keyword); verify(logger, never()).debug(anyString()); @@ -223,7 +223,7 @@ public class TestPorta{ assertThrows(InvalidInputException.class, () -> { cipher.setInputString(""); - }, "Input must contain at least 1 letter"); + }); assertEquals("", cipher.inputString); verify(logger, times(1)).debug("Original input string {}", ""); @@ -241,7 +241,7 @@ public class TestPorta{ assertThrows(InvalidInputException.class, () -> { cipher.setInputString(null); - }, "Input cannot be null"); + }); assertEquals("", cipher.inputString); verify(logger, never()).debug(anyString(), anyString()); diff --git a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestSubstitution.java b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestSubstitution.java index 3dee32d..a53e5ac 100644 --- a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestSubstitution.java +++ b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestSubstitution.java @@ -172,7 +172,7 @@ public class TestSubstitution{ public void testSetKey_invalidLength(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword("AB"); - }, "The key must contain all letters and can contain all numbers"); + }); assertEquals("", cipher.keyword); verify(logger, times(1)).debug("Original key '{}'", "AB"); @@ -187,7 +187,7 @@ public class TestSubstitution{ public void testSetKey_null(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword(null); - }, "Key cannot be null"); + }); assertEquals("", cipher.keyword); verify(logger, never()).debug(eq("Original key '{}'"), anyString()); @@ -270,7 +270,7 @@ public class TestSubstitution{ assertThrows(InvalidInputException.class, () -> { cipher.setInputString(""); - }, "Input must contain at least 1 letter"); + }); assertEquals("", cipher.inputString); verify(logger, times(1)).debug("Original input string '{}'", ""); @@ -288,7 +288,7 @@ public class TestSubstitution{ assertThrows(InvalidInputException.class, () -> { cipher.setInputString(null); - }, "Input cannot be null"); + }); assertEquals("", cipher.inputString); verify(logger, never()).debug(eq("Original input string '{}'"), anyString()); diff --git a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestVigenere.java b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestVigenere.java index e001d63..83fc3d4 100644 --- a/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestVigenere.java +++ b/src/test/java/com/mattrixwv/cipherstream/monosubstitution/TestVigenere.java @@ -194,7 +194,7 @@ public class TestVigenere{ assertThrows(InvalidInputException.class, () -> { cipher.setInputString(""); - }, "Input cannot be null"); + }); assertEquals("", cipher.inputString); verify(logger, times(1)).debug("Original input string '{}'", ""); @@ -214,7 +214,7 @@ public class TestVigenere{ assertThrows(InvalidInputException.class, () -> { cipher.setInputString(null); - }, "Input must contain at least 1 letter"); + }); assertEquals("", cipher.inputString); verify(logger, never()).debug(eq("Original input string '{}'"), anyString()); @@ -240,7 +240,7 @@ public class TestVigenere{ public void testSetKeyword_blank(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword(""); - }, "Keyword must contain at least 2 letters"); + }); assertEquals("", cipher.keyword); assertEquals(new ArrayList<>(), cipher.offset); @@ -254,7 +254,7 @@ public class TestVigenere{ public void testSetKeyword_null(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword(null); - }, "Keyword must contain at least 2 letters"); + }); assertEquals("", cipher.keyword); assertEquals(new ArrayList<>(), cipher.offset); diff --git a/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestColumnar.java b/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestColumnar.java index 579b37c..9c790d0 100644 --- a/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestColumnar.java +++ b/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestColumnar.java @@ -1,13 +1,29 @@ //Mattrixwv/src/test/java/com/mattrixwv/CipherStreamJava/polySubstitution/TestColumnar.java //Mattrixwv // Created: 01-16-22 -//Modified: 07-09-22 +//Modified: 04-26-23 package com.mattrixwv.cipherstream.polysubstitution; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyChar; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; import com.mattrixwv.cipherstream.exceptions.InvalidCharacterException; import com.mattrixwv.cipherstream.exceptions.InvalidInputException; @@ -15,462 +31,928 @@ import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; public class TestColumnar{ - @Test - public void testEncode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(true, true, true, false); + private Columnar cipher; + private Logger logger; + //Variables + private String decodedString = "Message to*encode"; + private String decodedStringPadded = "Message to*encodexxxxxx"; + private String decodedStringClean = "MESSAGETOENCODEXXXXXX"; + private String encodedString = "Edeomte ac*gosnse"; + //TODO: This is a bug that needs fixed + private String encodedStringPadingAdded = "Edxeoxmte ac*xgoxsnxsex"; //When padding is added to outputString for decoding + private String encodedStringPadded = "Edxeoxm te*acxgoxsnxsex"; //When padding is left in outputString + private String encodedStringClean = "EDXEOXMTEACXGOXSNXSEX"; + private String keyword = "keyword"; + private ArrayList> encodeGrid = new ArrayList<>( + List.of( + new ArrayList<>( + List.of('K', 'E', 'Y', 'W', 'O', 'R', 'D') + ), + new ArrayList<>( + List.of('M', 'E', 'S', 'S', 'A', 'G', 'E') + ), + new ArrayList<>( + List.of('T', 'O', 'E', 'N', 'C', 'O', 'D') + ), + new ArrayList<>( + List.of('E', 'X', 'X', 'X', 'X', 'X', 'X') + ) + ) + ); + private ArrayList> decodeGrid = new ArrayList<>( + List.of( + new ArrayList<>( + List.of('D', 'E', 'K', 'O', 'R', 'W', 'Y') + ), + new ArrayList<>( + List.of('E', 'E', 'M', 'A', 'G', 'S', 'S') + ), + new ArrayList<>( + List.of('D', 'O', 'T', 'C', 'O', 'N', 'E') + ), + new ArrayList<>( + List.of('X', 'X', 'E', 'X', 'X', 'X', 'X') + ) + ) + ); - //Test lowercase encoding - String inputString = "messagetoencode"; - String keyword = "keyword"; - String correctOutput = "edxeoxmteacxgoxsnxsex"; - String output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - keyword = "keyword"; - correctOutput = "EDXEOXMTEACXGOXsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test whitespace encoding - inputString = "message to encode"; - keyword = "keyword"; - correctOutput = "edxeoxm te acxgoxsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message@to-encode"; - keyword = "keyword"; - correctOutput = "edxeoxm@te-acxgoxsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol encoding - inputString = "Message to*encode"; - keyword = "keyword"; - correctOutput = "Edxeoxm te*acxgoxsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - } - @Test - public void testNoCapitalEncode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(false, true, true, false); - - //Test lowercase encoding - String inputString = "messagetoencode"; - String keyword = "keyword"; - String correctOutput = "EDXEOXMTEACXGOXSNXSEX"; - String output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - keyword = "keyword"; - correctOutput = "EDXEOXMTEACXGOXSNXSEX"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace encoding - inputString = "message to encode"; - keyword = "keyword"; - correctOutput = "EDXEOXM TE ACXGOXSNXSEX"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message@to-encode"; - keyword = "keyword"; - correctOutput = "EDXEOXM@TE-ACXGOXSNXSEX"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol encoding - inputString = "Message to*encode"; - keyword = "keyword"; - correctOutput = "EDXEOXM TE*ACXGOXSNXSEX"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - } - @Test - public void testNoWhitespaceEncode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(true, false, true, false); - - //Test lowercase encoding - String inputString = "messagetoencode"; - String keyword = "keyword"; - String correctOutput = "edxeoxmteacxgoxsnxsex"; - String output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - keyword = "keyword"; - correctOutput = "EDXEOXMTEACXGOXsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace encoding - inputString = "message to encode"; - keyword = "keyword"; - correctOutput = "edxeoxmteacxgoxsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message@to-encode"; - keyword = "keyword"; - correctOutput = "edxeoxm@te-acxgoxsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol encoding - inputString = "Message to*encode"; - keyword = "keyword"; - correctOutput = "Edxeoxmte*acxgoxsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - } - @Test - public void testNoSymbolEncode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(true, true, false, false); - - //Test lowercase encoding - String inputString = "messagetoencode"; - String keyword = "keyword"; - String correctOutput = "edxeoxmteacxgoxsnxsex"; - String output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - keyword = "keyword"; - correctOutput = "EDXEOXMTEACXGOXsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace encoding - inputString = "message to encode"; - keyword = "keyword"; - correctOutput = "edxeoxm te acxgoxsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message@to-encode"; - keyword = "keyword"; - correctOutput = "edxeoxmteacxgoxsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol encoding - inputString = "Message to*encode"; - keyword = "keyword"; - correctOutput = "Edxeoxm teacxgoxsnxsex"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - } - @Test - public void testNoPaddingEncode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(true, true, true, true); - - //Test lowercase encoding - String inputString = "messagetoencode"; - String keyword = "keyword"; - String correctOutput = "edeomteacgosnse"; - String output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - keyword = "keyword"; - correctOutput = "EDEOMTEACGOSNSE"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace encoding - inputString = "message to encode"; - keyword = "keyword"; - correctOutput = "edeomte ac gosnse"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message@to-encode"; - keyword = "keyword"; - correctOutput = "edeomte@ac-gosnse"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol encoding - inputString = "Message To*encode"; - keyword = "keyword"; - correctOutput = "Edeomte Ac*gosnse"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - } - @Test - public void testNoCapitalWhitespaceSymbolEncode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(false, false, false, false); - - //Test lowercase encoding - String inputString = "messagetoencode"; - String keyword = "keyword"; - String correctOutput = "EDXEOXMTEACXGOXSNXSEX"; - String output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - keyword = "keyword"; - correctOutput = "EDXEOXMTEACXGOXSNXSEX"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace encoding - inputString = "message to encode"; - keyword = "keyword"; - correctOutput = "EDXEOXMTEACXGOXSNXSEX"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message@to-encode"; - keyword = "keyword"; - correctOutput = "EDXEOXMTEACXGOXSNXSEX"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol encoding - inputString = "Message to*encode"; - keyword = "keyword"; - correctOutput = "EDXEOXMTEACXGOXSNXSEX"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); + @BeforeEach + public void setup(){ + cipher = new Columnar(); + logger = mock(Logger.class); + Columnar.logger = logger; } @Test - public void testDecode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(true, true, true, false); + public void testConstructor_default(){ + cipher = new Columnar(); - //Test lowercase decoding - String inputString = "edxeoxmteacxgoxsnxsex"; - String keyword = "keyword"; - String correctOutput = "messagetoencodexxxxxx"; - String output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "EDXEOXMTEACXGOXsnxsex"; - keyword = "keyword"; - correctOutput = "MESSAGETOENCODExxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "edxeoxm te acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "message to encodexxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "edxeoxm@te-acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "message@to-encodexxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol decoding - inputString = "Edxeoxm te*acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "Message to*encodexxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); + assertFalse(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertFalse(cipher.removePadding); + assertEquals('X', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertEquals(new ArrayList<>(), cipher.grid); + assertEquals(0, cipher.charsAdded); } + @Test - public void testNoCapitalDecode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(false, true, true, false); + public void testConstructorPadding_noCapitals(){ + cipher = new Columnar(true, false, false, false); - //Test lowercase decoding - String inputString = "edxeoxmteacxgoxsnxsex"; - String keyword = "keyword"; - String correctOutput = "MESSAGETOENCODEXXXXXX"; - String output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "EDXEOXMTEACXGOXsnxsex"; - keyword = "keyword"; - correctOutput = "MESSAGETOENCODEXXXXXX"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "edxeoxm te acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "MESSAGE TO ENCODEXXXXXX"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "edxeoxm@te-acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "MESSAGE@TO-ENCODEXXXXXX"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol decoding - inputString = "Edxeoxm te*acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "MESSAGE TO*ENCODEXXXXXX"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); + assertTrue(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertFalse(cipher.removePadding); + assertEquals('x', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertEquals(new ArrayList<>(), cipher.grid); + assertEquals(0, cipher.charsAdded); } + @Test - public void testNoWhitespaceDecode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(true, false, true, false); + public void testConstructorPadding_noWhitespace(){ + cipher = new Columnar(false, true, false, false); - //Test lowercase decoding - String inputString = "edxeoxmteacxgoxsnxsex"; - String keyword = "keyword"; - String correctOutput = "messagetoencodexxxxxx"; - String output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "EDXEOXMTEACXGOXsnxsex"; - keyword = "keyword"; - correctOutput = "MESSAGETOENCODExxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "edxeoxm te acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "messagetoencodexxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "edxeoxm@te-acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "message@to-encodexxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol decoding - inputString = "Edxeoxm te*acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "Messageto*encodexxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); + assertFalse(cipher.preserveCapitals); + assertTrue(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertFalse(cipher.removePadding); + assertEquals('X', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertEquals(new ArrayList<>(), cipher.grid); + assertEquals(0, cipher.charsAdded); } + @Test - public void testNoSymbolDecode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(true, true, false, false); + public void testCosntructorPadding_noSymbols(){ + cipher = new Columnar(false, false, true, false); - //Test lowercase decoding - String inputString = "edxeoxmteacxgoxsnxsex"; - String keyword = "keyword"; - String correctOutput = "messagetoencodexxxxxx"; - String output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "EDXEOXMTEACXGOXsnxsex"; - keyword = "keyword"; - correctOutput = "MESSAGETOENCODExxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "edxeoxm te acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "message to encodexxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "edxeoxm@te-acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "messagetoencodexxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol decoding - inputString = "Edxeoxm te*acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "Message toencodexxxxxx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); + assertFalse(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertTrue(cipher.preserveSymbols); + assertFalse(cipher.removePadding); + assertEquals('X', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertEquals(new ArrayList<>(), cipher.grid); + assertEquals(0, cipher.charsAdded); } + @Test - public void testNoPaddingDecode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(true, true, true, true); + public void testConstructorPadding_noPadding(){ + cipher = new Columnar(false, false, false, true); - //Test lowercase decoding - String inputString = "edeomteacgosnse"; - String keyword = "keyword"; - String correctOutput = "messagetoencode"; - String output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "EDEOMTEACGOSNSE"; - keyword = "keyword"; - correctOutput = "MESSAGETOENCODE"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "edeomte ac gosnse"; - keyword = "keyword"; - correctOutput = "message to encode"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "edeomte@ac-gosnse"; - keyword = "keyword"; - correctOutput = "message@to-encode"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol decoding - inputString = "Edeomte ac*gosnse"; - keyword = "keyword"; - correctOutput = "Message to*encode"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); + assertFalse(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertTrue(cipher.removePadding); + assertEquals('X', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertEquals(new ArrayList<>(), cipher.grid); + assertEquals(0, cipher.charsAdded); } + @Test - public void testNoCapitalWhitespaceSymbolDecode() throws InvalidCharacterException, InvalidKeywordException, InvalidInputException{ - Columnar cipher = new Columnar(false, false, false, false); + public void testConstructorCharacter_noCapitals(){ + cipher = new Columnar(true, false, false, false, 'y'); - //Test lowercase decoding - String inputString = "edxeoxmteacxgoxsnxsex"; - String keyword = "keyword"; - String correctOutput = "MESSAGETOENCODEXXXXXX"; - String output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "EDXEOXMTEACXGOXsnxsex"; - keyword = "keyword"; - correctOutput = "MESSAGETOENCODEXXXXXX"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); + assertTrue(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertFalse(cipher.removePadding); + assertEquals('y', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertEquals(new ArrayList<>(), cipher.grid); + assertEquals(0, cipher.charsAdded); + } - //Test whitespace decoding - inputString = "edxeoxm te acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "MESSAGETOENCODEXXXXXX"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); + @Test + public void testConstructorCharacter_noWhitespace(){ + cipher = new Columnar(false, true, false, false, 'y'); - //Test symbol decoding - inputString = "edxeoxm@te-acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "MESSAGETOENCODEXXXXXX"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); + assertFalse(cipher.preserveCapitals); + assertTrue(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertFalse(cipher.removePadding); + assertEquals('Y', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertEquals(new ArrayList<>(), cipher.grid); + assertEquals(0, cipher.charsAdded); + } - //Test mixed case, whitespace, symbol decoding - inputString = "Edxeoxm te*acxgoxsnxsex"; - keyword = "keyword"; - correctOutput = "MESSAGETOENCODEXXXXXX"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); + @Test + public void testConstructorCharacter_noSymbols(){ + cipher = new Columnar(false, false, true, false, 'y'); + + assertFalse(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertTrue(cipher.preserveSymbols); + assertFalse(cipher.removePadding); + assertEquals('Y', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertEquals(new ArrayList<>(), cipher.grid); + assertEquals(0, cipher.charsAdded); + } + + @Test + public void testConstructorCharacter_noPadding(){ + cipher = new Columnar(false, false, false, true, 'y'); + + assertFalse(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertTrue(cipher.removePadding); + assertEquals('Y', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertEquals(new ArrayList<>(), cipher.grid); + assertEquals(0, cipher.charsAdded); + } + + @Test + public void testConstructorCharacter_differentCharacter(){ + cipher = new Columnar(false, false, false, false, 'z'); + + assertFalse(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertFalse(cipher.removePadding); + assertEquals('Z', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertEquals(new ArrayList<>(), cipher.grid); + assertEquals(0, cipher.charsAdded); + } + + @Test + public void testGetCleanInputString(){ + cipher.inputString = decodedString; + + String output = cipher.getCleanInputString(); + + assertEquals(decodedString.toUpperCase().replaceAll("[^A-Z]", ""), output); + } + + @Test + public void testCreateGridEncode(){ + cipher.inputString = decodedStringPadded; + cipher.keyword = keyword.toUpperCase(); + + cipher.createGridEncode(); + + assertEquals(encodeGrid, cipher.grid); + verify(logger, times(1)).debug("Creating grid for encoding"); + } + + @Test + public void testCreateGridDecode(){ + cipher.inputString = encodedStringPadingAdded; + cipher.keyword = keyword.toUpperCase(); + + cipher.createGridDecode(); + + assertEquals(decodeGrid, cipher.grid); + verify(logger, times(1)).debug("Creating grid for decoding"); + } + + @Test + public void testSetInputStringEncode(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.keyword = keyword; + cipher.characterToAdd = 'x'; + + cipher.setInputStringEncode(decodedString); + + assertEquals(decodedStringPadded, cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", decodedString); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Appending {} characters", 6); + verify(logger, times(1)).debug("Cleaned input string '{}'", decodedStringPadded); + } + + @Test + public void testSetInputStringEncode_noCapitals(){ + cipher.preserveCapitals = false; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.keyword = keyword; + cipher.characterToAdd = 'X'; + + cipher.setInputStringEncode(decodedString); + + assertEquals(decodedStringPadded.toUpperCase(), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", decodedString); + verify(logger, times(1)).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Appending {} characters", 6); + verify(logger, times(1)).debug("Cleaned input string '{}'", decodedStringPadded.toUpperCase()); + } + + @Test + public void testSetInputStringEncode_noWhitespace(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = false; + cipher.preserveSymbols = true; + cipher.keyword = keyword; + cipher.characterToAdd = 'x'; + + cipher.setInputStringEncode(decodedString); + + assertEquals(decodedStringPadded.replaceAll("\\s", ""), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", decodedString); + verify(logger, never()).debug("Removing case"); + verify(logger, times(1)).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Appending {} characters", 6); + verify(logger, times(1)).debug("Cleaned input string '{}'", decodedStringPadded.replaceAll("\\s", "")); + } + + @Test + public void testSetInputStringEncode_noSymbols(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = false; + cipher.keyword = keyword; + cipher.characterToAdd = 'x'; + + cipher.setInputStringEncode(decodedString); + + assertEquals(decodedStringPadded.replaceAll("[^a-zA-Z\\s]", ""), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", decodedString); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, times(1)).debug("Removing symbols"); + verify(logger, times(1)).debug("Appending {} characters", 6); + verify(logger, times(1)).debug("Cleaned input string '{}'", decodedStringPadded.replaceAll("[^a-zA-Z\\s]", "")); + } + + @Test + public void testSetInputStringEncode_blank(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.keyword = keyword; + cipher.characterToAdd = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringEncode(""); + }); + + assertEquals("", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", ""); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, never()).debug(eq("Appending {} characters"), anyInt()); + verify(logger, times(1)).debug("Cleaned input string '{}'", ""); + } + + @Test + public void testSetInputStringEncode_blankClean(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.keyword = keyword; + cipher.characterToAdd = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringEncode("*"); + }); + + assertEquals("*", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", "*"); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, never()).debug(eq("Appending {} characters"), anyInt()); + verify(logger, times(1)).debug("Cleaned input string '{}'", "*"); + } + + @Test + public void testSetInputStringEncode_null(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.keyword = keyword; + cipher.characterToAdd = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringEncode(null); + }); + + assertEquals("", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, never()).debug(eq("Original input string '{}'"), anyString()); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, never()).debug(eq("Appending {} characters"), anyInt()); + verify(logger, never()).debug(eq("Cleaned input string '{}'"), anyString()); + } + + @Test + public void testSetInputStringDecode(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.keyword = keyword.toUpperCase(); + cipher.characterToAdd = 'x'; + + cipher.setInputStringDecode(encodedString); + + assertEquals(encodedStringPadingAdded, cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", encodedString); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", encodedStringPadingAdded); + } + + @Test + public void testSetInputStringDecode_perfectLength(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.keyword = keyword.toUpperCase(); + cipher.characterToAdd = 'x'; + + cipher.setInputStringDecode("Message to encod"); + + assertEquals("Message to encod", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", "Message to encod"); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", "Message to encod"); + } + + @Test + public void testSetInputStringDecode_noCapitals(){ + cipher.preserveCapitals = false; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.keyword = keyword.toUpperCase(); + cipher.characterToAdd = 'X'; + + cipher.setInputStringDecode(encodedString); + + assertEquals(encodedStringPadingAdded.toUpperCase(), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", encodedString); + verify(logger, times(1)).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", encodedStringPadingAdded.toUpperCase()); + } + + @Test + public void testSetInputStringDecode_noWhitespace(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = false; + cipher.preserveSymbols = true; + cipher.keyword = keyword.toUpperCase(); + cipher.characterToAdd = 'x'; + + cipher.setInputStringDecode(encodedString); + + assertEquals(encodedStringPadingAdded.replaceAll("\\s", ""), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", encodedString); + verify(logger, never()).debug("Removing case"); + verify(logger, times(1)).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", encodedStringPadingAdded.replaceAll("\\s", "")); + } + + @Test + public void testSetInputStringDecode_noSymbols(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = false; + cipher.keyword = keyword.toUpperCase(); + cipher.characterToAdd = 'x'; + + cipher.setInputStringDecode(encodedString); + + assertEquals(encodedStringPadingAdded.replaceAll("[^a-zA-Z\\s]", ""), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", encodedString); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, times(1)).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", encodedStringPadingAdded.replaceAll("[^a-zA-Z\\s]", "")); + } + + @Test + public void testSetInputStringDecode_blank(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.keyword = keyword.toUpperCase(); + cipher.characterToAdd = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringDecode(""); + }); + + assertEquals("", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", ""); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", ""); + } + + @Test + public void testSetInputStringDecode_blankClean(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.keyword = keyword.toUpperCase(); + cipher.characterToAdd = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringDecode("*"); + }); + + assertEquals("*", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", "*"); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", "*"); + } + + @Test + public void testSetInputStringDecode_null(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.keyword = keyword.toUpperCase(); + cipher.characterToAdd = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringDecode(null); + }); + + assertEquals("", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, never()).debug(eq("Original input string '{}'"), anyString()); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, never()).debug(eq("Cleaned input string '{}'"), anyString()); + } + + @Test + public void testCreateOutputStringFromColumns(){ + cipher.removePadding = true; + cipher.inputString = decodedStringPadded; + cipher.keyword = keyword.toUpperCase(); + cipher.grid = decodeGrid; + cipher.charsAdded = 6; + cipher.characterToAdd = 'x'; + + cipher.createOutputStringFromColumns(); + + assertEquals(encodedString, cipher.outputString); + verify(logger, times(1)).debug("Creating output string for encoding"); + verify(logger, times(1)).debug("Getting added characters"); + verify(logger, times(1)).debug("Turning grid into string"); + verify(logger, times(1)).debug("Formatting output string"); + verify(logger, times(1)).debug("Output string '{}'", encodedString); + } + + @Test + public void testCreateOutputStringFromColumns_padding(){ + cipher.removePadding = false; + cipher.inputString = decodedStringPadded; + cipher.keyword = keyword.toUpperCase(); + cipher.grid = decodeGrid; + cipher.charsAdded = 6; + cipher.characterToAdd = 'x'; + + cipher.createOutputStringFromColumns(); + + assertEquals(encodedStringPadded, cipher.outputString); + verify(logger, times(1)).debug("Creating output string for encoding"); + verify(logger, times(1)).debug("Getting added characters"); + verify(logger, times(1)).debug("Turning grid into string"); + verify(logger, times(1)).debug("Formatting output string"); + verify(logger, times(1)).debug("Output string '{}'", encodedStringPadded); + } + + @Test + public void testCreateOutputStringFromRows(){ + cipher.removePadding = false; + cipher.inputString = encodedStringPadded; + cipher.keyword = keyword.toUpperCase(); + cipher.grid = encodeGrid; + cipher.charsAdded = 6; + cipher.characterToAdd = 'x'; + + cipher.createOutputStringFromRows(); + + assertEquals(decodedStringPadded, cipher.outputString); + verify(logger, times(1)).debug("Creating output string for decoding"); + verify(logger, times(1)).debug("Transforming grid to a string"); + verify(logger, times(1)).debug("Removing padding"); + verify(logger, times(1)).debug("Formatting output string"); + verify(logger, times(23)).debug(eq("Working character {}"), anyChar()); + verify(logger, times(1)).debug("Adding upper case"); + verify(logger, times(20)).debug("Adding lower case"); + verify(logger, times(2)).debug("Adding symbol"); + verify(logger, times(1)).debug("Decoded output string '{}'", decodedStringPadded); + } + + @Test + public void testCreateOuputStringFromRows_removePadding(){ + cipher.removePadding = true; + cipher.inputString = encodedStringPadingAdded; + cipher.keyword = keyword.toUpperCase(); + cipher.grid = encodeGrid; + cipher.charsAdded = 6; + cipher.characterToAdd = 'x'; + + cipher.createOutputStringFromRows(); + + assertEquals(decodedString, cipher.outputString); + verify(logger, times(1)).debug("Creating output string for decoding"); + verify(logger, times(1)).debug("Transforming grid to a string"); + verify(logger, times(1)).debug("Removing padding"); + verify(logger, times(1)).debug("Formatting output string"); + verify(logger, times(17)).debug(eq("Working character {}"), anyChar()); + verify(logger, times(1)).debug("Adding upper case"); + verify(logger, times(14)).debug("Adding lower case"); + verify(logger, times(2)).debug("Adding symbol"); + verify(logger, times(1)).debug("Decoded output string '{}'", decodedString); + } + + @Test + public void testSetKeyword(){ + cipher.setKeyword(keyword); + + assertEquals(keyword.toUpperCase(), cipher.keyword); + verify(logger, times(1)).debug("Original keyword {}", keyword); + verify(logger, times(1)).debug("Cleaned keyword {}", keyword.toUpperCase()); + } + + @Test + public void testSetKeyword_blank(){ + assertThrows(InvalidKeywordException.class, () -> { + cipher.setKeyword(""); + }); + + assertEquals("", cipher.keyword); + verify(logger, times(1)).debug("Original keyword {}", ""); + verify(logger, times(1)).debug("Cleaned keyword {}", ""); + } + + @Test + public void testSetKeyword_null(){ + assertThrows(InvalidKeywordException.class, () -> { + cipher.setKeyword(null); + }); + + assertEquals("", cipher.keyword); + verify(logger, never()).debug(eq("Original keyword {}"), anyString()); + verify(logger, never()).debug(eq("Cleaned keyword {}"), anyString()); + } + + @Test + public void testSetCharacterToAdd(){ + cipher.preserveCapitals = false; + + cipher.setCharacterToAdd('a'); + + assertEquals('A', cipher.characterToAdd); + verify(logger, times(1)).debug("Setting character to add {}", 'a'); + verify(logger, times(1)).debug("Character to add for padding {}", 'A'); + } + + @Test + public void testSetCharacterToAdd_preserveCapitals(){ + cipher.preserveCapitals = true; + + cipher.setCharacterToAdd('a'); + + assertEquals('a', cipher.characterToAdd); + verify(logger, times(1)).debug("Setting character to add {}", 'a'); + verify(logger, times(1)).debug("Character to add for padding {}", 'a'); + } + + @Test + public void testSetCharacterToAdd_symbol(){ + assertThrows(InvalidCharacterException.class, () -> { + cipher.setCharacterToAdd('*'); + }); + + assertEquals('X', cipher.characterToAdd); + verify(logger, never()).debug(eq("Setting character to add {}"), anyChar()); + verify(logger, never()).debug(eq("Character to add for padding {}"), anyChar()); + } + + @Test + public void testGetKeywordAlphaLocations(){ + ArrayList alphaLocations = new ArrayList<>(List.of(6, 1, 0, 4, 5, 3, 2)); + + cipher.keyword = keyword.toUpperCase(); + + ArrayList returnedLocations = cipher.getKeywordAlphaLocations(); + + assertEquals(alphaLocations, returnedLocations); + verify(logger, times(1)).debug("Creating an array of keyword letter locations"); + verify(logger, times(1)).debug("Array of keyword letters {}", alphaLocations); + } + + @Test + public void testGetKeywordOriginalLocations(){ + ArrayList orderedLocations = new ArrayList<>(List.of(2, 1, 6, 5, 3, 4, 0)); + + cipher.keyword = keyword.toUpperCase(); + + ArrayList returnedLocations = cipher.getKeywordOriginalLocations(); + + assertEquals(orderedLocations, returnedLocations); + verify(logger, times(1)).debug("Creating array of original keyword locations"); + verify(logger, times(1)).debug("Array of keyword letters {}", orderedLocations); + } + + @Test + public void testRearangeGrid_encode(){ + ArrayList listOrder = new ArrayList<>(List.of(6, 1, 0, 4, 5, 3, 2)); + + cipher.grid = encodeGrid; + + cipher.rearangeGrid(listOrder); + + assertEquals(decodeGrid, cipher.grid); + verify(logger, times(1)).debug("Rearanging grid"); + verify(logger, times(1)).debug("New grid {}", decodeGrid); + } + + @Test + public void testRearangeGrid_decode(){ + ArrayList listOrder = new ArrayList<>(List.of(2, 1, 6, 5, 3, 4, 0)); + + cipher.grid = decodeGrid; + + cipher.rearangeGrid(listOrder); + + assertEquals(encodeGrid, cipher.grid); + verify(logger, times(1)).debug("Rearanging grid"); + verify(logger, times(1)).debug("New grid {}", encodeGrid); + } + + @Test + public void testEncode(){ + cipher.preserveCapitals = true; + cipher.removePadding = true; + cipher.inputString = decodedStringPadded; + cipher.keyword = keyword.toUpperCase(); + cipher.charsAdded = 6; + cipher.characterToAdd = 'x'; + + cipher.encode(); + + assertEquals(encodedString, cipher.outputString); + verify(logger, times(1)).debug("Encoding"); + verify(logger, times(1)).debug("Creating grid for encoding"); + verify(logger, times(2)).debug("Creating an array of keyword letter locations"); + verify(logger, times(1)).debug("Rearanging grid"); + verify(logger, times(1)).debug("Creating output string for encoding"); + } + + @Test + public void testEncode_padding(){ + cipher.preserveCapitals = true; + cipher.removePadding = false; + cipher.inputString = decodedStringPadded; + cipher.keyword = keyword.toUpperCase(); + cipher.charsAdded = 6; + cipher.characterToAdd = 'x'; + + cipher.encode(); + + assertEquals(encodedStringPadded, cipher.outputString); + verify(logger, times(1)).debug("Encoding"); + verify(logger, times(1)).debug("Creating grid for encoding"); + verify(logger, times(1)).debug("Creating an array of keyword letter locations"); + verify(logger, times(1)).debug("Rearanging grid"); + verify(logger, times(1)).debug("Creating output string for encoding"); + } + + @Test + public void testDecode(){ + cipher.preserveCapitals = true; + cipher.removePadding = true; + cipher.inputString = encodedStringPadingAdded; + cipher.keyword = keyword.toUpperCase(); + cipher.charsAdded = 6; + cipher.characterToAdd = 'x'; + + cipher.decode(); + + assertEquals(decodedString, cipher.outputString); + verify(logger, times(1)).debug("Decoding"); + verify(logger, times(1)).debug("Creating grid for decoding"); + verify(logger, times(2)).debug("Creating array of original keyword locations"); + verify(logger, times(1)).debug("Rearanging grid"); + verify(logger, times(1)).debug("Creating output string for decoding"); + } + + @Test + public void testDecode_padding(){ + cipher.preserveCapitals = true; + cipher.removePadding = false; + cipher.inputString = encodedStringPadded; + cipher.keyword = keyword.toUpperCase(); + cipher.charsAdded = 6; + cipher.characterToAdd = 'x'; + + cipher.decode(); + + assertEquals(decodedStringPadded, cipher.outputString); + verify(logger, times(1)).debug("Decoding"); + verify(logger, times(1)).debug("Creating grid for decoding"); + verify(logger, times(1)).debug("Creating array of original keyword locations"); + verify(logger, times(1)).debug("Rearanging grid"); + verify(logger, times(1)).debug("Creating output string for decoding"); + } + + @Test + public void testGetters(){ + cipher.inputString = decodedString; + cipher.keyword = keyword; + cipher.outputString = encodedString; + + assertEquals(decodedString, cipher.getInputString()); + assertEquals(keyword, cipher.getKeyword()); + assertEquals(encodedString, cipher.getOutputString()); + } + + @Test + public void testReset(){ + cipher.inputString = decodedString; + cipher.keyword = keyword; + cipher.outputString = encodedString; + cipher.grid = encodeGrid; + cipher.charsAdded = 5; + + cipher.reset(); + + assertEquals("", cipher.inputString); + assertEquals("", cipher.keyword); + assertEquals("", cipher.outputString); + assertEquals(new ArrayList<>(), cipher.grid); + assertEquals(0, cipher.charsAdded); + } + + @Test + public void testPracticalEncode(){ + cipher = new Columnar(true, true, true, true); + + String output = cipher.encode(keyword, decodedString); + + assertEquals(decodedStringPadded, cipher.inputString); + assertEquals(keyword.toUpperCase(), cipher.keyword); + assertEquals(encodedString, cipher.outputString); + assertEquals(encodedString, output); + } + + @Test + public void testPracticalEncode_noPadding(){ + cipher = new Columnar(true, true, true, false); + + String output = cipher.encode(keyword, decodedString); + + assertEquals(decodedStringPadded, cipher.inputString); + assertEquals(keyword.toUpperCase(), cipher.keyword); + assertEquals(encodedStringPadded, cipher.outputString); + assertEquals(encodedStringPadded, output); + } + + @Test + public void testPracticalEncode_clean(){ + cipher = new Columnar(false, false, false, false); + + String output = cipher.encode(keyword, decodedString); + + assertEquals(decodedStringClean, cipher.inputString); + assertEquals(keyword.toUpperCase(), cipher.keyword); + assertEquals(encodedStringClean, cipher.outputString); + assertEquals(encodedStringClean, output); + } + + @Test + public void testPracticalDecode(){ + cipher = new Columnar(true, true, true, true); + + String output = cipher.decode(keyword, encodedString); + + assertEquals(encodedStringPadingAdded, cipher.inputString); + assertEquals(keyword.toUpperCase(), cipher.keyword); + assertEquals(decodedString, cipher.outputString); + assertEquals(decodedString, output); + } + + @Test + public void testPracticalDecode_noPadding(){ + cipher = new Columnar(true, true, true, false); + + String output = cipher.decode(keyword, encodedStringPadded); + + assertEquals(encodedStringPadded, cipher.inputString); + assertEquals(keyword.toUpperCase(), cipher.keyword); + assertEquals(decodedStringPadded, cipher.outputString); + assertEquals(decodedStringPadded, output); + } + + @Test + public void testPracticalDecode_clean(){ + cipher = new Columnar(false, false, false, false); + + String output = cipher.decode(keyword, encodedString); + + assertEquals(encodedStringClean, cipher.inputString); + assertEquals(keyword.toUpperCase(), cipher.keyword); + assertEquals(decodedStringClean, cipher.outputString); + assertEquals(decodedStringClean, output); } } diff --git a/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestHill.java b/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestHill.java index b065492..f7334ed 100644 --- a/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestHill.java +++ b/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestHill.java @@ -1,528 +1,766 @@ //CipherStreamJava/src/test/java/com/mattrixwv/CipherStreamjava/polySubstitution/TestHill.java //Mattrixwv // Created: 01-31-22 -//Modified: 07-09-22 +//Modified: 04-28-23 package com.mattrixwv.cipherstream.polysubstitution; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyChar; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import java.util.ArrayList; + +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; import com.mattrixwv.cipherstream.exceptions.InvalidCharacterException; import com.mattrixwv.cipherstream.exceptions.InvalidInputException; import com.mattrixwv.cipherstream.exceptions.InvalidKeyException; +import com.mattrixwv.matrix.ModMatrix; public class TestHill{ - @Test - public void testEncode() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(true, true, true, true); + private Hill cipher; + private Logger logger; + //Fields + private String decodedString = "Message to^encoded"; + private String decodedStringPadded = "Message to^encodedxx"; + private String decodedStringClean = "MESSAGETOENCODEDXX"; + private String encodedString = "Mgkeqge ul^ikhisplrd"; + private String encodedStringClean = "MGKEQGEULIKHISPLRD"; + private int[][] keyArray = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; + private ModMatrix key = new ModMatrix(keyArray, 26); - //Test lowercase encoding - String inputString = "messagetoencode"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "mgkeqgeulikhisp"; - String output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGEULIKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - //Test whitespace encoding - inputString = "message to encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqge ul ikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message*to+encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqge*ul+ikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test padding encoding - inputString = "messagetoencod"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqgeulikhul"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, and symbol encoding - inputString = "Message to^encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "Mgkeqge ul^ikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - } - - @Test - public void testNoCapitalEncode() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(false, true, true, true); - - //Test lowercase encoding - String inputString = "messagetoencode"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "MGKEQGEULIKHISP"; - String output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGEULIKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test whitespace encoding - inputString = "message to encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGE UL IKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message*to+encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGE*UL+IKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test padding encoding - inputString = "messagetoencod"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGEULIKHUL"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, and symbol encoding - inputString = "Message to^encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGE UL^IKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - } - - @Test - public void testNoWhitespaceEncode() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(true, false, true, true); - - //Test lowercase encoding - String inputString = "messagetoencode"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "mgkeqgeulikhisp"; - String output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGEULIKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test whitespace encoding - inputString = "message to encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqgeulikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message*to+encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqge*ul+ikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test padding encoding - inputString = "messagetoencod"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqgeulikhul"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, and symbol encoding - inputString = "Message to^encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "Mgkeqgeul^ikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - } - - @Test - public void testNoSymbolEncode() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(true, true, false, true); - - //Test lowercase encoding - String inputString = "messagetoencode"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "mgkeqgeulikhisp"; - String output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGEULIKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test whitespace encoding - inputString = "message to encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqge ul ikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message*to+encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqgeulikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test padding encoding - inputString = "messagetoencod"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqgeulikhul"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, and symbol encoding - inputString = "Message to^encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "Mgkeqge ulikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - } - - @Test - public void testNoPaddingEncoding() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(true, true, true, false); - - //Test lowercase encoding - String inputString = "messagetoencode"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "mgkeqgeulikhisp"; - String output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGEULIKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test whitespace encoding - inputString = "message to encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqge ul ikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message*to+encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqge*ul+ikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test padding encoding - inputString = "messagetoencod"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "mgkeqgeulikhulb"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, and symbol encoding - inputString = "Message to^encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "Mgkeqge ul^ikhisp"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - } - - @Test - public void testNoCapitalWhitespaceSymbolEncode() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(false, false, false, false); - - //Test lowercase encoding - String inputString = "messagetoencode"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "MGKEQGEULIKHISP"; - String output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "MESSAGETOENCODE"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGEULIKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test whitespace encoding - inputString = "message to encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGEULIKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "message*to+encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGEULIKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test padding encoding - inputString = "messagetoencod"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGEULIKHULB"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, and symbol encoding - inputString = "Message to^encode"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MGKEQGEULIKHISP"; - output = cipher.encode(key, inputString); - assertEquals(correctOutput, output); + @BeforeEach + public void setup(){ + cipher = new Hill(); + logger = mock(Logger.class); + Hill.logger = logger; } @Test - public void testDecode() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(true, true, true, true); + public void testConstructor_default(){ + cipher = new Hill(); - //Test lowercase decoding - String inputString = "mgkeqgeulikhisp"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "messagetoencode"; - String output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "MGKEQGEULIKHISP"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGETOENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "mgkeqge ul ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "message to encode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "mgkeqge*ul+ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "message*to+encode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, and symbol decoding - inputString = "Mgkeqge ul^ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "Message to^encode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); + assertFalse(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertEquals('X', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals(new ModMatrix(26), cipher.key); + assertEquals("", cipher.outputString); } @Test - public void testNoCapitalDecode() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(false, true, true, true); + public void testConstructorShort_noCapitals(){ + cipher = new Hill(false, true, true); - //Test lowercase decoding - String inputString = "mgkeqgeulikhisp"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "MESSAGETOENCODE"; - String output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "MGKEQGEULIKHISP"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGETOENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "mgkeqge ul ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGE TO ENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "mgkeqge*ul+ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGE*TO+ENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, and symbol decoding - inputString = "Mgkeqge ul^ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGE TO^ENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); + assertFalse(cipher.preserveCapitals); + assertTrue(cipher.preserveWhitespace); + assertTrue(cipher.preserveSymbols); + assertEquals('X', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals(new ModMatrix(26), cipher.key); + assertEquals("", cipher.outputString); } @Test - public void testNoWhitespaceDecode() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(true, false, true, true); + public void testConstructorShort_noWhitespace(){ + cipher = new Hill(true, false, true); - //Test lowercase decoding - String inputString = "mgkeqgeulikhisp"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "messagetoencode"; - String output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "MGKEQGEULIKHISP"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGETOENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "mgkeqge ul ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "messagetoencode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "mgkeqge*ul+ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "message*to+encode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, and symbol decoding - inputString = "Mgkeqge ul^ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "Messageto^encode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); + assertTrue(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertTrue(cipher.preserveSymbols); + assertEquals('x', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals(new ModMatrix(26), cipher.key); + assertEquals("", cipher.outputString); } @Test - public void testNoSymbolDecode() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(true, true, false, true); + public void testConstructorShort_noSymbols(){ + cipher = new Hill(true, true, false); - //Test lowercase decoding - String inputString = "mgkeqgeulikhisp"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "messagetoencode"; - String output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "MGKEQGEULIKHISP"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGETOENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "mgkeqge ul ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "message to encode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "mgkeqge*ul+ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "messagetoencode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, and symbol decoding - inputString = "Mgkeqge ul^ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "Message toencode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); + assertTrue(cipher.preserveCapitals); + assertTrue(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertEquals('x', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals(new ModMatrix(26), cipher.key); + assertEquals("", cipher.outputString); } @Test - public void testNoPaddingDecoding() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(true, true, true, false); + public void testConstructorLong_noCapitals(){ + cipher = new Hill(false, true, true, 'j'); - //Test lowercase decoding - String inputString = "mgkeqgeulikhisp"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "messagetoencode"; - String output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "MGKEQGEULIKHISP"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGETOENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "mgkeqge ul ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "message to encode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "mgkeqge*ul+ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "message*to+encode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, and symbol decoding - inputString = "Mgkeqge ul^ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "Message to^encode"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); + assertFalse(cipher.preserveCapitals); + assertTrue(cipher.preserveWhitespace); + assertTrue(cipher.preserveSymbols); + assertEquals('J', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals(new ModMatrix(26), cipher.key); + assertEquals("", cipher.outputString); } @Test - public void testNoCapitalWhitespaceSymbolDecode() throws InvalidCharacterException, InvalidKeyException, InvalidInputException{ - Hill cipher = new Hill(false, false, false, false); + public void testConstructorLong_noWhitespace(){ + cipher = new Hill(true, false, true, 'j'); - //Test lowercase decoding - String inputString = "mgkeqgeulikhisp"; - int[][] key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - String correctOutput = "MESSAGETOENCODE"; - String output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "MGKEQGEULIKHISP"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGETOENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); + assertTrue(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertTrue(cipher.preserveSymbols); + assertEquals('j', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals(new ModMatrix(26), cipher.key); + assertEquals("", cipher.outputString); + } - //Test whitespace decoding - inputString = "mgkeqge ul ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGETOENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); + @Test + public void testConstructorLong_noSymbols(){ + cipher = new Hill(true, true, false, 'j'); - //Test symbol decoding - inputString = "mgkeqge*ul+ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGETOENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); + assertTrue(cipher.preserveCapitals); + assertTrue(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertEquals('j', cipher.characterToAdd); + assertEquals("", cipher.inputString); + assertEquals(new ModMatrix(26), cipher.key); + assertEquals("", cipher.outputString); + } - //Test mixed case, whitespace, and symbol decoding - inputString = "Mgkeqge ul^ikhisp"; - key = new int[][]{{1, 4, 2}, {2, 4, 1}, {4, 1, 2}}; - correctOutput = "MESSAGETOENCODE"; - output = cipher.decode(key, inputString); - assertEquals(correctOutput, output); + @Test + public void testSetKey(){ + cipher.setKey(key); + + assertEquals(key, cipher.key); + verify(logger, times(1)).debug("Setting key"); + verify(logger, times(1)).debug("Testing mod"); + verify(logger, times(1)).debug("Testing square"); + verify(logger, times(1)).debug("Testing invertable"); + verify(logger, times(1)).debug("key = {}", key); + } + + @Test + public void testSetKey_invalidMod(){ + assertThrows(InvalidKeyException.class, () -> { + cipher.setKey(new ModMatrix(keyArray, 30)); + }); + + assertEquals(new ModMatrix(26), cipher.key); + verify(logger, times(1)).debug("Setting key"); + verify(logger, times(1)).debug("Testing mod"); + verify(logger, never()).debug("Testing square"); + verify(logger, never()).debug("Testing invertable"); + verify(logger, never()).debug(eq("key = {}"), any(ModMatrix.class)); + } + + @Test + public void testSetKey_NotSquare(){ + assertThrows(InvalidKeyException.class, () -> { + cipher.setKey(new ModMatrix(new int[][]{{10, 11}}, 26)); + }); + + assertEquals(new ModMatrix(26), cipher.key); + verify(logger, times(1)).debug("Setting key"); + verify(logger, times(1)).debug("Testing mod"); + verify(logger, times(1)).debug("Testing square"); + verify(logger, never()).debug("Testing invertable"); + verify(logger, never()).debug(eq("key = {}"), any(ModMatrix.class)); + } + + @Test + public void testSetKey_notInvertable(){ + assertThrows(InvalidKeyException.class, () -> { + cipher.setKey(new ModMatrix(new int[][]{{10, 11}, {12, 13}}, 26)); + }); + + assertEquals(new ModMatrix(26), cipher.key); + verify(logger, times(1)).debug("Setting key"); + verify(logger, times(1)).debug("Testing mod"); + verify(logger, times(1)).debug("Testing square"); + verify(logger, times(1)).debug("Testing invertable"); + verify(logger, never()).debug(eq("key = {}"), any(ModMatrix.class)); + } + + @Test + public void testSetInputStringEncode(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.key = key; + cipher.characterToAdd = 'x'; + + cipher.setInputStringEncode(decodedString); + + assertEquals(decodedStringPadded, cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", decodedString); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Checking length"); + verify(logger, times(1)).debug("Adding {} characters", 2); + verify(logger, times(1)).debug("Cleaned input string '{}'", decodedStringPadded); + } + + @Test + public void testSetInputStringEncode_noCapitals(){ + cipher.preserveCapitals = false; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.key = key; + cipher.characterToAdd = 'X'; + + cipher.setInputStringEncode(decodedString); + + assertEquals(decodedStringPadded.toUpperCase(), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", decodedString); + verify(logger, times(1)).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Checking length"); + verify(logger, times(1)).debug("Adding {} characters", 2); + verify(logger, times(1)).debug("Cleaned input string '{}'", decodedStringPadded.toUpperCase()); + } + + @Test + public void testSetInputStringEncode_noWhitespace(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = false; + cipher.preserveSymbols = true; + cipher.key = key; + cipher.characterToAdd = 'x'; + + cipher.setInputStringEncode(decodedString); + + assertEquals(decodedStringPadded.replaceAll("\\s", ""), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", decodedString); + verify(logger, never()).debug("Removing capitals"); + verify(logger, times(1)).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Checking length"); + verify(logger, times(1)).debug("Adding {} characters", 2); + verify(logger, times(1)).debug("Cleaned input string '{}'", decodedStringPadded.replaceAll("\\s", "")); + } + + @Test + public void testSetInputStringEncode_noSymbols(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = false; + cipher.key = key; + cipher.characterToAdd = 'x'; + + cipher.setInputStringEncode(decodedString); + + assertEquals(decodedStringPadded.replaceAll("[^a-zA-Z\\s]", ""), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", decodedString); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, times(1)).debug("Removing symbols"); + verify(logger, times(1)).debug("Checking length"); + verify(logger, times(1)).debug("Adding {} characters", 2); + verify(logger, times(1)).debug("Cleaned input string '{}'", decodedStringPadded.replaceAll("[^a-zA-Z\\s]", "")); + } + + @Test + public void testSetInputStringEncode_blank(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.key = key; + cipher.characterToAdd = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringEncode(""); + }); + + assertEquals("", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", ""); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Checking length"); + verify(logger, times(1)).debug("Adding {} characters", 0); + verify(logger, times(1)).debug("Cleaned input string '{}'", ""); + } + + @Test + public void testSetInputStringEncode_blankClean(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.key = key; + cipher.characterToAdd = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringEncode("*"); + }); + + assertEquals("*", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, times(1)).debug("Original input string '{}'", "*"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Checking length"); + verify(logger, times(1)).debug("Adding {} characters", 0); + verify(logger, times(1)).debug("Cleaned input string '{}'", "*"); + } + + @Test + public void testSetInputStringEncode_null(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.key = key; + cipher.characterToAdd = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringEncode(null); + }); + + assertEquals("", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for encoding"); + verify(logger, never()).debug(eq("Original input string '{}'"), anyString()); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, never()).debug("Checking length"); + verify(logger, never()).debug(eq("Adding {} characters"), anyInt()); + verify(logger, never()).debug(eq("Cleaned input string '{}'"), anyString()); + } + + @Test + public void testSetInputStringDecode(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.key = key; + + cipher.setInputStringDecode(encodedString); + + assertEquals(encodedString, cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", encodedString); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", encodedString); + verify(logger, times(1)).debug("Checking length"); + } + + @Test + public void testSetInputStringDecode_noCapitals(){ + cipher.preserveCapitals = false; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.key = key; + + cipher.setInputStringDecode(encodedString); + + assertEquals(encodedString.toUpperCase(), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", encodedString); + verify(logger, times(1)).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", encodedString.toUpperCase()); + verify(logger, times(1)).debug("Checking length"); + } + + @Test + public void testSetInputStringDecode_noWhitespace(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = false; + cipher.preserveSymbols = true; + cipher.key = key; + + cipher.setInputStringDecode(encodedString); + + assertEquals(encodedString.replaceAll("\\s", ""), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", encodedString); + verify(logger, never()).debug("Removing capitals"); + verify(logger, times(1)).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", encodedString.replaceAll("\\s", "")); + verify(logger, times(1)).debug("Checking length"); + } + + @Test + public void testSetInputStringDecode_noSymbols(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = false; + cipher.key = key; + + cipher.setInputStringDecode(encodedString); + + assertEquals(encodedString.replaceAll("[^a-zA-Z\\s]", ""), cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", encodedString); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, times(1)).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", encodedString.replaceAll("[^a-zA-Z\\s]", "")); + verify(logger, times(1)).debug("Checking length"); + } + + @Test + public void testSetInputStringDecode_notMultiple(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.key = key; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringDecode(encodedString + "a"); + }); + + assertEquals(encodedString + "a", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", encodedString + "a"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", encodedString + "a"); + verify(logger, times(1)).debug("Checking length"); + } + + @Test + public void testSetInputStringDecode_blank(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.key = key; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringDecode(""); + }); + + assertEquals("", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", ""); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", ""); + verify(logger, times(1)).debug("Checking length"); + } + + @Test + public void testSetInputStringDecode_blankClean(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.key = key; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringDecode("*^&"); + }); + + assertEquals("*^&", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, times(1)).debug("Original input string '{}'", "*^&"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Cleaned input string '{}'", "*^&"); + verify(logger, times(1)).debug("Checking length"); + } + + @Test + public void testSetInputStringDecode_null(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.key = key; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputStringDecode(null); + }); + + assertEquals("", cipher.inputString); + verify(logger, times(1)).debug("Setting input string for decoding"); + verify(logger, never()).debug(eq("Original input string '{}'"), anyString()); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, never()).debug(eq("Cleaned input string '{}'"), anyString()); + verify(logger, never()).debug("Checking length"); + } + + @Test + public void testGetCleanInputString(){ + cipher.inputString = decodedStringPadded; + + String output = cipher.getCleanInputString(); + + assertEquals(decodedStringClean, output); + verify(logger, times(1)).debug("Cleaning inputString"); + verify(logger, times(1)).debug("Clean input string '{}'", decodedStringClean); + } + + @Test + public void testSetCharacterToAdd(){ + cipher.preserveCapitals = true; + + cipher.setCharacterToAdd('j'); + + assertEquals('j', cipher.characterToAdd); + verify(logger, times(1)).debug("Setting character to add {}", 'j'); + verify(logger, never()).debug("Removing capitals"); + verify(logger, times(1)).debug("Cleaned character {}", 'j'); + } + + @Test + public void testSetCharacterToAdd_noCapitals(){ + cipher.preserveCapitals = false; + + cipher.setCharacterToAdd('j'); + + assertEquals('J', cipher.characterToAdd); + verify(logger, times(1)).debug("Setting character to add {}", 'j'); + verify(logger, times(1)).debug("Removing capitals"); + verify(logger, times(1)).debug("Cleaned character {}", 'J'); + } + + @Test + public void testSetCharacterToAdd_nonAlpha(){ + cipher.preserveCapitals = true; + + assertThrows(InvalidCharacterException.class, () -> { + cipher.setCharacterToAdd('1'); + }); + + assertEquals('X', cipher.characterToAdd); + verify(logger, times(1)).debug("Setting character to add {}", '1'); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug(eq("Cleaned character {}"), anyChar()); + } + + @Test + public void testPolishOutputString(){ + cipher.inputString = decodedStringPadded; + cipher.outputString = encodedStringClean; + + String output = cipher.polishOutputString(); + + assertEquals(encodedString, output); + verify(logger, times(1)).debug("Polishing output string"); + verify(logger, times(20)).debug(eq("Current char {}"), anyChar()); + verify(logger, times(1)).debug("Uppercase"); + verify(logger, times(17)).debug("Lowercase"); + verify(logger, times(2)).debug("Symbol"); + verify(logger, times(1)).debug("Polished string '{}'", encodedString); + } + + @Test + public void testGetInputVectors(){ + ArrayList expectedVectors = new ArrayList<>(); + expectedVectors.add(new ModMatrix(new int[][]{{12}, { 4}, {18}}, 26)); + expectedVectors.add(new ModMatrix(new int[][]{{18}, { 0}, { 6}}, 26)); + expectedVectors.add(new ModMatrix(new int[][]{{ 4}, {19}, {14}}, 26)); + expectedVectors.add(new ModMatrix(new int[][]{{ 4}, {13}, { 2}}, 26)); + expectedVectors.add(new ModMatrix(new int[][]{{14}, { 3}, { 4}}, 26)); + expectedVectors.add(new ModMatrix(new int[][]{{ 3}, {23}, {23}}, 26)); + + cipher.inputString = decodedStringPadded; + cipher.key = key; + + ArrayList returnedVectors = cipher.getInputVectors(); + + assertEquals(expectedVectors, returnedVectors); + verify(logger, times(1)).debug("Generating input vectors"); + verify(logger, times(6)).debug(eq("Current substring '{}'"), anyString()); + verify(logger, times(6)).debug(eq("Current vector {}"), any(ModMatrix.class)); + } + + @Test + public void testGetOutputFromVectors(){ + ArrayList outputVectors = new ArrayList<>(); + outputVectors.add(key.multiply(new ModMatrix(new int[][]{{12}, { 4}, {18}}, 26))); + outputVectors.add(key.multiply(new ModMatrix(new int[][]{{18}, { 0}, { 6}}, 26))); + outputVectors.add(key.multiply(new ModMatrix(new int[][]{{ 4}, {19}, {14}}, 26))); + outputVectors.add(key.multiply(new ModMatrix(new int[][]{{ 4}, {13}, { 2}}, 26))); + outputVectors.add(key.multiply(new ModMatrix(new int[][]{{14}, { 3}, { 4}}, 26))); + outputVectors.add(key.multiply(new ModMatrix(new int[][]{{ 3}, {23}, {23}}, 26))); + + String returnedString = cipher.getOutputFromVectors(outputVectors); + + assertEquals(encodedStringClean, returnedString); + verify(logger, times(1)).debug("Turning vectors into a string"); + verify(logger, times(6)).debug(eq("Current vector {}"), any(ModMatrix.class)); + verify(logger, times(1)).debug("Converted string '{}'", encodedStringClean); + } + + @Test + public void testEncode(){ + cipher.inputString = decodedStringPadded; + cipher.key = key; + + cipher.encode(); + + assertEquals(encodedString, cipher.outputString); + verify(logger, times(1)).debug("Encoding"); + verify(logger, times(1)).debug("Multiplying vectors"); + verify(logger, times(6)).debug(eq("Current input vector {}"), any(ModMatrix.class)); + verify(logger, times(6)).debug(eq("Multiplied vector {}"), any(ModMatrix.class)); + } + + @Test + public void testDecode(){ + cipher.inputString = encodedString; + cipher.key = key; + + cipher.decode(); + + assertEquals(decodedStringPadded, cipher.outputString); + verify(logger, times(1)).debug("Decoding"); + verify(logger, times(1)).debug("Getting inverse of key"); + verify(logger, times(1)).debug("Inverse of key {}", key.inverse()); + verify(logger, times(6)).debug(eq("Current input vector {}"), any(ModMatrix.class)); + verify(logger, times(6)).debug(eq("Multiplied vector {}"), any(ModMatrix.class)); + } + + @Test + public void testGetters(){ + cipher.inputString = decodedString; + cipher.outputString = encodedString; + cipher.key = key; + + assertEquals(decodedString, cipher.getInputString()); + assertEquals(encodedString, cipher.getOutputString()); + assertEquals(key, cipher.getKey()); + } + + @Test + public void testReset(){ + cipher.inputString = decodedString; + cipher.outputString = encodedString; + cipher.key = key; + + cipher.reset(); + + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals(new ModMatrix(26), cipher.key); + verify(logger, times(1)).debug("Resetting fields"); + } + + @Test + public void testPracticalEncode(){ + cipher = new Hill(true, true, true); + + String output = cipher.encode(key, decodedString); + + assertEquals(decodedStringPadded, cipher.inputString); + assertEquals(key, cipher.key); + assertEquals(encodedString, cipher.outputString); + assertEquals(encodedString, output); + } + + @Test + public void testPracticalEncode_clean(){ + cipher = new Hill(false, false, false); + + String output = cipher.encode(key, decodedString); + + assertEquals(decodedStringClean, cipher.inputString); + assertEquals(key, cipher.key); + assertEquals(encodedStringClean, cipher.outputString); + assertEquals(encodedStringClean, output); + } + + @Test + public void testPracticalEncode_array(){ + cipher = new Hill(true, true, true); + + String output = cipher.encode(keyArray, decodedString); + + assertEquals(decodedStringPadded, cipher.inputString); + assertEquals(key, cipher.key); + assertEquals(encodedString, cipher.outputString); + assertEquals(encodedString, output); + } + + @Test + public void testPracticalEncode_padding(){ + cipher = new Hill(true, true, true, 'j'); + + String output = cipher.encode(key, decodedString); + + assertEquals(decodedString + "jj", cipher.inputString); + assertEquals(key, cipher.key); + assertEquals("Mgkeqge ul^ikhispfzn", cipher.outputString); + assertEquals("Mgkeqge ul^ikhispfzn", output); + } + + @Test + public void testPracticalDecode(){ + cipher = new Hill(true, true, true); + + String output = cipher.decode(key, encodedString); + + assertEquals(encodedString, cipher.inputString); + assertEquals(key, cipher.key); + assertEquals(decodedStringPadded, cipher.outputString); + assertEquals(decodedStringPadded, output); + } + + @Test + public void testPracticalDecode_clean(){ + cipher = new Hill(false, false, false); + + String output = cipher.decode(key, encodedString); + + assertEquals(encodedStringClean, cipher.inputString); + assertEquals(key, cipher.key); + assertEquals(decodedStringClean, cipher.outputString); + assertEquals(decodedStringClean, output); + } + + @Test + public void testPracticalDecode_array(){ + cipher = new Hill(true, true, true); + + String output = cipher.decode(keyArray, encodedString); + + assertEquals(encodedString, cipher.inputString); + assertEquals(key, cipher.key); + assertEquals(decodedStringPadded, cipher.outputString); + assertEquals(decodedStringPadded, output); + } + + @Test + public void testPracticalDecode_padding(){ + cipher = new Hill(true, true, true, 'j'); + + String output = cipher.decode(key, "Mgkeqge ul^ikhispfzn"); + + assertEquals("Mgkeqge ul^ikhispfzn", cipher.inputString); + assertEquals(key, cipher.key); + assertEquals(decodedString + "jj", cipher.outputString); + assertEquals(decodedString + "jj", output); } } diff --git a/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestPlayfair.java b/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestPlayfair.java index 33235ac..5e5f097 100644 --- a/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestPlayfair.java +++ b/src/test/java/com/mattrixwv/cipherstream/polysubstitution/TestPlayfair.java @@ -1,517 +1,902 @@ //CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/TestPlayfair.java //Matthew Ellison // Created: 07-30-21 -//Modified: 07-09-22 +//Modified: 04-28-23 package com.mattrixwv.cipherstream.polysubstitution; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyChar; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; import com.mattrixwv.cipherstream.exceptions.InvalidCharacterException; import com.mattrixwv.cipherstream.exceptions.InvalidInputException; +import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; +import com.mattrixwv.cipherstream.polysubstitution.Playfair.CharLocation; public class TestPlayfair{ - @Test - public void testEncode() throws InvalidCharacterException, InvalidInputException{ - Playfair cipher = new Playfair(true, true, true); + private Playfair cipher; + private Logger logger; + //Fields + private String inputString = "Hide the gold in - the@tree+stump"; + private String inputStringPadded = "Hide the gold in - the@trexe+stump"; + private String inputStringClean = "HIDETHEGOLDINTHETREXESTUMP"; + private String outputString = "Bmod zbx dnab ek - udm@uixmm+ouvif"; + private String outputStringClean = "BMODZBXDNABEKUDMUIXMMOUVIF"; + private String keyword = "Play-fair@Exam ple"; + private String keywordClean = "PLAYFIREXMBCDGHKNOQSTUVWZ"; + private char[][] grid = new char[][]{ + {'P', 'L', 'A', 'Y', 'F'}, + {'I', 'R', 'E', 'X', 'M'}, + {'B', 'C', 'D', 'G', 'H'}, + {'K', 'N', 'O', 'Q', 'S'}, + {'T', 'U', 'V', 'W', 'Z'} + }; + + + @BeforeEach + public void setup(){ + cipher = new Playfair(); + logger = mock(Logger.class); + Playfair.logger = logger; + } + + + @Test + public void testConstructor_default(){ + cipher = new Playfair(); + + assertFalse(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertArrayEquals(new char[5][5], cipher.grid); + assertEquals('J', cipher.replaced); + assertEquals('I', cipher.replacer); + assertEquals('X', cipher.doubled); + } + + @Test + public void testConstructor_noCapitals(){ + cipher = new Playfair(false, true, true); + + assertFalse(cipher.preserveCapitals); + assertTrue(cipher.preserveWhitespace); + assertTrue(cipher.preserveSymbols); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertArrayEquals(new char[5][5], cipher.grid); + assertEquals('J', cipher.replaced); + assertEquals('I', cipher.replacer); + assertEquals('X', cipher.doubled); + } + + @Test + public void testConstructor_noWhitespace(){ + cipher = new Playfair(true, false, true); + + assertTrue(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertTrue(cipher.preserveSymbols); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertArrayEquals(new char[5][5], cipher.grid); + assertEquals('j', cipher.replaced); + assertEquals('i', cipher.replacer); + assertEquals('x', cipher.doubled); + } + + @Test + public void testConstructor_noSymbols(){ + cipher = new Playfair(true, true, false); + + assertTrue(cipher.preserveCapitals); + assertTrue(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertArrayEquals(new char[5][5], cipher.grid); + assertEquals('j', cipher.replaced); + assertEquals('i', cipher.replacer); + assertEquals('x', cipher.doubled); + } + + @Test + public void testConstructor_letters_noCapitals(){ + cipher = new Playfair(false, true, true, 'a', 'b', 'c'); + + assertFalse(cipher.preserveCapitals); + assertTrue(cipher.preserveWhitespace); + assertTrue(cipher.preserveSymbols); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertArrayEquals(new char[5][5], cipher.grid); + assertEquals('A', cipher.replaced); + assertEquals('B', cipher.replacer); + assertEquals('C', cipher.doubled); + } + + @Test + public void testConstructor_letters_noWhitespace(){ + cipher = new Playfair(true, false, true, 'a', 'b', 'c'); + + assertTrue(cipher.preserveCapitals); + assertFalse(cipher.preserveWhitespace); + assertTrue(cipher.preserveSymbols); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertArrayEquals(new char[5][5], cipher.grid); + assertEquals('a', cipher.replaced); + assertEquals('b', cipher.replacer); + assertEquals('c', cipher.doubled); + } + + @Test + public void testConstructor_letters_noSymbols(){ + cipher = new Playfair(true, true, false, 'a', 'b', 'c'); + + assertTrue(cipher.preserveCapitals); + assertTrue(cipher.preserveWhitespace); + assertFalse(cipher.preserveSymbols); + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertArrayEquals(new char[5][5], cipher.grid); + assertEquals('a', cipher.replaced); + assertEquals('b', cipher.replacer); + assertEquals('c', cipher.doubled); + } + + @Test + public void testSetDoubled(){ + cipher.setDoubled('a'); + + assertEquals('A', cipher.doubled); + verify(logger, times(1)).debug("Setting doubled"); + verify(logger, times(1)).debug("Original character {}", 'a'); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replacer"); + verify(logger, times(1)).debug("Checking same as replaced"); + verify(logger, times(1)).debug("Removing capitals"); + verify(logger, times(1)).debug("Setting doubled to {}", 'A'); + } + + @Test + public void testSetDoubled_capital(){ + cipher.preserveCapitals = true; + + cipher.setDoubled('a'); + + assertEquals('a', cipher.doubled); + verify(logger, times(1)).debug("Setting doubled"); + verify(logger, times(1)).debug("Original character {}", 'a'); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replacer"); + verify(logger, times(1)).debug("Checking same as replaced"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, times(1)).debug("Setting doubled to {}", 'a'); + } + + @Test + public void testSetDoubled_digit(){ + assertThrows(InvalidCharacterException.class, () -> { + cipher.setDoubled('1'); + }); + + assertEquals('X', cipher.doubled); + verify(logger, times(1)).debug("Setting doubled"); + verify(logger, times(1)).debug("Original character {}", '1'); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, never()).debug("Checking same as replacer"); + verify(logger, never()).debug("Checking same as replaced"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug(eq("Setting doubled to {}"), anyChar()); + } + + @Test + public void testSetDoubled_replacer(){ + assertThrows(InvalidCharacterException.class, () -> { + cipher.setDoubled(cipher.replacer); + }); + + assertEquals('X', cipher.doubled); + verify(logger, times(1)).debug("Setting doubled"); + verify(logger, times(1)).debug("Original character {}", cipher.replacer); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replacer"); + verify(logger, never()).debug("Checking same as replaced"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Setting doubled to {}", 'A'); + } + + @Test + public void testSetDoubled_replaced(){ + assertThrows(InvalidCharacterException.class, () -> { + cipher.setDoubled(cipher.replaced); + }); + + assertEquals('X', cipher.doubled); + verify(logger, times(1)).debug("Setting doubled"); + verify(logger, times(1)).debug("Original character {}", cipher.replaced); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replacer"); + verify(logger, times(1)).debug("Checking same as replaced"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug("Setting doubled to {}", 'A'); + } + + @Test + public void testSetReplacer(){ + cipher.setReplacer('a'); + + assertEquals('A', cipher.replacer); + verify(logger, times(1)).debug("Setting replacer"); + verify(logger, times(1)).debug("Original character {}", 'a'); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replaced"); + verify(logger, times(1)).debug("Checking same as doubled"); + verify(logger, times(1)).debug("Removing capitals"); + verify(logger, times(1)).debug("Setting replacer to {}", 'A'); + } + + @Test + public void testSetReplacer_capital(){ + cipher.preserveCapitals = true; + + cipher.setReplacer('a'); + + assertEquals('a', cipher.replacer); + verify(logger, times(1)).debug("Setting replacer"); + verify(logger, times(1)).debug("Original character {}", 'a'); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replaced"); + verify(logger, times(1)).debug("Checking same as doubled"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, times(1)).debug("Setting replacer to {}", 'a'); + } + + @Test + public void testSetReplacer_digital(){ + assertThrows(InvalidCharacterException.class, () -> { + cipher.setReplacer('1'); + }); + + assertEquals('I', cipher.replacer); + verify(logger, times(1)).debug("Setting replacer"); + verify(logger, times(1)).debug("Original character {}", '1'); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, never()).debug("Checking same as replaced"); + verify(logger, never()).debug("Checking same as doubled"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug(eq("Setting replacer to {}"), anyChar()); + } + + @Test + public void testSetReplacer_replaced(){ + assertThrows(InvalidCharacterException.class, () -> { + cipher.setReplacer(cipher.replaced); + }); + + assertEquals('I', cipher.replacer); + verify(logger, times(1)).debug("Setting replacer"); + verify(logger, times(1)).debug("Original character {}", cipher.replaced); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replaced"); + verify(logger, never()).debug("Checking same as doubled"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug(eq("Setting replacer to {}"), anyChar()); + } + + @Test + public void testSetReplacer_doubled(){ + assertThrows(InvalidCharacterException.class, () -> { + cipher.setReplacer(cipher.doubled); + }); + + assertEquals('I', cipher.replacer); + verify(logger, times(1)).debug("Setting replacer"); + verify(logger, times(1)).debug("Original character {}", cipher.doubled); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replaced"); + verify(logger, times(1)).debug("Checking same as doubled"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug(eq("Setting replacer to {}"), anyChar()); + } + + @Test + public void testSetReplaced(){ + cipher.setReplaced('a'); + + assertEquals('A', cipher.replaced); + verify(logger, times(1)).debug("Setting replaced"); + verify(logger, times(1)).debug("Original character {}", 'a'); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replacer"); + verify(logger, times(1)).debug("Checking same as doubled"); + verify(logger, times(1)).debug("Removing capitals"); + verify(logger, times(1)).debug("Setting replaced to {}", 'A'); + } + + @Test + public void testSetReplaced_capital(){ + cipher.preserveCapitals = true; + + cipher.setReplaced('a'); + + assertEquals('a', cipher.replaced); + verify(logger, times(1)).debug("Setting replaced"); + verify(logger, times(1)).debug("Original character {}", 'a'); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replacer"); + verify(logger, times(1)).debug("Checking same as doubled"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, times(1)).debug("Setting replaced to {}", 'a'); + } + + @Test + public void testSetReplaced_digital(){ + assertThrows(InvalidCharacterException.class, () -> { + cipher.setReplaced('1'); + }); + + assertEquals('J', cipher.replaced); + verify(logger, times(1)).debug("Setting replaced"); + verify(logger, times(1)).debug("Original character {}", '1'); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, never()).debug("Checking same as replacer"); + verify(logger, never()).debug("Checking same as doubled"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug(eq("Setting replaced to {}"), anyChar()); + } + + @Test + public void testSetReplaced_replacer(){ + assertThrows(InvalidCharacterException.class, () -> { + cipher.setReplaced(cipher.replacer); + }); + + assertEquals('J', cipher.replaced); + verify(logger, times(1)).debug("Setting replaced"); + verify(logger, times(1)).debug("Original character {}", cipher.replacer); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replacer"); + verify(logger, never()).debug("Checking same as doubled"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug(eq("Setting replaced to {}"), anyChar()); + } + + @Test + public void testSetReplaced_doubled(){ + assertThrows(InvalidCharacterException.class, () -> { + cipher.setReplaced(cipher.doubled); + }); + + assertEquals('J', cipher.replaced); + verify(logger, times(1)).debug("Setting replaced"); + verify(logger, times(1)).debug("Original character {}", cipher.doubled); + verify(logger, times(1)).debug("Checking letter"); + verify(logger, times(1)).debug("Checking same as replacer"); + verify(logger, times(1)).debug("Checking same as doubled"); + verify(logger, never()).debug("Removing capitals"); + verify(logger, never()).debug(eq("Setting replaced to {}"), anyChar()); + } + + @Test + public void testCreateGrid(){ + String expectedGridString = "[P L A Y F]\n[I R E X M]\n[B C D G H]\n[K N O Q S]\n[T U V W Z]"; + cipher.keyword = keywordClean; + + cipher.createGrid(); + + assertArrayEquals(grid, cipher.grid); + verify(logger, times(1)).debug("Creating grid from keyword"); + verify(logger, times(25)).debug(eq("Letter {} going to position [{}] [{}]"), anyChar(), anyInt(), anyInt()); + verify(logger, times(1)).debug("Grid\n{}", expectedGridString); + } + + @Test + public void testSetInputString(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.doubled = 'x'; + + cipher.setInputString(inputString, true); + + assertEquals(inputStringPadded, cipher.inputString); + verify(logger, times(1)).debug("Setting input string"); + verify(logger, times(1)).debug("Original input string {}", inputString); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + } + + @Test + public void testSetInputString_noCapitals(){ + cipher.preserveCapitals = false; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.doubled = 'X'; + + cipher.setInputString(inputString, true); + + assertEquals(inputStringPadded.toUpperCase(), cipher.inputString); + verify(logger, times(1)).debug("Setting input string"); + verify(logger, times(1)).debug("Original input string {}", inputString); + verify(logger, times(1)).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + } + + @Test + public void testSetInputString_noWhitespace(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = false; + cipher.preserveSymbols = true; + cipher.doubled = 'x'; + + cipher.setInputString(inputString, true); + + assertEquals(inputStringPadded.replaceAll("\\s", ""), cipher.inputString); + verify(logger, times(1)).debug("Setting input string"); + verify(logger, times(1)).debug("Original input string {}", inputString); + verify(logger, never()).debug("Removing case"); + verify(logger, times(1)).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + } + + @Test + public void testSetInputString_noSymbols(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = false; + cipher.doubled = 'x'; + + cipher.setInputString(inputString, true); + + assertEquals(inputStringPadded.replaceAll("[^a-zA-Z\\s]", ""), cipher.inputString); + verify(logger, times(1)).debug("Setting input string"); + verify(logger, times(1)).debug("Original input string {}", inputString); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, times(1)).debug("Removing symbols"); + } + + @Test + public void testSetInputString_blank(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.doubled = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputString("", true); + }); + + assertEquals("", cipher.inputString); + verify(logger, times(1)).debug("Setting input string"); + verify(logger, times(1)).debug("Original input string {}", ""); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + } + + @Test + public void testSetInputString_decoding(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.doubled = 'x'; + + cipher.setInputString(outputString, false); + + assertEquals(outputString, cipher.inputString); + verify(logger, times(1)).debug("Setting input string"); + verify(logger, times(1)).debug("Original input string {}", outputString); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Clean input string '{}'", outputString); + } + + @Test + public void testSetInputString_decodingContainsReplaced(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.doubled = 'x'; + + assertThrows(InvalidCharacterException.class, () -> { + cipher.setInputString(outputString + Character.toString(cipher.replaced), false); + }); + + assertEquals("", cipher.inputString); + verify(logger, times(1)).debug("Setting input string"); + verify(logger, times(1)).debug("Original input string {}", outputString + Character.toString(cipher.replaced)); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, never()).debug("Clean input string '{}'", outputString); + } + + @Test + public void testSetInputString_decodingOddLength(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.doubled = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputString(outputString + "a", false); + }); + + assertEquals(outputString + "a", cipher.inputString); + verify(logger, times(1)).debug("Setting input string"); + verify(logger, times(1)).debug("Original input string {}", outputString + "a"); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, times(1)).debug("Clean input string '{}'", outputString + "a"); + } + + @Test + public void testSetInputString_blankClean(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.doubled = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputString("**", true); + }); + + assertEquals("**", cipher.inputString); + verify(logger, times(1)).debug("Setting input string"); + verify(logger, times(1)).debug("Original input string {}", "**"); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, never()).debug("Clean input string '{}'", "**"); + } + + @Test + public void testSetInputString_null(){ + cipher.preserveCapitals = true; + cipher.preserveWhitespace = true; + cipher.preserveSymbols = true; + cipher.doubled = 'x'; + + assertThrows(InvalidInputException.class, () -> { + cipher.setInputString(null, true); + }); + + assertEquals("", cipher.inputString); + verify(logger, times(1)).debug("Setting input string"); + verify(logger, never()).debug(eq("Original input string {}"), anyString()); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing whitespace"); + verify(logger, never()).debug("Removing symbols"); + verify(logger, never()).debug(eq("Clean input string '{}'"), anyString()); + } + + @Test + public void testSetInputStringEncode(){ + cipher.doubled = 'x'; + + cipher.setInputStringEncode(inputString); + + assertEquals(inputStringPadded, cipher.inputString); + verify(logger, times(1)).debug("Cleaning up input string for encoding"); + verify(logger, times(1)).debug("Replacing all {} with {}", cipher.replaced, cipher.replacer); + verify(logger, times(13)).debug(eq("Starting at character {}"), anyInt()); + verify(logger, times(13)).debug(eq("Adding to clean input: {} {} {} {}"), any(StringBuilder.class), anyChar(), any(StringBuilder.class), anyChar()); + verify(logger, times(1)).debug("Checking odd characters"); + verify(logger, never()).debug("Adding final character to make even"); + verify(logger, times(1)).debug("Cleaned input string '{}'", inputStringPadded); + } + + @Test + public void testSetInputStringEncode_odd(){ + cipher.doubled = 'x'; + + cipher.setInputStringEncode(inputStringPadded + 'a'); + + assertEquals(inputStringPadded + "ax", cipher.inputString); + verify(logger, times(1)).debug("Cleaning up input string for encoding"); + verify(logger, times(1)).debug("Replacing all {} with {}", cipher.replaced, cipher.replacer); + verify(logger, times(14)).debug(eq("Starting at character {}"), anyInt()); + verify(logger, times(14)).debug(eq("Adding to clean input: {} {} {} {}"), any(StringBuilder.class), anyChar(), any(StringBuilder.class), anyChar()); + verify(logger, times(1)).debug("Checking odd characters"); + verify(logger, times(1)).debug("Adding final character to make even"); + verify(logger, times(1)).debug("Cleaned input string '{}'", inputStringPadded + "ax"); + } + + @Test + public void testSetInputString_oddEndSymbol(){ + cipher.doubled = 'x'; + + cipher.setInputStringEncode(inputStringPadded + "a*"); + + assertEquals(inputStringPadded + "a*x", cipher.inputString); + verify(logger, times(1)).debug("Cleaning up input string for encoding"); + verify(logger, times(1)).debug("Replacing all {} with {}", cipher.replaced, cipher.replacer); + verify(logger, times(14)).debug(eq("Starting at character {}"), anyInt()); + verify(logger, times(14)).debug(eq("Adding to clean input: {} {} {} {}"), any(StringBuilder.class), anyChar(), any(StringBuilder.class), anyChar()); + verify(logger, times(1)).debug("Checking odd characters"); + verify(logger, times(1)).debug("Adding final character to make even"); + verify(logger, times(1)).debug("Cleaned input string '{}'", inputStringPadded + "a*x"); + } + + @Test + public void testSetInputString_oddEndDoubled(){ + cipher.doubled = 'x'; + cipher.replacer = 'i'; + + cipher.setInputStringEncode(inputStringPadded + 'x'); + + assertEquals(inputStringPadded + "xi", cipher.inputString); + verify(logger, times(1)).debug("Cleaning up input string for encoding"); + verify(logger, times(1)).debug("Replacing all {} with {}", cipher.replaced, cipher.replacer); + verify(logger, times(14)).debug(eq("Starting at character {}"), anyInt()); + verify(logger, times(14)).debug(eq("Adding to clean input: {} {} {} {}"), any(StringBuilder.class), anyChar(), any(StringBuilder.class), anyChar()); + verify(logger, times(1)).debug("Checking odd characters"); + verify(logger, times(1)).debug("Adding final character to make even"); + verify(logger, times(1)).debug("Cleaned input string '{}'", inputStringPadded + "xi"); + } + + @Test + public void testGetPreparedInputString(){ + cipher.inputString = inputStringPadded; + + String output = cipher.getPreparedInputString(); + assertEquals(inputStringClean, output); + verify(logger, times(1)).debug("Getting input string ready for encoding"); + verify(logger, times(1)).debug("Prepared string '{}'", inputStringClean); + } + + @Test + public void testSetKeyword(){ + cipher.setKeyword(keyword); + + assertEquals(keywordClean, cipher.keyword); + verify(logger, times(1)).debug("Setting keyword"); + verify(logger, times(1)).debug("Original keyword {}", keyword); + verify(logger, times(1)).debug("Removing case"); + verify(logger, times(1)).debug("Removing all non-letter characters"); + verify(logger, times(1)).debug("Appending the alphabet to the keyword"); + verify(logger, times(1)).debug("Replacing {} with {}", cipher.replaced, cipher.replacer); + verify(logger, times(1)).debug("Removing duplicate characters"); + verify(logger, times(1)).debug("Cleaned keyword {}", keywordClean); + } + + @Test + public void testSetKeyword_null(){ + assertThrows(InvalidKeywordException.class, () -> { + cipher.setKeyword(null); + }); + + assertEquals("", cipher.keyword); + verify(logger, times(1)).debug("Setting keyword"); + verify(logger, never()).debug(eq("Original keyword {}"), anyString()); + verify(logger, never()).debug("Removing case"); + verify(logger, never()).debug("Removing all non-letter characters"); + verify(logger, never()).debug("Appending the alphabet to the keyword"); + verify(logger, never()).debug(eq("Replacing {} with {}"), anyChar(), anyChar()); + verify(logger, never()).debug("Removing duplicate characters"); + verify(logger, never()).debug(eq("Cleaned keyword {}"), anyString()); + } + + @Test + public void testFindChar(){ + cipher.grid = grid; + + CharLocation returnedLocation = cipher.findChar('E'); + + assertEquals(1, returnedLocation.getX()); + assertEquals(2, returnedLocation.getY()); + verify(logger, times(1)).debug("Finding character in grid {}", 'E'); + verify(logger, times(1)).debug("Found at {}, {}", 1, 2); + } + + @Test + public void testFindChar_invalid(){ + cipher.grid = grid; + + assertThrows(InvalidInputException.class, () -> { + cipher.findChar('J'); + }); + + verify(logger, times(1)).debug("Finding character in grid {}", 'J'); + verify(logger, never()).debug(eq("Found at {}, {}"), anyInt(), anyInt()); + } + + @Test + public void testGetGridChar(){ + cipher.grid = grid; + + char output = cipher.getGridChar(1, 1); + + assertEquals(grid[1][1], output); + verify(logger, times(1)).debug("Getting character from grid[{}][{}]", 1, 1); + verify(logger, times(1)).debug("Character {}", grid[1][1]); + } + + @Test + public void testGetGridChar_large(){ + cipher.grid = grid; + + char output = cipher.getGridChar(-4, -4); + + assertEquals(grid[1][1], output); + verify(logger, times(1)).debug("Getting character from grid[{}][{}]", -4, -4); + verify(logger, times(1)).debug("Character {}", grid[1][1]); + } + + @Test + public void testGetGridChar_negative(){ + cipher.grid = grid; + + char output = cipher.getGridChar(6, 6); + + assertEquals(grid[1][1], output); + verify(logger, times(1)).debug("Getting character from grid[{}][{}]", 6, 6); + verify(logger, times(1)).debug("Character {}", grid[1][1]); + } + + @Test + public void testAddCharactersToCleanString(){ + cipher.inputString = inputStringPadded; + + cipher.addCharactersToCleanString(outputStringClean); + + assertEquals(outputString, cipher.outputString); + verify(logger, times(1)).debug("Formatting output string"); + verify(logger, times(34)).debug(eq("Working character {}"), anyChar()); + verify(logger, times(1)).debug("Appending uppercase"); + verify(logger, times(25)).debug("Appending lowercase"); + verify(logger, times(8)).debug("Appending symbol"); + verify(logger, times(1)).debug("Formatted output '{}'", outputString); + } + + @Test + public void testEncode(){ + cipher.inputString = inputStringPadded; + cipher.keyword = keywordClean; + cipher.grid = grid; + + cipher.encode(); + + assertEquals(outputString, cipher.outputString); + verify(logger, times(1)).debug("Encoding"); + verify(logger, times(13)).debug(eq("Letters {} {}"), anyChar(), anyChar()); + verify(logger, times(2)).debug("Row encoding"); + verify(logger, times(1)).debug("Column encoding"); + verify(logger, times(10)).debug("Corner encoding"); + verify(logger, times(13)).debug(eq("Encoded letters {} {}"), anyChar(), anyChar()); + } + + @Test + public void testDecode(){ + cipher.inputString = outputString; + cipher.keyword = keywordClean; + cipher.grid = grid; + + cipher.decode(); + + assertEquals(inputStringPadded, cipher.outputString); + verify(logger, times(1)).debug("Decoding"); + verify(logger, times(13)).debug(eq("Letters {} {}"), anyChar(), anyChar()); + verify(logger, times(2)).debug("Row decoding"); + verify(logger, times(1)).debug("Column decoding"); + verify(logger, times(10)).debug("Corner decoding"); + verify(logger, times(13)).debug(eq("Decoded letters {} {}"), anyChar(), anyChar()); + } + + @Test + public void testReset(){ + cipher.inputString = inputString; + cipher.outputString = outputString; + cipher.keyword = keyword; + cipher.grid = grid; + + cipher.reset(); + + assertEquals("", cipher.inputString); + assertEquals("", cipher.outputString); + assertEquals("", cipher.keyword); + assertArrayEquals(new char[5][5], cipher.grid); + verify(logger, times(1)).debug("Resetting fields"); + } + + @Test + public void testGetters(){ + cipher.inputString = inputString; + cipher.outputString = outputString; + cipher.keyword = keyword; + cipher.grid = grid; + + assertEquals(inputString, cipher.getInputString()); + assertEquals(outputString, cipher.getOutputString()); + assertEquals(keyword, cipher.getKeyword()); + assertEquals("[P L A Y F]\n[I R E X M]\n[B C D G H]\n[K N O Q S]\n[T U V W Z]", cipher.getGrid()); + assertEquals('J', cipher.getReplaced()); + assertEquals('I', cipher.getReplacer()); + assertEquals('X', cipher.getDoubled()); + } + + + @Test + public void testPracticalEncode(){ + cipher = new Playfair(true, true, true); - //Test lowercase encoding - String inputString = "hidethegoldinthetreestump"; - String keyword = "Playfair Example"; - String correctOutput = "bmodzbxdnabekudmuixMmouvif"; String output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "HIDETHEGOLDINTHETREESTUMP"; - keyword = "Playfair Example"; - correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test odd letter count encoding - inputString = "hidethegoldinthetrexestum"; - keyword = "Playfair Example"; - correctOutput = "bmodzbxdnabekudmuixmmouviM"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test whitespace encoding - inputString = "hide the gold in the tree stump"; - keyword = "Playfair Example"; - correctOutput = "bmod zbx dnab ek udm uixMm ouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "hidethegoldin-the@tree+stump"; - keyword = "Playfair Example"; - correctOutput = "bmodzbxdnabek-udm@uixMm+ouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol encoding - inputString = "Hide the gold in - the@tree+stump"; - keyword = "Playfair Example"; - correctOutput = "Bmod zbx dnab ek - udm@uixMm+ouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test mixed case, whitespace, symbol encoding with mangled keyword - inputString = "Hide the gold in - the@tree+stump"; - keyword = "Play-fair@Exam ple"; - correctOutput = "Bmod zbx dnab ek - udm@uixMm+ouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); + assertEquals(inputStringPadded, cipher.inputString); + assertEquals(keywordClean, cipher.keyword); + assertEquals(outputString, cipher.outputString); + assertEquals(outputString, output); + assertArrayEquals(grid, cipher.grid); } - @Test - public void testNoWhitespaceEncode() throws InvalidCharacterException, InvalidInputException{ - Playfair cipher = new Playfair(true, false, true); - //Test lowercase encoding - String inputString = "hidethegoldinthetreestump"; - String keyword = "Playfair Example"; - String correctOutput = "bmodzbxdnabekudmuixMmouvif"; + @Test + public void testPracticalEncode_clean(){ + cipher = new Playfair(false, false, false); + String output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "HIDETHEGOLDINTHETREESTUMP"; - keyword = "Playfair Example"; - correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test odd letter count encoding - inputString = "hidethegoldinthetreestum"; - keyword = "Playfair Example"; - correctOutput = "bmodzbxdnabekudmuixMmouviM"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test whitespace encoding - inputString = "hide the gold in the tree stump"; - keyword = "Playfair Example"; - correctOutput = "bmodzbxdnabekudmuixMmouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "hidethegoldin-the@tree+stump"; - keyword = "Playfair Example"; - correctOutput = "bmodzbxdnabek-udm@uixMm+ouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol encoding - inputString = "Hide the gold in - the@tree+stump"; - keyword = "Playfair Example"; - correctOutput = "Bmodzbxdnabek-udm@uixMm+ouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test mixed case, whitespace, symbol encoding with mangled keyword - inputString = "Hide the gold in - the@tree+stump"; - keyword = "Play-fair@Exam ple"; - correctOutput = "Bmodzbxdnabek-udm@uixMm+ouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); + assertEquals(inputStringClean, cipher.inputString); + assertEquals(keywordClean, cipher.keyword); + assertEquals(outputStringClean, cipher.outputString); + assertEquals(outputStringClean, output); + assertArrayEquals(grid, cipher.grid); } + @Test - public void testNoCapitalEncode() throws InvalidCharacterException, InvalidInputException{ - Playfair cipher = new Playfair(false, true, true); + public void testPracticalDecode(){ + cipher = new Playfair(true, true, true); - //Test lowercase encoding - String inputString = "hidethegoldinthetreestump"; - String keyword = "Playfair Example"; - String correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIF"; - String output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "HIDETHEGOLDINTHETREESTUMP"; - keyword = "Playfair Example"; - correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test odd letter count encoding - inputString = "hidethegoldinthetreestum"; - keyword = "Playfair Example"; - correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIM"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); + String output = cipher.decode(keyword, outputString); - //Test whitespace encoding - inputString = "hide the gold in the tree stump"; - keyword = "Playfair Example"; - correctOutput = "BMOD ZBX DNAB EK UDM UIXMM OUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "hidethegoldin-the@tree+stump"; - keyword = "Playfair Example"; - correctOutput = "BMODZBXDNABEK-UDM@UIXMM+OUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol encoding - inputString = "Hide the gold in - the@tree+stump"; - keyword = "Playfair Example"; - correctOutput = "BMOD ZBX DNAB EK - UDM@UIXMM+OUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test mixed case, whitespace, symbol encoding with mangled keyword - inputString = "Hide the gold in - the@tree+stump"; - keyword = "Play-fair@Exam ple"; - correctOutput = "BMOD ZBX DNAB EK - UDM@UIXMM+OUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); + assertEquals(outputString, cipher.inputString); + assertEquals(keywordClean, cipher.keyword); + assertEquals(inputStringPadded, cipher.outputString); + assertEquals(inputStringPadded, output); + assertArrayEquals(grid, cipher.grid); } + @Test - public void testNoSymbolEncode() throws InvalidCharacterException, InvalidInputException{ - Playfair cipher = new Playfair(true, true, false); + public void testPracticalDecode_clean(){ + cipher = new Playfair(false, false, false); - //Test lowercase encoding - String inputString = "hidethegoldinthetreestump"; - String keyword = "Playfair Example"; - String correctOutput = "bmodzbxdnabekudmuixMmouvif"; - String output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "HIDETHEGOLDINTHETREESTUMP"; - keyword = "Playfair Example"; - correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test odd letter count encoding - inputString = "hidethegoldinthetreestum"; - keyword = "Playfair Example"; - correctOutput = "bmodzbxdnabekudmuixMmouviM"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); + String output = cipher.decode(keyword, outputString); - //Test whitespace encoding - inputString = "hide the gold in the tree stump"; - keyword = "Playfair Example"; - correctOutput = "bmod zbx dnab ek udm uixMm ouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "hidethegoldin-the@tree+stump"; - keyword = "Playfair Example"; - correctOutput = "bmodzbxdnabekudmuixMmouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol encoding - inputString = "Hide the gold in - the@tree+stump"; - keyword = "Playfair Example"; - correctOutput = "Bmod zbx dnab ek udmuixMmouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test mixed case, whitespace, symbol encoding with mangled keyword - inputString = "Hide the gold in - the@tree+stump"; - keyword = "Play-fair@Exam ple"; - correctOutput = "Bmod zbx dnab ek udmuixMmouvif"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - } - @Test - public void testNoCapitalWhitespaceSymbolEncode() throws InvalidCharacterException, InvalidInputException{ - Playfair cipher = new Playfair(false, false, false); - - //Test lowercase encoding - String inputString = "hidethegoldinthetreestump"; - String keyword = "Playfair Example"; - String correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIF"; - String output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase encoding - inputString = "HIDETHEGOLDINTHETREESTUMP"; - keyword = "Playfair Example"; - correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test odd letter count encoding - inputString = "hidethegoldinthetreestum"; - keyword = "Playfair Example"; - correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIM"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace encoding - inputString = "hide the gold in the tree stump"; - keyword = "Playfair Example"; - correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol encoding - inputString = "hidethegoldin-the@tree+stump"; - keyword = "Playfair Example"; - correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol encoding - inputString = "Hide the gold in - the@tree+stump"; - keyword = "Playfair Example"; - correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - //Test mixed case, whitespace, symbol encoding with mangled keyword - inputString = "Hide the gold in - the@tree+stump"; - keyword = "Play-fair@Exam ple"; - correctOutput = "BMODZBXDNABEKUDMUIXMMOUVIF"; - output = cipher.encode(keyword, inputString); - assertEquals(correctOutput, output); - } - @Test - public void testDecode() throws InvalidCharacterException, InvalidInputException{ - Playfair cipher = new Playfair(true, true, true); - - //Test lowercase decoding - String inputString = "bmodzbxdnabekudmuixmmouvif"; - String keyword = "Playfair Example"; - String correctOutput = "hidethegoldinthetrexestump"; - String output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "BMODZBXDNABEKUDMUIXMMOUVIF"; - keyword = "Playfair Example"; - correctOutput = "HIDETHEGOLDINTHETREXESTUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test odd letter count decoding - inputString = "bmodzbxdnabekudmuixmmouvim"; - keyword = "Playfair Example"; - correctOutput = "hidethegoldinthetrexestumx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "bmod zbx dnab ek udm uixmm ouvif"; - keyword = "Playfair Example"; - correctOutput = "hide the gold in the trexe stump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "bmodzbxdnabek-udm@uixmm+ouvif"; - keyword = "Playfair Example"; - correctOutput = "hidethegoldin-the@trexe+stump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whitespace, symbol decoding - inputString = "Bmod zbx dnab ek - udm@uixmm+ouvif"; - keyword = "Playfair Example"; - correctOutput = "Hide the gold in - the@trexe+stump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test mixed case, whtiespace, symbol decoding with mangled keyword - inputString = "Bmod zbx dnab ek - udm@uixmm+ouvif"; - keyword = "Play-fair@Exam ple"; - correctOutput = "Hide the gold in - the@trexe+stump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - } - @Test - public void testNoWhitespaceDecode() throws InvalidCharacterException, InvalidInputException{ - Playfair cipher = new Playfair(true, false, true); - - //Test lowercase decoding - String inputString = "bmodzbxdnabekudmuixmmouvif"; - String keyword = "Playfair Example"; - String correctOutput = "hidethegoldinthetrexestump"; - String output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "BMODZBXDNABEKUDMUIXMMOUVIF"; - keyword = "Playfair Example"; - correctOutput = "HIDETHEGOLDINTHETREXESTUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test odd letter count decoding - inputString = "bmodzbxdnabekudmuixmmouvim"; - keyword = "Playfair Example"; - correctOutput = "hidethegoldinthetrexestumx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "bmodzbxdnabekudmuixmmouvif"; - keyword = "Playfair Example"; - correctOutput = "hidethegoldinthetrexestump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "bmodzbxdnabek-udm@uixmm+ouvif"; - keyword = "Playfair Example"; - correctOutput = "hidethegoldin-the@trexe+stump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whtiespace, symbol decoding - inputString = "Bmodzbxdnabek-udm@uixmm+ouvif"; - keyword = "Playfair Example"; - correctOutput = "Hidethegoldin-the@trexe+stump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test mixed case, whtiespace, symbol decoding with mangled keyword - inputString = "Bmod zbx dnab ek - udm@uixmm+ouvif"; - keyword = "Play-fair@Exam ple"; - correctOutput = "Hidethegoldin-the@trexe+stump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - } - @Test - public void testNoCapitalDecode() throws InvalidCharacterException, InvalidInputException{ - Playfair cipher = new Playfair(false, true, true); - - //Test lowercase decoding - String inputString = "bmodzbxdnabekudmuixmmouvif"; - String keyword = "Playfair Example"; - String correctOutput = "HIDETHEGOLDINTHETREXESTUMP"; - String output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "BMODZBXDNABEKUDMUIXMMOUVIF"; - keyword = "Playfair Example"; - correctOutput = "HIDETHEGOLDINTHETREXESTUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test odd letter count decoding - inputString = "bmodzbxdnabekudmuixmmouvim"; - keyword = "Playfair Example"; - correctOutput = "HIDETHEGOLDINTHETREXESTUMX"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "bmod zbx dnab ek udm uixmm ouvif"; - keyword = "Playfair Example"; - correctOutput = "HIDE THE GOLD IN THE TREXE STUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "bmodzbxdnabek-udm@uixmm+ouvif"; - keyword = "Playfair Example"; - correctOutput = "HIDETHEGOLDIN-THE@TREXE+STUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whtiespace, symbol decoding - inputString = "Bmod zbx dnab ek - udm@uixmm+ouvif"; - keyword = "Playfair Example"; - correctOutput = "HIDE THE GOLD IN - THE@TREXE+STUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test mixed case, whtiespace, symbol decoding with mangled keyword - inputString = "Bmod zbx dnab ek - udm@uixmm+ouvif"; - keyword = "Play-fair@Exam ple"; - correctOutput = "HIDE THE GOLD IN - THE@TREXE+STUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - } - @Test - public void testNoSymbolDecode() throws InvalidCharacterException, InvalidInputException{ - Playfair cipher = new Playfair(true, true, false); - - //Test lowercase decoding - String inputString = "bmodzbxdnabekudmuixmmouvif"; - String keyword = "Playfair Example"; - String correctOutput = "hidethegoldinthetrexestump"; - String output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "BMODZBXDNABEKUDMUIXMMOUVIF"; - keyword = "Playfair Example"; - correctOutput = "HIDETHEGOLDINTHETREXESTUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test odd letter count decoding - inputString = "bmodzbxdnabekudmuixmmouvim"; - keyword = "Playfair Example"; - correctOutput = "hidethegoldinthetrexestumx"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "bmod zbx dnab ek udm uixmm ouvif"; - keyword = "Playfair Example"; - correctOutput = "hide the gold in the trexe stump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "bmodzbxdnabek-udm@uixmm+ouvif"; - keyword = "Playfair Example"; - correctOutput = "hidethegoldinthetrexestump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whtiespace, symbol decoding - inputString = "Bmod zbx dnab ek - udm@uixmm+ouvif"; - keyword = "Playfair Example"; - correctOutput = "Hide the gold in thetrexestump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test mixed case, whtiespace, symbol decoding with mangled keyword - inputString = "Bmod zbx dnab ek - udm@uixmm+ouvif"; - keyword = "Play-fair@Exam ple"; - correctOutput = "Hide the gold in thetrexestump"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - } - @Test - public void testNoCapitalWhitespaceSymbolDecode() throws InvalidCharacterException, InvalidInputException{ - Playfair cipher = new Playfair(false, false, false); - - //Test lowercase decoding - String inputString = "bmodzbxdnabekudmuixmmouvif"; - String keyword = "Playfair Example"; - String correctOutput = "HIDETHEGOLDINTHETREXESTUMP"; - String output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test uppercase decoding - inputString = "BMODZBXDNABEKUDMUIXMMOUVIF"; - keyword = "Playfair Example"; - correctOutput = "HIDETHEGOLDINTHETREXESTUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test odd letter count decoding - inputString = "bmodzbxdnabekudmuixmmouvim"; - keyword = "Playfair Example"; - correctOutput = "HIDETHEGOLDINTHETREXESTUMX"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test whitespace decoding - inputString = "bmod zbx dnab ek udm uixmm ouvif"; - keyword = "Playfair Example"; - correctOutput = "HIDETHEGOLDINTHETREXESTUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test symbol decoding - inputString = "bmodzbxdnabek-udm@uixmm+ouvif"; - keyword = "Playfair Example"; - correctOutput = "HIDETHEGOLDINTHETREXESTUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - - //Test mixed case, whtiespace, symbol decoding - inputString = "Bmod zbx dnab ek - udm@uixmm+ouvif"; - keyword = "Playfair Example"; - correctOutput = "HIDETHEGOLDINTHETREXESTUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); - //Test mixed case, whtiespace, symbol decoding with mangled keyword - inputString = "Bmod zbx dnab ek - udm@uixmm+ouvif"; - keyword = "Play-fair@Exam ple"; - correctOutput = "HIDETHEGOLDINTHETREXESTUMP"; - output = cipher.decode(keyword, inputString); - assertEquals(correctOutput, output); + assertEquals(outputStringClean, cipher.inputString); + assertEquals(keywordClean, cipher.keyword); + assertEquals(inputStringClean, cipher.outputString); + assertEquals(inputStringClean, output); + assertArrayEquals(grid, cipher.grid); } }