package scanner; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.junit.Before; import org.junit.Test; import error.ErrorManager; import scanner.LispScanner.UnterminatedStringException; import testutils.TestUtilities; import token.Eof; import token.Identifier; import token.LeftParenthesis; import token.Number; import token.QuoteMark; import token.QuotedString; import token.RightParenthesis; import token.Token; import token.TokenFactory.BadCharacterException; public class LispScannerTypeTester { private List> expectedTypes; private void assertTokenTypesMatch(String input) { InputStream stringInputStream = TestUtilities.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) { assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL); } } @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) { assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL); } } @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 givenSingleDigitNumber_ReturnsCorrectTypes() { String input = "1"; expectedTypes.add(Number.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); } }