//CipherStreamJava/src/test/java/com/mattrixwv/CipherStreamJava/monoSubstitution/TestSubstitution.java //Mattrixwv // Created: 02-22-22 //Modified: 04-18-23 package com.mattrixwv.cipherstream.monosubstitution; 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.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.InvalidInputException; import com.mattrixwv.cipherstream.exceptions.InvalidKeywordException; public class TestSubstitution{ private Substitution cipher; private Logger logger; //Variables private String decodedString = "Message to^encode"; private String decodedStringClean = "MESSAGETOENCODE"; private String decodedStringAlNum = "Message to^encode 123"; private String decodedStringAlNumClean = "MESSAGETOENCODE"; private String encodedString = "Oguucig vq^gpeqfg"; private String encodedStringClean = "OGUUCIGVQGPEQFG"; private String encodedStringAlNum = "Oguucig vq^gpeqfg 876"; private String encodedStringAlNumClean = "OGUUCIGVQGPEQFG"; private String keyword = "cdefghijklmnopqrstuvwxyzab"; private String keywordAlNum = "cdefghijklmnopqrstuvwxyzab9876543210"; @BeforeEach public void setup(){ cipher = new Substitution(); logger = mock(Logger.class); Substitution.logger = logger; } @Test public void testConstructor_default(){ cipher = new Substitution(); assertFalse(cipher.preserveCapitals); assertFalse(cipher.preserveWhitespace); assertFalse(cipher.preserveSymbols); assertEquals("", cipher.inputString); assertEquals("", cipher.outputString); assertEquals("", cipher.keyword); } @Test public void testConstructor_preservesCapitals(){ cipher = new Substitution(true, false, false); assertTrue(cipher.preserveCapitals); assertFalse(cipher.preserveWhitespace); assertFalse(cipher.preserveSymbols); assertEquals("", cipher.inputString); assertEquals("", cipher.outputString); assertEquals("", cipher.keyword); } @Test public void testConstructor_preservesWhitespace(){ cipher = new Substitution(false, true, false); assertFalse(cipher.preserveCapitals); assertTrue(cipher.preserveWhitespace); assertFalse(cipher.preserveSymbols); assertEquals("", cipher.inputString); assertEquals("", cipher.outputString); assertEquals("", cipher.keyword); } @Test public void testConstructor_preservesSymbols(){ cipher = new Substitution(false, false, true); assertFalse(cipher.preserveCapitals); assertFalse(cipher.preserveWhitespace); assertTrue(cipher.preserveSymbols); assertEquals("", cipher.inputString); assertEquals("", cipher.outputString); assertEquals("", cipher.keyword); } @Test public void testSetKey(){ cipher.setKeyword(keyword); assertEquals(keyword.toUpperCase(), cipher.keyword); verify(logger, times(1)).debug("Original key '{}'", keyword); verify(logger, times(1)).debug("Removing case"); verify(logger, times(1)).debug("Ensuring there are no duplicate mappings"); verify(logger, times(1)).debug("Ensuring there are only letters in the key"); verify(logger, never()).debug("Ensuring there are only alpha-numeric characters in the key"); verify(logger, times(1)).debug("Cleaned key '{}'", keyword.toUpperCase()); } @Test public void testSetKey_alNum(){ cipher.setKeyword(keywordAlNum); assertEquals(keywordAlNum.toUpperCase(), cipher.keyword); verify(logger, times(1)).debug("Original key '{}'", keywordAlNum); verify(logger, times(1)).debug("Removing case"); verify(logger, times(1)).debug("Ensuring there are no duplicate mappings"); verify(logger, never()).debug("Ensuring there are only letters in the key"); verify(logger, times(1)).debug("Ensuring there are only alpha-numeric characters in the key"); verify(logger, times(1)).debug("Cleaned key '{}'", keywordAlNum.toUpperCase()); } @Test public void testSetKey_duplicate(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword("ABA"); }); assertEquals("", cipher.keyword); verify(logger, times(1)).debug("Original key '{}'", "ABA"); verify(logger, times(1)).debug("Removing case"); verify(logger, times(1)).debug("Ensuring there are no duplicate mappings"); verify(logger, never()).debug("Ensuring there are only letters in the key"); verify(logger, never()).debug("Ensuring there are only alpha-numeric characters in the key"); verify(logger, never()).debug(eq("Cleaned key '{}'"), anyString()); } @Test public void testSetKey_invalidLetter(){ assertThrows(InvalidKeywordException.class, () ->{ cipher.setKeyword("abcdefghijklmnop1rstuvwxyz"); }); assertEquals("", cipher.keyword); verify(logger, times(1)).debug("Original key '{}'", "abcdefghijklmnop1rstuvwxyz"); verify(logger, times(1)).debug("Removing case"); verify(logger, times(1)).debug("Ensuring there are no duplicate mappings"); verify(logger, times(1)).debug("Ensuring there are only letters in the key"); verify(logger, never()).debug("Ensuring there are only alpha-numeric characters in the key"); verify(logger, never()).debug(eq("Cleaned key '{}'"), anyString()); } @Test public void testSetKey_invalidAlNum(){ assertThrows(InvalidKeywordException.class, () -> { cipher.setKeyword("abcdefghijklmnop^rstuvwxyz0123456789"); }); assertEquals("", cipher.keyword); verify(logger, times(1)).debug("Original key '{}'", "abcdefghijklmnop^rstuvwxyz0123456789"); verify(logger, times(1)).debug("Removing case"); verify(logger, times(1)).debug("Ensuring there are no duplicate mappings"); verify(logger, never()).debug("Ensuring there are only letters in the key"); verify(logger, times(1)).debug("Ensuring there are only alpha-numeric characters in the key"); verify(logger, never()).debug(eq("Cleaned key '{}'"), anyString()); } @Test 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"); verify(logger, times(1)).debug("Removing case"); verify(logger, times(1)).debug("Ensuring there are no duplicate mappings"); verify(logger, never()).debug("Ensuring there are only letters in the key"); verify(logger, never()).debug("Ensuring there are only alpha-numeric characters in the key"); verify(logger, never()).debug(eq("Cleaned key '{}'"), anyString()); } @Test 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()); verify(logger, never()).debug("Removing case"); verify(logger, never()).debug("Ensuring there are no duplicate mappings"); verify(logger, never()).debug("Ensuring there are only letters in the key"); verify(logger, never()).debug("Ensuring there are only alpha-numeric characters in the key"); verify(logger, never()).debug(eq("Cleaned key '{}'"), anyString()); } @Test public void testSetInputString(){ cipher.preserveCapitals = true; cipher.preserveWhitespace = true; cipher.preserveSymbols = true; cipher.setInputString(decodedString); assertEquals(decodedString, cipher.inputString); 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("Cleaned input string '{}'", decodedString); } @Test public void testSetInputString_noCapitals(){ cipher.preserveCapitals = false; cipher.preserveWhitespace = true; cipher.preserveSymbols = true; cipher.setInputString(decodedString); assertEquals(decodedString.toUpperCase(), cipher.inputString); 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("Cleaned input string '{}'", decodedString.toUpperCase()); } @Test public void testSetInputString_noWhitespace(){ cipher.preserveCapitals = true; cipher.preserveWhitespace = false; cipher.preserveSymbols = true; cipher.setInputString(decodedString); assertEquals(decodedString.replaceAll("\\s", ""), cipher.inputString); 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("Cleaned input string '{}'", decodedString.replaceAll("\\s", "")); } @Test public void testSetInputString_noSymbols(){ cipher.preserveCapitals = true; cipher.preserveWhitespace = true; cipher.preserveSymbols = false; cipher.setInputString(decodedString); assertEquals(decodedString.replaceAll("[^a-zA-Z\\s]", ""), cipher.inputString); 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("Cleaned input string '{}'", decodedString.replaceAll("[^a-zA-Z\\s]", "")); } @Test public void testSetInputString_blank(){ cipher.preserveCapitals = true; cipher.preserveWhitespace = true; cipher.preserveSymbols = true; assertThrows(InvalidInputException.class, () -> { cipher.setInputString(""); }, "Input must contain at least 1 letter"); assertEquals("", cipher.inputString); 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 testSetInputString_null(){ cipher.preserveCapitals = true; cipher.preserveWhitespace = true; cipher.preserveSymbols = true; assertThrows(InvalidInputException.class, () -> { cipher.setInputString(null); }, "Input cannot be null"); assertEquals("", cipher.inputString); 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 testEncode(){ cipher.preserveCapitals = true; cipher.preserveWhitespace = true; cipher.preserveSymbols = true; cipher.inputString = decodedStringAlNum; cipher.keyword = keywordAlNum.toUpperCase(); cipher.encode(); assertEquals(encodedStringAlNum, cipher.outputString); verify(logger, times(1)).debug("Encoding"); verify(logger, times(21)).debug(eq("Working character {}"), anyChar()); verify(logger, times(1)).debug("Encoding uppercase"); verify(logger, times(14)).debug("Encoding lowercase"); verify(logger, times(3)).debug("Encoding digit"); verify(logger, times(3)).debug("Passing symbol through"); verify(logger, times(1)).debug("Encoded message '{}'", encodedStringAlNum); } @Test public void testDecode(){ cipher.preserveCapitals = true; cipher.preserveWhitespace = true; cipher.preserveSymbols = true; cipher.inputString = encodedStringAlNum; cipher.keyword = keywordAlNum.toUpperCase(); cipher.decode(); assertEquals(decodedStringAlNum, cipher.outputString); verify(logger, times(1)).debug("Decoding"); verify(logger, times(21)).debug(eq("Working character {}"), anyChar()); verify(logger, times(1)).debug("Encoding uppercase"); verify(logger, times(14)).debug("Encoding lowercase"); verify(logger, times(3)).debug("Encoding digit"); verify(logger, times(3)).debug("Passing symbol through"); verify(logger, times(1)).debug("Decoded message '{}'", decodedStringAlNum); } @Test public void testGetters(){ cipher.inputString = decodedString; cipher.outputString = encodedString; cipher.keyword = keyword; assertEquals(decodedString, cipher.getInputString()); assertEquals(encodedString, cipher.getOutputString()); assertEquals(keyword, cipher.getKeyword()); } @Test public void testReset(){ cipher.inputString = decodedString; cipher.outputString = encodedString; cipher.keyword = keyword; cipher.reset(); assertEquals("", cipher.inputString); assertEquals("", cipher.outputString); assertEquals("", cipher.keyword); verify(logger, times(1)).debug("Resetting fields"); } @Test public void testPracticalEncoding(){ cipher = new Substitution(true, true, true); String output = cipher.encode(keyword, decodedString); assertEquals(decodedString, cipher.inputString); assertEquals(keyword.toUpperCase(), cipher.keyword); assertEquals(encodedString, cipher.outputString); assertEquals(encodedString, output); } @Test public void testPracticalEncoding_clean(){ cipher = new Substitution(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 testPracticalEncoding_alNum(){ cipher = new Substitution(true, true, true); String output = cipher.encode(keywordAlNum, decodedStringAlNum); assertEquals(decodedStringAlNum, cipher.inputString); assertEquals(keywordAlNum.toUpperCase(), cipher.keyword); assertEquals(encodedStringAlNum, cipher.outputString); assertEquals(encodedStringAlNum, output); } @Test public void testPracticalEncoding_alNumClean(){ cipher = new Substitution(false, false, false); String output = cipher.encode(keywordAlNum, decodedStringAlNum); assertEquals(decodedStringAlNumClean, cipher.inputString); assertEquals(keywordAlNum.toUpperCase(), cipher.keyword); assertEquals(encodedStringAlNumClean, cipher.outputString); assertEquals(encodedStringAlNumClean, output); } @Test public void testPrecticalEncoding_noAlNumKey(){ cipher = new Substitution(true, true, true); String output = cipher.encode(keyword, decodedStringAlNum); assertEquals(decodedStringAlNum, cipher.inputString); assertEquals(keyword.toUpperCase(), cipher.keyword); assertEquals(encodedString + " 123", cipher.outputString); assertEquals(encodedString + " 123", output); } @Test public void testPracticalDecoding(){ cipher = new Substitution(true, true, true); String output = cipher.decode(keyword, encodedString); assertEquals(encodedString, cipher.inputString); assertEquals(keyword.toUpperCase(), cipher.keyword); assertEquals(decodedString, cipher.outputString); assertEquals(decodedString, output); } @Test public void testPracticalDecoding_clean(){ cipher = new Substitution(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); } @Test public void testPracticalDecoding_alNum(){ cipher = new Substitution(true, true, true); String output = cipher.decode(keywordAlNum, encodedStringAlNum); assertEquals(encodedStringAlNum, cipher.inputString); assertEquals(keywordAlNum.toUpperCase(), cipher.keyword); assertEquals(decodedStringAlNum, cipher.outputString); assertEquals(decodedStringAlNum, output); } @Test public void testPracticalDecoding_alNumClean(){ cipher = new Substitution(false, false, false); String output = cipher.decode(keywordAlNum, encodedStringAlNum); assertEquals(encodedStringAlNumClean, cipher.inputString); assertEquals(keywordAlNum.toUpperCase(), cipher.keyword); assertEquals(decodedStringAlNumClean, cipher.outputString); assertEquals(decodedStringAlNumClean, output); } @Test public void testPracticalDecoding_noAlNumKey(){ cipher = new Substitution(true, true, true); String output = cipher.decode(keyword, encodedString + " 123"); assertEquals(encodedString + " 123", cipher.inputString); assertEquals(keyword.toUpperCase(), cipher.keyword); assertEquals(decodedString + " 123", cipher.outputString); assertEquals(decodedString + " 123", output); } }