From 357e14d427eafe8843d56432b9b43162b2398536 Mon Sep 17 00:00:00 2001 From: Steve Ramage Date: Sun, 28 Dec 2025 11:13:50 -0800 Subject: [PATCH] feat: add a couple more validators (Resolves #409) --- .../semanticdata/optionvalues/AiGenerated.kt | 3 + .../ai/ConfigParseAdActorSystemOptionValue.kt | 41 +++++++ ...seAddressSectionAddressScopeOptionValue.kt | 28 +++++ ...ConfigParseAdActorSystemOptionValueTest.kt | 70 +++++++++++ ...dressSectionAddressScopeOptionValueTest.kt | 109 ++++++++++++++++++ 5 files changed, 251 insertions(+) create mode 100644 src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseAdActorSystemOptionValue.kt create mode 100644 src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseAddressSectionAddressScopeOptionValue.kt create mode 100644 src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseAdActorSystemOptionValueTest.kt create mode 100644 src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseAddressSectionAddressScopeOptionValueTest.kt diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/AiGenerated.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/AiGenerated.kt index aa4b20e..b9cf1a5 100644 --- a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/AiGenerated.kt +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/AiGenerated.kt @@ -184,6 +184,9 @@ fun getAllAIGeneratedValidators(): Map { Validator("config_parse_wireguard_peer_route_priority", "0") to ConfigParseWireguardPeerRoutePriorityOptionValue() as OptionValueInformation, Validator("config_parse_wireguard_route_priority", "0") to ConfigParseWireguardRoutePriorityOptionValue() as OptionValueInformation, Validator("config_parse_wlan_iftype", "0") to ConfigParseWlanIftypeOptionValue() as OptionValueInformation, + Validator("config_parse_ad_actor_system", "0") to ConfigParseAdActorSystemOptionValue() as OptionValueInformation, + Validator("config_parse_address_section", "ADDRESS_SCOPE") to ConfigParseAddressSectionAddressScopeOptionValue() as OptionValueInformation, + ) return allValidators diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseAdActorSystemOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseAdActorSystemOptionValue.kt new file mode 100644 index 0000000..9611a6d --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseAdActorSystemOptionValue.kt @@ -0,0 +1,41 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.Validator +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues + +/** + * Validator for Bond.AdActorSystem + * C Function: config_parse_ad_actor_system(0) + * Used by Options: Bond.AdActorSystem + * + * Validates 802.3ad system MAC addresses in the format XX:XX:XX:XX:XX:XX + * where each XX is a hexadecimal byte (00-FF). + * + * Note: The C implementation also validates that the address is not null + * and not multicast, but those semantic checks cannot be implemented in + * the grammar layer. + */ +class ConfigParseAdActorSystemOptionValue : SimpleGrammarOptionValues( + "config_parse_ad_actor_system", + SequenceCombinator( + MAC_ADDRESS, + EOF() + ) +) { + companion object { + // MAC address octet: 2 hexadecimal digits + private val MAC_OCTET = RegexTerminal("[0-9a-fA-F]{2}", "[0-9a-fA-F]{2}") + private val COLON = LiteralChoiceTerminal(":") + + // MAC address format: XX:XX:XX:XX:XX:XX + val MAC_ADDRESS = SequenceCombinator( + MAC_OCTET, COLON, + MAC_OCTET, COLON, + MAC_OCTET, COLON, + MAC_OCTET, COLON, + MAC_OCTET, COLON, + MAC_OCTET + ) + } +} diff --git a/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseAddressSectionAddressScopeOptionValue.kt b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseAddressSectionAddressScopeOptionValue.kt new file mode 100644 index 0000000..e76e812 --- /dev/null +++ b/src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/ai/ConfigParseAddressSectionAddressScopeOptionValue.kt @@ -0,0 +1,28 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.* +import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues + +/** + * Validator for Address.Scope + * C Function: config_parse_address_section(ADDRESS_SCOPE) + * Used by Options: Address.Scope + * + * Valid values: + * - "global" - valid everywhere on the network, even through a gateway + * - "link" - only valid on this device, will not traverse a gateway + * - "host" - only valid within the device itself + * - Integer in the range 0-255 + * + * Note: IPv4 only - IPv6 scope is automatically assigned by the kernel + */ +class ConfigParseAddressSectionAddressScopeOptionValue : SimpleGrammarOptionValues( + "config_parse_address_section", + SequenceCombinator( + AlternativeCombinator( + FlexibleLiteralChoiceTerminal("global", "link", "host"), + IntegerTerminal(0, 256) + ), + EOF() + ) +) diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseAdActorSystemOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseAdActorSystemOptionValueTest.kt new file mode 100644 index 0000000..65ca45d --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseAdActorSystemOptionValueTest.kt @@ -0,0 +1,70 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseAdActorSystemOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidMacAddresses() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Bond] + AdActorSystem=00:11:22:33:44:55 + AdActorSystem=AA:BB:CC:DD:EE:FF + AdActorSystem=01:23:45:67:89:ab + AdActorSystem=FE:DC:BA:98:76:54 + """.trimIndent() + + // Execute SUT + setupFileInEditor("file.netdev", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + } + + @Test + fun testInvalidMacAddresses() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Bond] + AdActorSystem=00:11:22:33:44 + AdActorSystem=00:11:22:33:44:55:66 + AdActorSystem=00-11-22-33-44-55 + AdActorSystem=GG:HH:II:JJ:KK:LL + AdActorSystem=0:1:2:3:4:5 + AdActorSystem=001122334455 + """.trimIndent() + + // Execute SUT + setupFileInEditor("file.netdev", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(6, highlights) + } + + @Test + fun testMixedCaseIsValid() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Bond] + AdActorSystem=aA:bB:cC:dD:eE:fF + """.trimIndent() + + // Execute SUT + setupFileInEditor("file.netdev", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + } +} diff --git a/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseAddressSectionAddressScopeOptionValueTest.kt b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseAddressSectionAddressScopeOptionValueTest.kt new file mode 100644 index 0000000..e821b99 --- /dev/null +++ b/src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/inspections/ai/ConfigParseAddressSectionAddressScopeOptionValueTest.kt @@ -0,0 +1,109 @@ +package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai + +import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest +import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection +import org.junit.Test + +class ConfigParseAddressSectionAddressScopeOptionValueTest : AbstractUnitFileTest() { + + @Test + fun testValidLiteralValues() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Address] + Scope=global + Scope=link + Scope=host + """.trimIndent() + + // Execute SUT + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + } + + @Test + fun testValidIntegerValues() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Address] + Scope=0 + Scope=127 + Scope=255 + """.trimIndent() + + // Execute SUT + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(0, highlights) + } + + @Test + fun testInvalidLiteralValues() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Address] + Scope=invalid + Scope=localhost + Scope=site + """.trimIndent() + + // Execute SUT + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(3, highlights) + } + + @Test + fun testInvalidIntegerValues() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Address] + Scope=256 + Scope=-1 + Scope=1000 + """.trimIndent() + + // Execute SUT + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(3, highlights) + } + + @Test + fun testMixedInvalidValues() { + // Fixture Setup + // language="unit file (systemd)" + val file = """ + [Address] + Scope=global + Scope=invalid_value + Scope=100 + Scope=300 + """.trimIndent() + + // Execute SUT + setupFileInEditor("file.network", file) + enableInspection(InvalidValueInspection::class.java) + val highlights = myFixture.doHighlighting() + + // Verification + assertSize(2, highlights) + } +}