Clean up scanner tests

This commit is contained in:
Mike Cifelli 2018-07-22 11:10:00 -04:00
parent e60f253552
commit cb0e8a1d15
5 changed files with 72 additions and 103 deletions

View File

@ -2,7 +2,7 @@ package scanner
import error.CriticalLispException
abstract class LispInputStream: AbstractIterator<Int>() {
abstract class LispInputStream : AbstractIterator<Int>() {
abstract fun read(): Int
abstract fun unreadLastCharacter()

View File

@ -5,15 +5,12 @@ import file.FilePosition
import file.FilePositionTracker
import token.Token
import token.TokenFactoryImpl
import util.Characters
import util.Characters.BACKSLASH
import util.Characters.DOUBLE_QUOTE
import util.Characters.EOF
import util.Characters.NEWLINE
import util.Characters.isIdentifierCharacter
import util.Characters.isNumberPrefix
import java.io.InputStream
import java.lang.Character.isDigit
import java.lang.Character.isWhitespace
/**
@ -71,10 +68,10 @@ class LispScanner(inputStream: InputStream, fileName: String) {
ComplexTokenTextRetriever(firstDoubleQuote) { true }.retrieveToken()
private fun retrieveNumberTokenText(firstCharacter: Char) =
ComplexTokenTextRetriever(firstCharacter, Character::isDigit).retrieveToken()
ComplexTokenTextRetriever(firstCharacter) { it.isDigit() }.retrieveToken()
private fun retrieveIdentifierTokenText(firstCharacter: Char) =
ComplexTokenTextRetriever(firstCharacter, Characters::isIdentifierCharacter).retrieveToken()
ComplexTokenTextRetriever(firstCharacter) { isIdentifierCharacter(it) }.retrieveToken()
private inner class ComplexTokenTextRetriever(private val firstCharacter: Char,
private val isPartOfToken: (Char) -> Boolean) {

View File

@ -1,144 +1,127 @@
package scanner
import file.FilePosition
import org.junit.Test
import token.Token
import java.io.InputStream
import org.junit.Assert.assertTrue
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import testutil.TestUtilities.createInputStreamFromString
class LispScannerLineColumnTest {
private class LineColumn {
private var line: Int = 0
private var column: Int = 0
fun isEqual(position: FilePosition): Boolean {
return this.line == position.lineNumber && this.column == position.columnNumber
}
companion object {
const val TEST_FILE = "testFile"
}
fun create(line: Int, column: Int): LineColumn {
val lineColumn = LineColumn()
lineColumn.line = line
lineColumn.column = column
return lineColumn
}
}
}
private data class LineColumn(val line: Int = 0, val column: Int = 0)
private fun assertTokenLineAndColumnsMatch(input: String, expectedLineColumnList: Array<LineColumn>) {
val stringInputStream = createInputStreamFromString(input)
val lispScanner = LispScanner(stringInputStream, "testFile")
val lispScanner = LispScanner(stringInputStream, TEST_FILE)
for (lineColumn in expectedLineColumnList) {
val nextToken = lispScanner.nextToken
assertTrue(lineColumn.isEqual(nextToken.position))
val position = lispScanner.nextToken.position
val expectedPosition = FilePosition(TEST_FILE, lineColumn.line, lineColumn.column)
assertThat(position).isEqualTo(expectedPosition)
}
}
@Test
fun givenNothing_RecordsCorrectEofLocation() {
fun `location of EOF`() {
val input = ""
val expectedLinesAndColumns = arrayOf(LineColumn.create(1, 0))
val expectedLinesAndColumns = arrayOf(LineColumn(1, 0))
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns)
}
@Test
fun givenSimpleString_RecordsCorrectLocation() {
fun `location of a string`() {
val input = "\"string\""
val expectedLinesAndColumns = arrayOf(LineColumn.create(1, 1))
val expectedLinesAndColumns = arrayOf(LineColumn(1, 1))
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns)
}
@Test
fun givenStringWithTrailingSpace_RecordsCorrectLocation() {
fun `location of a string with a trailing space`() {
val input = "\"string\" "
val expectedLinesAndColumns = arrayOf(LineColumn.create(1, 1))
val expectedLinesAndColumns = arrayOf(LineColumn(1, 1))
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns)
}
@Test
fun givenIdentifier_RecordsCorrectLocation() {
fun `location of an identifier`() {
val input = "identifier"
val expectedLinesAndColumns = arrayOf(LineColumn.create(1, 1))
val expectedLinesAndColumns = arrayOf(LineColumn(1, 1))
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns)
}
@Test
fun givenIdentifierWithTrailingSpace_RecordsCorrectLocation() {
fun `location of an identifier with a trailing space`() {
val input = "identifier "
val expectedLinesAndColumns = arrayOf(LineColumn.create(1, 1))
val expectedLinesAndColumns = arrayOf(LineColumn(1, 1))
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns)
}
@Test
fun givenNumber_RecordsCorrectLocation() {
fun `location of a number`() {
val input = "123456789"
val expectedLinesAndColumns = arrayOf(LineColumn.create(1, 1))
val expectedLinesAndColumns = arrayOf(LineColumn(1, 1))
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns)
}
@Test
fun givenNumberWithTrailingSpace_RecordsCorrectLocation() {
fun `location of a number with a trailing space`() {
val input = "123456789 "
val expectedLinesAndColumns = arrayOf(LineColumn.create(1, 1))
val expectedLinesAndColumns = arrayOf(LineColumn(1, 1))
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns)
}
@Test
fun givenMultipleStrings_RecordsCorrectLocations() {
fun `locations of multiple strings`() {
val input = "\"string1\" \n \"string2 \n with newline\" \n \"string3\""
val expectedLinesAndColumns = arrayOf(LineColumn.create(1, 1), LineColumn.create(2, 2), LineColumn.create(4, 3))
val expectedLinesAndColumns = arrayOf(LineColumn(1, 1), LineColumn(2, 2), LineColumn(4, 3))
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns)
}
@Test
fun givenQuotedList_RecordsCorrectLocations() {
fun `locations of a quoted list`() {
val input = "'(1 2 3 4 5)"
val expectedLinesAndColumns = arrayOf(LineColumn.create(1, 1),
LineColumn.create(1, 2),
LineColumn.create(1, 3),
LineColumn.create(1, 5),
LineColumn.create(1, 7),
LineColumn.create(1, 9),
LineColumn.create(1, 11),
LineColumn.create(1, 12))
val expectedLinesAndColumns = arrayOf(LineColumn(1, 1),
LineColumn(1, 2),
LineColumn(1, 3),
LineColumn(1, 5),
LineColumn(1, 7),
LineColumn(1, 9),
LineColumn(1, 11),
LineColumn(1, 12))
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns)
}
@Test
fun givenListSpanningMultipleLines_RecordsCorrectLocations() {
fun `locations of a list spanning multiple lines`() {
val input = " ( 1 2 \n 3 4 \n5 ) "
val expectedLinesAndColumns = arrayOf(LineColumn.create(1, 2),
LineColumn.create(1, 4),
LineColumn.create(1, 6),
LineColumn.create(2, 2),
LineColumn.create(2, 4),
LineColumn.create(3, 1),
LineColumn.create(3, 3))
val expectedLinesAndColumns = arrayOf(LineColumn(1, 2),
LineColumn(1, 4),
LineColumn(1, 6),
LineColumn(2, 2),
LineColumn(2, 4),
LineColumn(3, 1),
LineColumn(3, 3))
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns)
}
@Test
fun givenCommentImmediatelyFollowingNumber_RecordsCorrectLocations() {
fun `locations of numbers separated by a comment`() {
val input = "12;comment\n34"
val expectedLinesAndColumns = arrayOf(LineColumn.create(1, 1), LineColumn.create(2, 1))
val expectedLinesAndColumns = arrayOf(LineColumn(1, 1), LineColumn(2, 1))
assertTokenLineAndColumnsMatch(input, expectedLinesAndColumns)
}

View File

@ -1,44 +1,36 @@
package scanner
import file.FilePosition
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import java.io.InputStream
import org.junit.Assert.assertEquals
import testutil.TestUtilities.createInputStreamFromString
class LispScannerTextTest {
private fun assertTokenTextMatches(input: String, expectedTextList: Array<String>) {
private fun assertTokenTextMatches(input: String, expectedText: Array<String>) {
val lispScanner = createLispScanner(input)
for (expectedText in expectedTextList)
assertEquals(expectedText, lispScanner.nextToken.text)
for (expected in expectedText)
assertThat(lispScanner.nextToken.text).isEqualTo(expected)
}
private fun assertTokenTextMatches(input: String, expectedText: String) {
private fun assertTokenTextMatches(input: String, expected: String) {
val lispScanner = createLispScanner(input)
assertEquals(expectedText, lispScanner.nextToken.text)
assertThat(lispScanner.nextToken.text).isEqualTo(expected)
}
private fun createLispScanner(input: String): LispScanner {
val stringInputStream = createInputStreamFromString(input)
return LispScanner(stringInputStream, "testFile")
}
private fun createLispScanner(input: String) = LispScanner(createInputStreamFromString(input), "testFile")
private fun assertInputFileNameMatches(input: String, expectedInputFileName: String) {
val stringInputStream = createInputStreamFromString(input)
val lispScanner = LispScanner(stringInputStream, expectedInputFileName)
val (fileName) = lispScanner.nextToken.position
assertEquals(expectedInputFileName, fileName)
assertThat(fileName).isEqualTo(expectedInputFileName)
}
@Test
fun givenEmptyStream_RecordsCorrectFileName() {
fun `an empty stream records the correct file name`() {
val input = ""
val expectedFileName = "testFileName"
@ -46,7 +38,7 @@ class LispScannerTextTest {
}
@Test
fun givenParenthesis_RecordsCorrectText() {
fun `scan parenthesis`() {
val input = "()"
val expected = arrayOf("(", ")")
@ -54,7 +46,7 @@ class LispScannerTextTest {
}
@Test
fun givenQuote_RecordsCorrectText() {
fun `scan a quote`() {
val input = "'"
val expected = "'"
@ -62,7 +54,7 @@ class LispScannerTextTest {
}
@Test
fun givenEof_ReordsCorrectText() {
fun `scan EOF`() {
val input = ""
val expected = "EOF"
@ -70,28 +62,28 @@ class LispScannerTextTest {
}
@Test
fun givenIdentifier_RecordsCorrectText() {
fun `scan an identifier`() {
val input = "identifier"
assertTokenTextMatches(input, input)
}
@Test
fun givenNumber_RecordsCorrectText() {
fun `scan a number`() {
val input = "192837456"
assertTokenTextMatches(input, input)
}
@Test
fun givenString_RecordsCorrectText() {
fun `scan a string`() {
val input = "\"String!!! \n More... \""
assertTokenTextMatches(input, input)
}
@Test
fun givenNumberFollowedByComment_RecordsCorrectText() {
fun `scan a number followed by a comment`() {
val input = "192837456;comment"
val expected = "192837456"
@ -99,7 +91,7 @@ class LispScannerTextTest {
}
@Test
fun givenIdentifiersWithCommentBetween_RecordsCorrectText() {
fun `scan identifiers separated by a comment`() {
val input = "abc123;comment\nabc222"
val expected = arrayOf("abc123", "abc222")
@ -107,7 +99,7 @@ class LispScannerTextTest {
}
@Test
fun givenBackTickExpression_RecordsCorrectText() {
fun `scan a back tick expression`() {
val input = "`(list ,a ,@b)"
val expected = arrayOf("`", "(", "list", ",", "a", ",", "@", "b", ")")

View File

@ -1,8 +1,13 @@
package scanner
import error.Severity.ERROR
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import scanner.LispScanner.UnterminatedStringException
import testutil.TestUtilities.createInputStreamFromString
import token.AtSign
import token.Backquote
import token.Comma
@ -15,16 +20,8 @@ import token.QuotedString
import token.RightParenthesis
import token.Token
import token.TokenFactory.BadCharacterException
import java.io.InputStream
import java.util.ArrayList
import error.Severity.ERROR
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import testutil.TestUtilities.createInputStreamFromString
class LispScannerTypeTest {
private var expectedTypes: MutableList<Class<out Token>>? = null