Skip to content

Commit 92c10bd

Browse files
Steve Ramageclaude
andcommitted
test: verify IPv6 canonicalization composes with hardware-address fields (#501)
Because a HARDWARE_ADDRESS field (Match=, Link=, Neighbor=) accepts IPv6 literals via the shared IPV6_ADDR combinator — which carries SemanticTag.IPV6 — the RFC 5952 canonicalization inspection and its quick-fix work there too. Add tests proving: a non-canonical IPv6 in Match=/Link= is flagged and rewritten (including rewriting only the IPv6 within a list, exercising the quick-fix offset); a plain MAC is untouched; and a strict 6-byte MAC field (SR-IOV=) never triggers it. Also assert both combinators colour as a single Role.LITERAL span. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent c01cd8f commit 92c10bd

2 files changed

Lines changed: 89 additions & 0 deletions

File tree

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai
2+
3+
import com.intellij.lang.annotation.HighlightSeverity
4+
import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest
5+
import net.sjrx.intellij.plugins.systemdunitfiles.inspections.Ipv6CanonicalFormInspection
6+
import net.sjrx.intellij.plugins.systemdunitfiles.settings.ExperimentalSettings
7+
import org.junit.Test
8+
9+
/**
10+
* A hardware-address field (Match=, Link=) accepts IPv6 literals, and those literals carry the
11+
* SemanticTag.IPV6 from the shared IPV6_ADDR combinator — so the RFC 5952 canonicalization inspection
12+
* and its quick-fix compose with the new MAC validators (#501). A strict 6-byte MAC field, which does
13+
* not accept IP literals, must never be touched.
14+
*/
15+
class MacAddressIpv6QuickFixTest : AbstractUnitFileTest() {
16+
17+
override fun tearDown() {
18+
try {
19+
ExperimentalSettings.getInstance(project).state.useGrammarParseEngine = false
20+
} finally {
21+
super.tearDown()
22+
}
23+
}
24+
25+
private fun enableNewEngine() {
26+
ExperimentalSettings.getInstance(project).state.useGrammarParseEngine = true
27+
}
28+
29+
private fun hasCanonicalWarning() = myFixture.doHighlighting().any {
30+
it.severity == HighlightSeverity.WEAK_WARNING && it.description?.contains("canonical form") == true
31+
}
32+
33+
@Test
34+
fun testNonCanonicalIpv6InMatchIsFlagged() {
35+
enableNewEngine()
36+
setupFileInEditor("f.network", "[Match]\nMACAddress=2001:DB8::1\n")
37+
enableInspection(Ipv6CanonicalFormInspection::class.java)
38+
assertTrue(hasCanonicalWarning())
39+
}
40+
41+
@Test
42+
fun testPlainMacIsNotFlagged() {
43+
enableNewEngine()
44+
setupFileInEditor("f.network", "[Match]\nMACAddress=00:11:22:33:44:55\n")
45+
enableInspection(Ipv6CanonicalFormInspection::class.java)
46+
assertFalse(hasCanonicalWarning())
47+
}
48+
49+
@Test
50+
fun testStrictMacFieldNeverColorsAnIpv6() {
51+
// SR-IOV.MACAddress is a strict 6-byte MAC: an IPv6 literal is invalid there and, crucially, is
52+
// NOT a labeled IPv6 span, so the canonicalization inspection must not fire.
53+
enableNewEngine()
54+
setupFileInEditor("f.link", "[SR-IOV]\nMACAddress=2001:DB8::1\n")
55+
enableInspection(Ipv6CanonicalFormInspection::class.java)
56+
assertFalse(hasCanonicalWarning())
57+
}
58+
59+
@Test
60+
fun testQuickFixRewritesSingleIpv6() {
61+
enableNewEngine()
62+
setupFileInEditor("f.network", "[Link]\nMACAddress=2001:D${COMPLETION_POSITION}B8::1\n")
63+
enableInspection(Ipv6CanonicalFormInspection::class.java)
64+
myFixture.doHighlighting()
65+
66+
myFixture.launchAction(myFixture.findSingleIntention("Convert to canonical IPv6"))
67+
myFixture.checkResult("[Link]\nMACAddress=2001:db8::1\n")
68+
}
69+
70+
@Test
71+
fun testQuickFixRewritesOnlyTheIpv6WithinAList() {
72+
// Offset handling: the IPv6 sits after a MAC in a Match= list; only it should be rewritten.
73+
enableNewEngine()
74+
setupFileInEditor("f.network", "[Match]\nMACAddress=00:11:22:33:44:55 2001:D${COMPLETION_POSITION}B8::1\n")
75+
enableInspection(Ipv6CanonicalFormInspection::class.java)
76+
myFixture.doHighlighting()
77+
78+
myFixture.launchAction(myFixture.findSingleIntention("Convert to canonical IPv6"))
79+
myFixture.checkResult("[Match]\nMACAddress=00:11:22:33:44:55 2001:db8::1\n")
80+
}
81+
}

src/test/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/grammar/MacAddressGrammarTest.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,12 @@ class MacAddressGrammarTest {
7575
assertEquals(true, macs.accepts("00:11:22:33:44:55 aa:bb:cc:dd:ee:ff"))
7676
assertEquals(false, macs.accepts("00:11:22:33:44:55 192.168.1.1")) // list of MACs, no IP literals
7777
}
78+
79+
@Test
80+
fun testAddressColorsAsOneLiteralSpan() {
81+
// Both combinators are wrapped in Labeled(Role.LITERAL): the whole address is a single literal
82+
// span (not coloured per octet / with the separators as operators).
83+
assertEquals(listOf(Region(0, 17, Role.LITERAL)), mac.colorize("00:11:22:33:44:55"))
84+
assertEquals(listOf(Region(0, 17, Role.LITERAL)), hwAddr.colorize("00-11-22-33-44-55"))
85+
}
7886
}

0 commit comments

Comments
 (0)