From 4e1d76296fa3856569531c92ff09162e194c9424 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Wed, 9 Sep 2026 13:11:04 +0200 Subject: [PATCH] test: cover predicateKeywordsAreRecognized --- src/test/kotlin/kestrel/LexerTest.kt | 136 +++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/src/test/kotlin/kestrel/LexerTest.kt b/src/test/kotlin/kestrel/LexerTest.kt index 702395e..c333de9 100644 --- a/src/test/kotlin/kestrel/LexerTest.kt +++ b/src/test/kotlin/kestrel/LexerTest.kt @@ -105,4 +105,140 @@ class LexerTest { fun unexpectedCharacterFails() { assertFailsWith { lex("SELECT @") } } + + @Test + fun predicateKeywordsAreRecognized() { + assertEquals( + listOf( + TokenType.Is, TokenType.In, TokenType.Between, TokenType.Like, + TokenType.Case, TokenType.When, TokenType.Then, TokenType.Else, TokenType.End, + TokenType.EndOfInput + ), + types("IS in Between LIKE case WHEN then ELSE end") + ) + } + + @Test + fun existsKeywordIsRecognizedAndCaseInsensitive() { + assertEquals(listOf(TokenType.Exists, TokenType.Exists, TokenType.EndOfInput), types("EXISTS exists")) + } + + @Test + fun viewAndReplaceKeywordsAreRecognizedAndCaseInsensitive() { + assertEquals( + listOf(TokenType.View, TokenType.Replace, TokenType.View, TokenType.Replace, TokenType.EndOfInput), + types("VIEW REPLACE view replace") + ) + } + + @Test + fun compoundQueryKeywordsAreRecognizedAndCaseInsensitive() { + assertEquals( + listOf( + TokenType.Union, TokenType.All, TokenType.Intersect, TokenType.Except, + TokenType.Union, TokenType.All, TokenType.Intersect, TokenType.Except, + TokenType.EndOfInput + ), + types("UNION ALL INTERSECT EXCEPT union all intersect except") + ) + } + + @Test + fun withAndRecursiveKeywordsAreRecognizedAndCaseInsensitive() { + assertEquals( + listOf(TokenType.With, TokenType.Recursive, TokenType.With, TokenType.Recursive, TokenType.EndOfInput), + types("WITH RECURSIVE with recursive") + ) + } + + @Test + fun castCascadeRestrictDecimalAndDateKeywordsAreRecognizedAndCaseInsensitive() { + assertEquals( + listOf( + TokenType.Cast, TokenType.Cascade, TokenType.Restrict, TokenType.Decimal, TokenType.Date, + TokenType.Cast, TokenType.Cascade, TokenType.Restrict, TokenType.Decimal, TokenType.Date, + TokenType.EndOfInput + ), + types("CAST CASCADE RESTRICT DECIMAL DATE cast cascade restrict decimal date") + ) + } + + @Test + fun foreignKeyKeywordsAreRecognizedAndCaseInsensitive() { + assertEquals( + listOf( + TokenType.Foreign, TokenType.Key, TokenType.References, TokenType.Check, + TokenType.No, TokenType.Action, + TokenType.Foreign, TokenType.Key, TokenType.References, TokenType.Check, + TokenType.No, TokenType.Action, + TokenType.EndOfInput + ), + types("FOREIGN KEY REFERENCES CHECK NO ACTION foreign key references check no action") + ) + } + + @Test + fun uniqueKeywordIsRecognizedAndCaseInsensitive() { + assertEquals( + listOf(TokenType.Unique, TokenType.Unique, TokenType.EndOfInput), + types("UNIQUE unique") + ) + } + + @Test + fun prepareExecuteAndDeallocateKeywordsAreRecognizedAndCaseInsensitive() { + assertEquals( + listOf( + TokenType.Prepare, TokenType.Execute, TokenType.Deallocate, + TokenType.Prepare, TokenType.Execute, TokenType.Deallocate, + TokenType.EndOfInput + ), + types("PREPARE EXECUTE DEALLOCATE prepare execute deallocate") + ) + } + + @Test + fun tempAndTemporaryKeywordsAreRecognizedAndCaseInsensitive() { + assertEquals( + listOf(TokenType.Temp, TokenType.Temporary, TokenType.Temp, TokenType.Temporary, TokenType.EndOfInput), + types("TEMP TEMPORARY temp temporary") + ) + } + + @Test + fun collateKeywordIsRecognizedAndCaseInsensitive() { + assertEquals( + listOf(TokenType.Collate, TokenType.Collate, TokenType.EndOfInput), + types("COLLATE collate") + ) + } + + @Test + fun parameterTokenCarriesItsOneBasedIndex() { + val token = lex("\$1").first() + assertEquals(TokenType.Parameter, token.type) + assertEquals(1L, token.intValue) + assertEquals("\$1", token.lexeme) + } + + @Test + fun parameterTokenSupportsMultipleDigits() { + val token = lex("\$42").first() + assertEquals(TokenType.Parameter, token.type) + assertEquals(42L, token.intValue) + } + + @Test + fun consecutiveParametersLexAsSeparateTokens() { + assertEquals( + listOf(TokenType.Parameter, TokenType.Comma, TokenType.Parameter, TokenType.EndOfInput), + types("\$1,\$2") + ) + } + + @Test + fun dollarSignWithNoFollowingDigitIsALexError() { + assertFailsWith { lex("\$") } + assertFailsWith { lex("\$abc") } + } }