package scanner; import static error.ErrorManager.Severity.ERROR; import static org.junit.Assert.*; import static testutil.TestUtilities.createInputStreamFromString; import java.io.InputStream; import java.util.*; import org.junit.*; import scanner.LispScanner.UnterminatedStringException; import token.*; import token.Number; import token.TokenFactory.BadCharacterException; public class LispScannerTypeTester { private List> expectedTypes; private void assertTokenTypesMatch(String input) { InputStream stringInputStream = createInputStreamFromString(input); LispScanner lispScanner = new LispScanner(stringInputStream, "testFile"); for (Class type : expectedTypes) assertTrue(type.isInstance(lispScanner.getNextToken())); assertTrue(lispScanner.getNextToken() instanceof Eof); } @Before public void setUp() { expectedTypes = new ArrayList<>(); } @Test public void givenEmptyFile_ReturnsCorrectTypes() { String input = ""; assertTokenTypesMatch(input); } @Test(expected = BadCharacterException.class) public void givenBadCharacter_ThrowsException() { String input = "["; assertTokenTypesMatch(input); } @Test public void givenBadCharacter_ExceptionContainsCorrectSeverity() { String input = "abc\ndef["; expectedTypes.add(Identifier.class); expectedTypes.add(Identifier.class); try { assertTokenTypesMatch(input); } catch (BadCharacterException e) { assertEquals(ERROR, e.getSeverity()); } } @Test public void givenBadCharacter_ExceptionContainsMessage() { String input = "abc\ndef["; expectedTypes.add(Identifier.class); expectedTypes.add(Identifier.class); try { assertTokenTypesMatch(input); } catch (BadCharacterException e) { String message = e.getMessage(); assertNotNull(message); assertTrue(message.length() > 0); } } @Test public void givenNil_ReturnsCorrectTypes() { String input = "()"; expectedTypes.add(LeftParenthesis.class); expectedTypes.add(RightParenthesis.class); assertTokenTypesMatch(input); } @Test public void givenListOfNumbers_ReturnsCorrectTypes() { String input = "(1 2)"; expectedTypes.add(LeftParenthesis.class); expectedTypes.add(Number.class); expectedTypes.add(Number.class); expectedTypes.add(RightParenthesis.class); assertTokenTypesMatch(input); } @Test public void givenString_ReturnsCorrectTypes() { String input = "\"string\""; expectedTypes.add(QuotedString.class); assertTokenTypesMatch(input); } @Test public void givenStringWithEscapedDoubleQuote_ReturnsCorrectTypes() { String input = "\"string \n hi \\\" bye\""; expectedTypes.add(QuotedString.class); assertTokenTypesMatch(input); } @Test public void givenStringWithEscapedDoubleQuoteAndComment_ReturnsCorrectTypes() { String input = "\"string \n hi \\\" ; bye\""; expectedTypes.add(QuotedString.class); assertTokenTypesMatch(input); } @Test(expected = UnterminatedStringException.class) public void givenUnterminatedString_ThrowsException() { String input = "\"oh no!"; expectedTypes.add(QuotedString.class); assertTokenTypesMatch(input); } @Test() public void givenUnterminatedString_ExceptionHasCorrectSeverity() { String input = "\"oh no!"; expectedTypes.add(QuotedString.class); try { assertTokenTypesMatch(input); } catch (LispScanner.UnterminatedStringException e) { assertEquals(ERROR, e.getSeverity()); } } @Test() public void givenUnterminatedString_ExceptionContainsMessage() { String input = "\"oh no!"; expectedTypes.add(QuotedString.class); try { assertTokenTypesMatch(input); } catch (LispScanner.UnterminatedStringException e) { String message = e.getMessage(); assertNotNull(message); assertTrue(message.length() > 0); } } @Test public void givenIdentifier_ReturnsCorrectTypes() { String input = "abcdefgHIJKLMNOP1234"; expectedTypes.add(Identifier.class); assertTokenTypesMatch(input); } @Test public void givenPrefixedIdentifiers_ReturnsCorrectTypes() { String input = "-a +b"; expectedTypes.add(Identifier.class); expectedTypes.add(Identifier.class); assertTokenTypesMatch(input); } @Test public void givenSingleDigitNumber_ReturnsCorrectTypes() { String input = "1"; expectedTypes.add(Number.class); assertTokenTypesMatch(input); } @Test public void givenPrefixedNegativeNumber_ReturnsCorrectTypes() { String input = "-1"; expectedTypes.add(Number.class); assertTokenTypesMatch(input); } @Test public void givenPrefixedNumber_ReturnsCorrectTypes() { String input = "+1"; expectedTypes.add(Number.class); assertTokenTypesMatch(input); } @Test public void givenPrefixedNegativeNumberAndIdentifier_ReturnsCorrectTypes() { String input = "-1apple"; expectedTypes.add(Number.class); expectedTypes.add(Identifier.class); assertTokenTypesMatch(input); } @Test public void givenPrefixedNumberAndIdentifier_ReturnsCorrectTypes() { String input = "+1apple"; expectedTypes.add(Number.class); expectedTypes.add(Identifier.class); assertTokenTypesMatch(input); } @Test public void givenPrefixedNegativeNumberAndString_ReturnsCorrectTypes() { String input = "-1\"apple\""; expectedTypes.add(Number.class); expectedTypes.add(QuotedString.class); assertTokenTypesMatch(input); } @Test public void givenPrefixedNumberAndString_ReturnsCorrectTypes() { String input = "+1\"apple\""; expectedTypes.add(Number.class); expectedTypes.add(QuotedString.class); assertTokenTypesMatch(input); } @Test public void givenMultipleDigitNumber_ReturnsCorrectTypes() { String input = "1234567890"; expectedTypes.add(Number.class); assertTokenTypesMatch(input); } @Test public void givenQuote_ReturnsCorrectTypes() { String input = "'"; expectedTypes.add(QuoteMark.class); assertTokenTypesMatch(input); } @Test public void givenManyTypesWithNoWhitespace_ReturnsCorrectTypes() { String input = "xxx\"hi\"999()'aaa"; expectedTypes.add(Identifier.class); expectedTypes.add(QuotedString.class); expectedTypes.add(Number.class); expectedTypes.add(LeftParenthesis.class); expectedTypes.add(RightParenthesis.class); expectedTypes.add(QuoteMark.class); expectedTypes.add(Identifier.class); assertTokenTypesMatch(input); } @Test public void givenFunctionCall_ReturnsCorrectTypes() { String input = "(defun myFunction (x)\n (print x))"; expectedTypes.add(LeftParenthesis.class); expectedTypes.add(Identifier.class); expectedTypes.add(Identifier.class); expectedTypes.add(LeftParenthesis.class); expectedTypes.add(Identifier.class); expectedTypes.add(RightParenthesis.class); expectedTypes.add(LeftParenthesis.class); expectedTypes.add(Identifier.class); expectedTypes.add(Identifier.class); expectedTypes.add(RightParenthesis.class); expectedTypes.add(RightParenthesis.class); assertTokenTypesMatch(input); } }