diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/SemanticDataRepository.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/SemanticDataRepository.kt index b6252529..c6ebdf46 100644 --- a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/SemanticDataRepository.kt +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/SemanticDataRepository.kt @@ -115,12 +115,14 @@ class SemanticDataRepository private constructor() { validatorMap.putAll(AllowedCpuSetOptionValue.validators) validatorMap.putAll(TtySizeOptionValue.validators) validatorMap.putAll(ExecDirectoriesOptionValue.validators) - validatorMap.putAll(IOLimitOptionValue.validators) + validatorMap.putAll(CGWeightOptionValue.validators) + validatorMap.putAll(BlockIOWeightOptionValue.validators) + validatorMap.putAll(BlockIOBandwidthOptionValue.validators) validatorMap.putAll(ImagePolicyOptionValue.validators) validatorMap.putAll(CPUWeightOptionValue.validators) validatorMap.putAll(CPUSharesOptionValue.validators) - + validatorMap.putAll(CgroupSocketBindOptionValue.validators) validatorMap.putAll(RlimitOptionValue.validators) // Scopes are not supported since they aren't standard unit files. fileClassToSectionNameToKeyValuesFromDoc["unit"]?.remove(SCOPE_KEYWORD) @@ -543,8 +545,6 @@ unit types. These options are documented in MatchResult): MatchResult { + var index = offset + val tokens = mutableListOf() + val terminals = mutableListOf() + + var match = f(value, index) + + + if (match.matchResult == -1) { + return MatchResult(tokens, offset, terminals, match.longestMatch) + } + + var maxLength = match.longestMatch + + + index = match.matchResult + tokens.addAll(match.tokens) + terminals.addAll(match.terminals) + + match = f(value, index) + maxLength = max(maxLength, match.longestMatch) + + return MatchResult(tokens, index, terminals, maxLength) + } + + override fun SyntacticMatch(value: String, offset: Int): MatchResult { + return match(value, offset, combinator::SyntacticMatch) + } + + override fun SemanticMatch(value: String, offset: Int): MatchResult { + return match(value, offset, combinator::SemanticMatch) + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForBlockIOBandwidthOptionValue.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForBlockIOBandwidthOptionValue.kt new file mode 100644 index 00000000..db821732 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForBlockIOBandwidthOptionValue.kt @@ -0,0 +1,110 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections + +import junit.framework.TestCase +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest + +class InvalidValueInspectionForBlockIOBandwidthOptionValue : AbstractUnitFileTest() { + + fun testNoWarningWhenNumberSpecifiedWithoutUnit() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOReadBandwidth=/home 2 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + + } + + fun testNoWarningWhenNumberSpecifiedWithUnit() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOReadBandwidth=/home 2M + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + + } + + fun testWeakWarningWhenNegativeIntegerSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOReadBandwidth=-5 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("BlockIOReadBandwidth's value does not match the expected format. Possible reasons include unrecognized characters or premature end of input.", info!!.description) + TestCase.assertEquals("-5", info.text) + } + + fun testWeakWarningWhenDeviceSpecifiedWithNoValue() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOReadBandwidth=/home + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("BlockIOReadBandwidth's value does not match the expected format. Possible reasons include unrecognized characters or premature end of input.", info!!.description) + TestCase.assertEquals("/home", info.text) + } + + + fun testWeakWarningWhenPositiveIntegerSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOReadBandwidth=5 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("BlockIOReadBandwidth's value does not match the expected format. Possible reasons include unrecognized characters or premature end of input.", info!!.description) + TestCase.assertEquals("5", info.text) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForBlockIOWeight.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForBlockIOWeight.kt new file mode 100644 index 00000000..319eda33 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForBlockIOWeight.kt @@ -0,0 +1,152 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections + +import junit.framework.TestCase +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest + +class InvalidValueInspectionForBlockBlockIOWeight : AbstractUnitFileTest() { + + fun testNoWarningWhenTenSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOWeight=10 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + } + + fun testNoWarningWhenOneThousandSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOWeight=1000 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + } + + fun testWeakWarningWhenNineIsSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOWeight=9 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("BlockIOWeight's value is correctly formatted but seems invalid", info!!.description) + TestCase.assertEquals("9", info.text) + } + + + fun testWeakWarningWhenZeroIsSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOWeight=0 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("BlockIOWeight's value is correctly formatted but seems invalid", info!!.description) + TestCase.assertEquals("0", info.text) + } + + fun testWeakWarningWhenNegativeTenIsSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOWeight=-10 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("BlockIOWeight's value is correctly formatted but seems invalid", info!!.description) + TestCase.assertEquals("-10", info.text) + } + + + fun testWeakWarningWhenNegativeHundredThousandIsSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOWeight=-100000 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("BlockIOWeight's value is correctly formatted but seems invalid", info!!.description) + TestCase.assertEquals("-100000", info.text) + } + + + fun testWeakWarningWhenOneThousandAndOneIsSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + BlockIOWeight=1001 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("BlockIOWeight's value is correctly formatted but seems invalid", info!!.description) + TestCase.assertEquals("1001", info.text) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForCGWeight.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForCGWeight.kt new file mode 100644 index 00000000..f151f3dd --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForCGWeight.kt @@ -0,0 +1,148 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections + +import junit.framework.TestCase +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest + +class InvalidValueInspectionForCGWeight : AbstractUnitFileTest() { + + fun testNoWarningWhenIdleSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + IOWeight=1000 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + } + + fun testNoWarningWhenOneSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + IOWeight=1 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + } + + fun testNoWarningWhenTenThousandSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + IOWeight=10000 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + } + + fun testWeakWarningWhenZeroIsSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + IOWeight=0 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("IOWeight's value is correctly formatted but seems invalid", info!!.description) + TestCase.assertEquals("0", info.text) + } + + fun testWeakWarningWhenNegativeTenIsSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + IOWeight=-10 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("IOWeight's value is correctly formatted but seems invalid", info!!.description) + TestCase.assertEquals("-10", info.text) + } + + + fun testWeakWarningWhenNegativeHundredThousandIsSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + IOWeight=-100000 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("IOWeight's value is correctly formatted but seems invalid", info!!.description) + TestCase.assertEquals("-100000", info.text) + } + + + fun testWeakWarningWhenTenThousandOneIsSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + IOWeight=10001 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("IOWeight's value is correctly formatted but seems invalid", info!!.description) + TestCase.assertEquals("10001", info.text) + } + +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForCGroupSocketBind.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForCGroupSocketBind.kt new file mode 100644 index 00000000..0701bebb --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/InvalidValueInspectionForCGroupSocketBind.kt @@ -0,0 +1,159 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections + +import junit.framework.TestCase +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest + +class InvalidValueInspectionForCGroupSocketBindOptionValue : AbstractUnitFileTest() { + + fun testNoWarningsWithDocumentedExamples() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + # Allow binding IPv6 socket addresses with a port greater than or equal to 10000. + SocketBindAllow=ipv6:10000-65535 + SocketBindDeny=any + # Allow binding IPv4 and IPv6 socket addresses with 1234 and 4321 ports. + + SocketBindAllow=1234 + SocketBindAllow=4321 + SocketBindDeny=any + # Deny binding IPv6 socket addresses. + SocketBindDeny=ipv6 + # Deny binding IPv4 and IPv6 socket addresses. + + SocketBindDeny=any + + # Allow binding only over TCP + + SocketBindAllow=tcp + SocketBindDeny=any + + # Allow binding only over IPv6/TCP + SocketBindAllow=ipv6:tcp + SocketBindDeny=any + + # Allow binding ports within 10000-65535 range over IPv4/UDP. + SocketBindAllow=ipv4:udp:10000-65535 + SocketBindDeny=any + + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + } + + + fun testWeakWarningWhenInvalidAddressFamilySpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + SocketBindAllow=ipv5 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("SocketBindAllow's value does not match the expected format.", info!!.description) + TestCase.assertEquals("ipv5", info.text) + } + + + fun testWeakWarningWhenInvalidTransportSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + SocketBindAllow=icmp + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("SocketBindAllow's value does not match the expected format.", info!!.description) + TestCase.assertEquals("icmp", info.text) + } + + + fun testWeakWarningWhenInvalidPortSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + SocketBindAllow=12458757 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("SocketBindAllow's value is correctly formatted but seems invalid.", info!!.description) + TestCase.assertEquals("12458757", info.text) + } + + fun testWeakWarningWhenDoubleColonSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + SocketBindAllow=ipv6::tcp + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("SocketBindAllow's value does not match the expected format.", info!!.description) + TestCase.assertEquals("::tcp", info.text) + } + + fun testWeakWarningWhenInvalidPortRangeSpecified() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Service] + SocketBindAllow=ipv6:tcp:12--21485 + """.trimIndent() + + + // Execute SUT + setupFileInEditor("file.service", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(1, highlights) + val info = highlights[0] + assertStringContains("SocketBindAllow's value is correctly formatted but seems invalid.", info!!.description) + TestCase.assertEquals("-", info.text) + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/OptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/OptionValueTest.kt index 2fe3e32b..3db54edd 100644 --- a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/OptionValueTest.kt +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/OptionValueTest.kt @@ -35,7 +35,7 @@ class OptionValueTest : AbstractUnitFileTest() { println("Missing:$totalMissingValidators") println("Found:$totalFoundValidators") - if (totalMissingValidators > 540) { + if (totalMissingValidators >= 500) { assertEquals("Number of missing validators is too high at ${totalMissingValidators} vs. found ${totalFoundValidators}", sortedList, "") } diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/grammar/Grammar.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/grammar/Grammar.kt index fed38a94..15f9eb70 100644 --- a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/grammar/Grammar.kt +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/grammar/Grammar.kt @@ -618,6 +618,101 @@ class GrammarTest : TestCase() { assertEquals(listOf(), match.tokens) } + fun testZeroOrOneCombinatorMatches() { + /** + * Fixture Setup + */ + + // This combinator should match the options passed in. + val fizzOrBuzz = RegexTerminal("[a-z]{4}", "fizz|buzz") + + val zeroOrOneCombinator = ZeroOrOne(fizzOrBuzz) + + val semValid = "fizz" + val synValid = "bleh" + val semValidEmpty = "" + val invalid = "Hello World" + val garbage = "XX" + + val semValidFromOffset = "${garbage}${semValid}" + val semValidEmptyFromOffset = "${garbage}${semValidEmpty}" + val synValidFromOffset = "${garbage}${synValid}" + val invalidFromOffset = "${garbage}${invalid}" + + /** + * Execute SUT & Verification + */ + var match = zeroOrOneCombinator.SyntacticMatch(semValid, 0) + assertEquals(semValid.length, match.matchResult) + assertEquals(listOf("fizz"), match.tokens) + assertEquals(listOf("RegexTerminal"), TerminalTypes(match.terminals)) + + match = zeroOrOneCombinator.SemanticMatch(semValid, 0) + assertEquals(semValid.length, match.matchResult) + assertEquals(listOf("fizz"), match.tokens) + assertEquals(listOf("RegexTerminal"), TerminalTypes(match.terminals)) + + match = zeroOrOneCombinator.SyntacticMatch(synValid, 0) + assertEquals(synValid.length, match.matchResult) + assertEquals(listOf("bleh"), match.tokens) + assertEquals(listOf("RegexTerminal"), TerminalTypes(match.terminals)) + + match = zeroOrOneCombinator.SemanticMatch(synValid, 0) + assertEquals(0, match.matchResult) + assertEquals(listOf(), match.tokens) + + match = zeroOrOneCombinator.SyntacticMatch(semValidEmpty, 0) + assertEquals(semValidEmpty.length, match.matchResult) + assertEquals(listOf(), match.tokens) + + match = zeroOrOneCombinator.SemanticMatch(semValidEmpty, 0) + assertEquals(semValidEmpty.length, match.matchResult) + assertEquals(listOf(), match.tokens) + + match = zeroOrOneCombinator.SyntacticMatch(invalid, 0) + assertEquals(0, match.matchResult) + assertEquals(listOf(), match.tokens) + + match = zeroOrOneCombinator.SemanticMatch(invalid, 0) + assertEquals(0, match.matchResult) + assertEquals(listOf(), match.tokens) + + match = zeroOrOneCombinator.SyntacticMatch(semValidFromOffset, garbage.length) + assertEquals(semValidFromOffset.length, match.matchResult) + assertEquals(listOf("fizz"), match.tokens) + assertEquals(listOf("RegexTerminal"), TerminalTypes(match.terminals)) + + match = zeroOrOneCombinator.SemanticMatch(semValidFromOffset, garbage.length) + assertEquals(semValidFromOffset.length, match.matchResult) + assertEquals(listOf("fizz"), match.tokens) + assertEquals(listOf("RegexTerminal"), TerminalTypes(match.terminals)) + + match = zeroOrOneCombinator.SyntacticMatch(synValidFromOffset, garbage.length) + assertEquals(synValidFromOffset.length, match.matchResult) + assertEquals(listOf("bleh"), match.tokens) + assertEquals(listOf("RegexTerminal"), TerminalTypes(match.terminals)) + + match = zeroOrOneCombinator.SemanticMatch(synValidFromOffset, garbage.length) + assertEquals(garbage.length, match.matchResult) + assertEquals(listOf(), match.tokens) + + match = zeroOrOneCombinator.SyntacticMatch(semValidEmptyFromOffset, garbage.length) + assertEquals(garbage.length, match.matchResult) + assertEquals(listOf(), match.tokens) + + match = zeroOrOneCombinator.SemanticMatch(semValidEmptyFromOffset, garbage.length) + assertEquals(garbage.length, match.matchResult) + assertEquals(listOf(), match.tokens) + + match = zeroOrOneCombinator.SyntacticMatch(invalidFromOffset, garbage.length) + assertEquals(garbage.length, match.matchResult) + assertEquals(listOf(), match.tokens) + + match = zeroOrOneCombinator.SemanticMatch(invalidFromOffset, garbage.length) + assertEquals(garbage.length, match.matchResult) + assertEquals(listOf(), match.tokens) + } + fun testEOFCombinatorMatches() { /** * Fixture Setup