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