Source file
src/testing/match_test.go
1
2
3
4
5 package testing
6
7 import (
8 "fmt"
9 "reflect"
10 "regexp"
11 "strings"
12 "unicode"
13 )
14
15
16 func TestIsSpace(t *T) {
17 n := 0
18 for r := rune(0); r <= unicode.MaxRune; r++ {
19 if isSpace(r) != unicode.IsSpace(r) {
20 t.Errorf("IsSpace(%U)=%t incorrect", r, isSpace(r))
21 n++
22 if n > 10 {
23 return
24 }
25 }
26 }
27 }
28
29 func TestSplitRegexp(t *T) {
30 res := func(s ...string) filterMatch { return simpleMatch(s) }
31 alt := func(m ...filterMatch) filterMatch { return alternationMatch(m) }
32 testCases := []struct {
33 pattern string
34 result filterMatch
35 }{
36
37
38
39 {"", res("")},
40 {"/", res("", "")},
41 {"//", res("", "", "")},
42 {"A", res("A")},
43 {"A/B", res("A", "B")},
44 {"A/B/", res("A", "B", "")},
45 {"/A/B/", res("", "A", "B", "")},
46 {"[A]/(B)", res("[A]", "(B)")},
47 {"[/]/[/]", res("[/]", "[/]")},
48 {"[/]/[:/]", res("[/]", "[:/]")},
49 {"/]", res("", "]")},
50 {"]/", res("]", "")},
51 {"]/[/]", res("]", "[/]")},
52 {`([)/][(])`, res(`([)/][(])`)},
53 {"[(]/[)]", res("[(]", "[)]")},
54
55 {"A/B|C/D", alt(res("A", "B"), res("C", "D"))},
56
57
58
59 {")/", res(")/")},
60 {")/(/)", res(")/(", ")")},
61 {"a[/)b", res("a[/)b")},
62 {"(/]", res("(/]")},
63 {"(/", res("(/")},
64 {"[/]/[/", res("[/]", "[/")},
65 {`\p{/}`, res(`\p{`, "}")},
66 {`\p/`, res(`\p`, "")},
67 {`[[:/:]]`, res(`[[:/:]]`)},
68 }
69 for _, tc := range testCases {
70 a := splitRegexp(tc.pattern)
71 if !reflect.DeepEqual(a, tc.result) {
72 t.Errorf("splitRegexp(%q) = %#v; want %#v", tc.pattern, a, tc.result)
73 }
74
75
76
77 if _, err := regexp.Compile(tc.pattern); err != nil {
78 ok := true
79 if err := a.verify("", regexp.MatchString); err != nil {
80 ok = false
81 }
82 if ok {
83 t.Errorf("%s: expected error in any of %q", tc.pattern, a)
84 }
85 }
86 }
87 }
88
89 func TestMatcher(t *T) {
90 testCases := []struct {
91 pattern string
92 parent, sub string
93 ok bool
94 partial bool
95 }{
96
97 {"", "", "TestFoo", true, false},
98 {"TestFoo", "", "TestFoo", true, false},
99 {"TestFoo/", "", "TestFoo", true, true},
100 {"TestFoo/bar/baz", "", "TestFoo", true, true},
101 {"TestFoo", "", "TestBar", false, false},
102 {"TestFoo/", "", "TestBar", false, false},
103 {"TestFoo/bar/baz", "", "TestBar/bar/baz", false, false},
104
105
106 {"", "TestFoo", "x", true, false},
107 {"TestFoo", "TestFoo", "x", true, false},
108 {"TestFoo/", "TestFoo", "x", true, false},
109 {"TestFoo/bar/baz", "TestFoo", "bar", true, true},
110
111
112 {"TestFoo/bar/baz", "TestFoo", "bar/baz", true, false},
113 {"TestFoo/bar/baz", "TestFoo/bar", "baz", true, false},
114 {"TestFoo/bar/baz", "TestFoo", "x", false, false},
115 {"TestFoo", "TestBar", "x", false, false},
116 {"TestFoo/", "TestBar", "x", false, false},
117 {"TestFoo/bar/baz", "TestBar", "x/bar/baz", false, false},
118
119 {"A/B|C/D", "TestA", "B", true, false},
120 {"A/B|C/D", "TestC", "D", true, false},
121 {"A/B|C/D", "TestA", "C", false, false},
122
123
124 {"", "TestFoo", "x", true, false},
125 {"/", "TestFoo", "x", true, false},
126 {"./", "TestFoo", "x", true, false},
127 {"./.", "TestFoo", "x", true, false},
128 {"/bar/baz", "TestFoo", "bar", true, true},
129 {"/bar/baz", "TestFoo", "bar/baz", true, false},
130 {"//baz", "TestFoo", "bar/baz", true, false},
131 {"//", "TestFoo", "bar/baz", true, false},
132 {"/bar/baz", "TestFoo/bar", "baz", true, false},
133 {"//foo", "TestFoo", "bar/baz", false, false},
134 {"/bar/baz", "TestFoo", "x", false, false},
135 {"/bar/baz", "TestBar", "x/bar/baz", false, false},
136 }
137
138 for _, tc := range testCases {
139 m := newMatcher(regexp.MatchString, tc.pattern, "-test.run")
140
141 parent := &common{name: tc.parent}
142 if tc.parent != "" {
143 parent.level = 1
144 }
145 if n, ok, partial := m.fullName(parent, tc.sub); ok != tc.ok || partial != tc.partial {
146 t.Errorf("for pattern %q, fullName(parent=%q, sub=%q) = %q, ok %v partial %v; want ok %v partial %v",
147 tc.pattern, tc.parent, tc.sub, n, ok, partial, tc.ok, tc.partial)
148 }
149 }
150 }
151
152 var namingTestCases = []struct{ name, want string }{
153
154 {"", "x/#00"},
155 {"", "x/#01"},
156 {"#0", "x/#0"},
157 {"#00", "x/#00#01"},
158 {"#", "x/#"},
159 {"#", "x/##01"},
160
161 {"t", "x/t"},
162 {"t", "x/t#01"},
163 {"t", "x/t#02"},
164 {"t#00", "x/t#00"},
165
166 {"a#01", "x/a#01"},
167 {"a", "x/a"},
168 {"a", "x/a#02"},
169 {"a", "x/a#03"},
170 {"a#02", "x/a#02#01"},
171
172 {"b#00", "x/b#00"},
173 {"b", "x/b"},
174 {"b", "x/b#01"},
175 {"b#9223372036854775807", "x/b#9223372036854775807"},
176 {"b", "x/b#02"},
177 {"b", "x/b#03"},
178
179
180 {"A:1 B:2", "x/A:1_B:2"},
181 {"s\t\r\u00a0", "x/s___"},
182 {"\x01", `x/\x01`},
183 {"\U0010ffff", `x/\U0010ffff`},
184 }
185
186 func TestNaming(t *T) {
187 m := newMatcher(regexp.MatchString, "", "")
188 parent := &common{name: "x", level: 1}
189
190 for i, tc := range namingTestCases {
191 if got, _, _ := m.fullName(parent, tc.name); got != tc.want {
192 t.Errorf("%d:%s: got %q; want %q", i, tc.name, got, tc.want)
193 }
194 }
195 }
196
197 func FuzzNaming(f *F) {
198 for _, tc := range namingTestCases {
199 f.Add(tc.name)
200 }
201 parent := &common{name: "x", level: 1}
202 var m *matcher
203 var seen map[string]string
204 reset := func() {
205 m = newMatcher(regexp.MatchString, "", "")
206 seen = make(map[string]string)
207 }
208 reset()
209
210 f.Fuzz(func(t *T, subname string) {
211 if len(subname) > 10 {
212
213 t.Skip()
214 }
215 name := m.unique(parent.name, subname)
216 if !strings.Contains(name, "/"+subname) {
217 t.Errorf("name %q does not contain subname %q", name, subname)
218 }
219 if prev, ok := seen[name]; ok {
220 t.Errorf("name %q generated by both %q and %q", name, prev, subname)
221 }
222 if len(seen) > 1e6 {
223
224 reset()
225 }
226 seen[name] = subname
227 })
228 }
229
230
231
232 func (m alternationMatch) GoString() string {
233 s := make([]string, len(m))
234 for i, m := range m {
235 s[i] = fmt.Sprintf("%#v", m)
236 }
237 return fmt.Sprintf("(%s)", strings.Join(s, " | "))
238 }
239
View as plain text