Skip to content

Commit 25ae8b9

Browse files
committed
more grammat tests
1 parent 3583640 commit 25ae8b9

2 files changed

Lines changed: 86 additions & 14 deletions

File tree

internal/grammar/grammar.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ const (
6565

6666
scoping = `^ --- -* $`
6767

68-
// a label is field of a FQDN
68+
// label is a field of a FQDN
6969
label = `(?: [- \w]+ )` // hyphen and word chars, the rest is done by the parser
7070

7171
// word

internal/grammar/grammar_test.go

Lines changed: 85 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,103 @@ func TestGrammar(t *testing.T) {
1515
}
1616
}
1717

18-
func TestGrammarWords(t *testing.T) {
18+
func TestGrammarRules(t *testing.T) {
1919
t.Parallel()
20+
2021
tt := []struct {
2122
rule string
2223
input string
2324
want bool
2425
}{
25-
{
26-
rule: "word",
27-
input: "with-hyphen",
28-
want: true,
29-
},
30-
{
31-
rule: "cswords",
32-
input: "std,open",
33-
want: true,
34-
},
26+
// ── word ────────────────────────────────────────────────────────────
27+
{rule: "word", input: "hello", want: true},
28+
{rule: "word", input: "with-hyphen", want: true},
29+
{rule: "word", input: "word123", want: true},
30+
{rule: "word", input: "_underscore", want: true},
31+
{rule: "word", input: "", want: false},
32+
33+
// ── cswords ─────────────────────────────────────────────────────────
34+
{rule: "cswords", input: "single", want: true},
35+
{rule: "cswords", input: "std,open", want: true},
36+
{rule: "cswords", input: "a,b-c,d", want: true},
37+
{rule: "cswords", input: ",leading,comma", want: false},
38+
{rule: "cswords", input: "trailing,comma,", want: false},
39+
{rule: "cswords", input: "a,,b", want: false}, // double comma
40+
{rule: "cswords", input: "-starts,with,hyphen", want: false},
41+
{rule: "cswords", input: "with space", want: false}, // spaces not allowed
42+
43+
// ── comment ─────────────────────────────────────────────────────────
44+
{rule: "comment", input: "# this is a comment", want: true},
45+
{rule: "comment", input: "#", want: true},
46+
{rule: "comment", input: "# ", want: true},
47+
{rule: "comment", input: "not a comment", want: false},
48+
{rule: "comment", input: "", want: false},
49+
{rule: "comment", input: " # indented", want: false}, // ^ anchors at start
50+
51+
// ── scoping ─────────────────────────────────────────────────────────
52+
{rule: "scoping", input: "---", want: true},
53+
{rule: "scoping", input: "----", want: true},
54+
{rule: "scoping", input: "----------", want: true},
55+
{rule: "scoping", input: "--", want: false}, // minimum three dashes
56+
{rule: "scoping", input: "- -", want: false}, // no spaces
57+
{rule: "scoping", input: "--- x", want: false}, // nothing after dashes
58+
59+
// ── fqdn ────────────────────────────────────────────────────────────
60+
{rule: "fqdn", input: "www.example.com", want: true},
61+
{rule: "fqdn", input: "www.example.com.", want: true}, // trailing dot allowed
62+
{rule: "fqdn", input: "*.foo.bar", want: true}, // wildcard prefix
63+
{rule: "fqdn", input: "example.com", want: true},
64+
{rule: "fqdn", input: "a.b.c.d.e.tld", want: true},
65+
{rule: "fqdn", input: "localhost", want: false}, // bare hostname, no dot
66+
{rule: "fqdn", input: "192.168.1.1", want: false}, // TLD must end with letter
67+
{rule: "fqdn", input: "", want: false},
68+
{rule: "fqdn", input: "foo bar.com", want: false}, // spaces not allowed in label
69+
70+
// ── ident (no trailing $, anchored only at start) ───────────────────
71+
{rule: "ident", input: "VLAN", want: true},
72+
{rule: "ident", input: "VRF", want: true},
73+
{rule: "ident", input: "STATUS_OK", want: true},
74+
{rule: "ident", input: "VLAN10", want: true},
75+
{rule: "ident", input: "A9", want: true},
76+
{rule: "ident", input: "A", want: false}, // [A-Z0-9_]+ needs ≥1 more char
77+
{rule: "ident", input: "lowercase", want: false},
78+
{rule: "ident", input: "Mixed", want: false},
79+
{rule: "ident", input: "1NVALID", want: false}, // must start with A-Z
80+
81+
// ── ip (no trailing $, anchored only at start) ───────────────────────
82+
{rule: "ip", input: "192.168.1.1", want: true},
83+
{rule: "ip", input: "192.168.1.1/24", want: true}, // prefix is fine, no trailing $
84+
{rule: "ip", input: "10.0.0.1", want: true},
85+
{rule: "ip", input: "2001:db8::1", want: true},
86+
{rule: "ip", input: "::1", want: true},
87+
{rule: "ip", input: "not-an-ip", want: false},
88+
{rule: "ip", input: "", want: false},
89+
90+
// ── ipv4 (no trailing $) ─────────────────────────────────────────────
91+
{rule: "ipv4", input: "192.168.1.1", want: true},
92+
{rule: "ipv4", input: "0.0.0.0", want: true},
93+
{rule: "ipv4", input: "255.255.255.255", want: true},
94+
{rule: "ipv4", input: "192.168.1.1/24", want: true}, // CIDR — no trailing $ intended
95+
{rule: "ipv4", input: "2001:db8::1", want: false}, // IPv6 must not match ipv4
96+
{rule: "ipv4", input: "1.2.3", want: false}, // only three octets
97+
{rule: "ipv4", input: "not-an-ip", want: false},
98+
99+
// ── ipv6 (no trailing $) ─────────────────────────────────────────────
100+
{rule: "ipv6", input: "2001:db8::1 foo", want: true},
101+
{rule: "ipv6", input: "::1", want: true},
102+
{rule: "ipv6", input: "fe80::1", want: true},
103+
{rule: "ipv6", input: "2001:db8::1/64", want: true}, // prefix — no trailing $ intended
104+
{rule: "ipv6", input: "192.168.1.1", want: false}, // pure dotted-decimal has no colon
105+
{rule: "ipv6", input: "not-an-ip", want: false},
35106
}
36107

37108
for _, tc := range tt {
38-
t.Run(tc.input, func(t *testing.T) {
109+
tc := tc
110+
t.Run(tc.rule+"/"+tc.input, func(t *testing.T) {
39111
t.Parallel()
40112
got := g.MustRx(tc.rule).MatchString(tc.input)
41113
if got != tc.want {
42-
t.Fatalf("rule: %s, input: %s, got %v, want %v", tc.rule, tc.input, got, tc.want)
114+
t.Fatalf("rule=%q input=%q: got %v, want %v", tc.rule, tc.input, got, tc.want)
43115
}
44116
})
45117
}

0 commit comments

Comments
 (0)