LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2010 The Go Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style | |
3 // license that can be found in the LICENSE file. | |
4 | |
5 package regexp | |
6 | |
7 import ( | |
8 "fmt" | |
9 "strings" | |
10 "testing" | |
11 ) | |
12 | |
13 // For each pattern/text pair, what is the expected output of each function? | |
14 // We can derive the textual results from the indexed results, the non-submatch | |
15 // results from the submatched results, the single results from the 'all' result
s, | |
16 // and the byte results from the string results. Therefore the table includes | |
17 // only the FindAllStringSubmatchIndex result. | |
18 type FindTest struct { | |
19 pat string | |
20 text string | |
21 matches [][]int | |
22 } | |
23 | |
24 func (t FindTest) String() string { | |
25 return fmt.Sprintf("pat: %#q text: %#q", t.pat, t.text) | |
26 } | |
27 | |
28 var findTests = []FindTest{ | |
29 {``, ``, build(1, 0, 0)}, | |
30 {`^abcdefg`, "abcdefg", build(1, 0, 7)}, | |
31 {`a+`, "baaab", build(1, 1, 4)}, | |
32 {"abcd..", "abcdef", build(1, 0, 6)}, | |
33 {`a`, "a", build(1, 0, 1)}, | |
34 {`x`, "y", nil}, | |
35 {`b`, "abc", build(1, 1, 2)}, | |
36 {`.`, "a", build(1, 0, 1)}, | |
37 {`.*`, "abcdef", build(1, 0, 6)}, | |
38 {`^`, "abcde", build(1, 0, 0)}, | |
39 {`$`, "abcde", build(1, 5, 5)}, | |
40 {`^abcd$`, "abcd", build(1, 0, 4)}, | |
41 {`^bcd'`, "abcdef", nil}, | |
42 {`^abcd$`, "abcde", nil}, | |
43 {`a+`, "baaab", build(1, 1, 4)}, | |
44 {`a*`, "baaab", build(3, 0, 0, 1, 4, 5, 5)}, | |
45 {`[a-z]+`, "abcd", build(1, 0, 4)}, | |
46 {`[^a-z]+`, "ab1234cd", build(1, 2, 6)}, | |
47 {`[a\-\]z]+`, "az]-bcz", build(2, 0, 4, 6, 7)}, | |
48 {`[^\n]+`, "abcd\n", build(1, 0, 4)}, | |
49 {`[日本語]+`, "日本語日本語", build(1, 0, 18)}, | |
50 {`日本語+`, "日本語", build(1, 0, 9)}, | |
51 {`日本語+`, "日本語語語語", build(1, 0, 18)}, | |
52 {`()`, "", build(1, 0, 0, 0, 0)}, | |
53 {`(a)`, "a", build(1, 0, 1, 0, 1)}, | |
54 {`(.)(.)`, "日a", build(1, 0, 4, 0, 3, 3, 4)}, | |
55 {`(.*)`, "", build(1, 0, 0, 0, 0)}, | |
56 {`(.*)`, "abcd", build(1, 0, 4, 0, 4)}, | |
57 {`(..)(..)`, "abcd", build(1, 0, 4, 0, 2, 2, 4)}, | |
58 {`(([^xyz]*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 3, 4)}, | |
59 {`((a|b|c)*(d))`, "abcd", build(1, 0, 4, 0, 4, 2, 3, 3, 4)}, | |
60 {`(((a|b|c)*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 2, 3, 3, 4)}, | |
61 {`\a\b\f\n\r\t\v`, "\a\b\f\n\r\t\v", build(1, 0, 7)}, | |
62 {`[\a\b\f\n\r\t\v]+`, "\a\b\f\n\r\t\v", build(1, 0, 7)}, | |
63 | |
64 {`a*(|(b))c*`, "aacc", build(1, 0, 4, 2, 2, -1, -1)}, | |
65 {`(.*).*`, "ab", build(1, 0, 2, 0, 2)}, | |
66 {`[.]`, ".", build(1, 0, 1)}, | |
67 {`/$`, "/abc/", build(1, 4, 5)}, | |
68 {`/$`, "/abc", nil}, | |
69 | |
70 // multiple matches | |
71 {`.`, "abc", build(3, 0, 1, 1, 2, 2, 3)}, | |
72 {`(.)`, "abc", build(3, 0, 1, 0, 1, 1, 2, 1, 2, 2, 3, 2, 3)}, | |
73 {`.(.)`, "abcd", build(2, 0, 2, 1, 2, 2, 4, 3, 4)}, | |
74 {`ab*`, "abbaab", build(3, 0, 3, 3, 4, 4, 6)}, | |
75 {`a(b*)`, "abbaab", build(3, 0, 3, 1, 3, 3, 4, 4, 4, 4, 6, 5, 6)}, | |
76 | |
77 // fixed bugs | |
78 {`ab$`, "cab", build(1, 1, 3)}, | |
79 {`axxb$`, "axxcb", nil}, | |
80 {`data`, "daXY data", build(1, 5, 9)}, | |
81 {`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)}, | |
82 {`zx+`, "zzx", build(1, 1, 3)}, | |
83 | |
84 // can backslash-escape any punctuation | |
85 {`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`, | |
86 `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)}, | |
87 {`[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~]+`, | |
88 `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)}, | |
89 {"\\`", "`", build(1, 0, 1)}, | |
90 {"[\\`]+", "`", build(1, 0, 1)}, | |
91 | |
92 // long set of matches (longer than startSize) | |
93 { | |
94 ".", | |
95 "qwertyuiopasdfghjklzxcvbnm1234567890", | |
96 build(36, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9,
9, 10, | |
97 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17,
17, 18, 18, 19, 19, 20, | |
98 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27,
27, 28, 28, 29, 29, 30, | |
99 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36), | |
100 }, | |
101 } | |
102 | |
103 // build is a helper to construct a [][]int by extracting n sequences from x. | |
104 // This represents n matches with len(x)/n submatches each. | |
105 func build(n int, x ...int) [][]int { | |
106 ret := make([][]int, n) | |
107 runLength := len(x) / n | |
108 j := 0 | |
109 for i := range ret { | |
110 ret[i] = make([]int, runLength) | |
111 copy(ret[i], x[j:]) | |
112 j += runLength | |
113 if j > len(x) { | |
114 panic("invalid build entry") | |
115 } | |
116 } | |
117 return ret | |
118 } | |
119 | |
120 // First the simple cases. | |
121 | |
122 func TestFind(t *testing.T) { | |
123 for _, test := range findTests { | |
124 re := MustCompile(test.pat) | |
125 if re.String() != test.pat { | |
126 t.Errorf("String() = `%s`; should be `%s`", re.String(),
test.pat) | |
127 } | |
128 result := re.Find([]byte(test.text)) | |
129 switch { | |
130 case len(test.matches) == 0 && len(result) == 0: | |
131 // ok | |
132 case test.matches == nil && result != nil: | |
133 t.Errorf("expected no match; got one: %s", test) | |
134 case test.matches != nil && result == nil: | |
135 t.Errorf("expected match; got none: %s", test) | |
136 case test.matches != nil && result != nil: | |
137 expect := test.text[test.matches[0][0]:test.matches[0][1
]] | |
138 if expect != string(result) { | |
139 t.Errorf("expected %q got %q: %s", expect, resul
t, test) | |
140 } | |
141 } | |
142 } | |
143 } | |
144 | |
145 func TestFindString(t *testing.T) { | |
146 for _, test := range findTests { | |
147 result := MustCompile(test.pat).FindString(test.text) | |
148 switch { | |
149 case len(test.matches) == 0 && len(result) == 0: | |
150 // ok | |
151 case test.matches == nil && result != "": | |
152 t.Errorf("expected no match; got one: %s", test) | |
153 case test.matches != nil && result == "": | |
154 // Tricky because an empty result has two meanings: no m
atch or empty match. | |
155 if test.matches[0][0] != test.matches[0][1] { | |
156 t.Errorf("expected match; got none: %s", test) | |
157 } | |
158 case test.matches != nil && result != "": | |
159 expect := test.text[test.matches[0][0]:test.matches[0][1
]] | |
160 if expect != result { | |
161 t.Errorf("expected %q got %q: %s", expect, resul
t, test) | |
162 } | |
163 } | |
164 } | |
165 } | |
166 | |
167 func testFindIndex(test *FindTest, result []int, t *testing.T) { | |
168 switch { | |
169 case len(test.matches) == 0 && len(result) == 0: | |
170 // ok | |
171 case test.matches == nil && result != nil: | |
172 t.Errorf("expected no match; got one: %s", test) | |
173 case test.matches != nil && result == nil: | |
174 t.Errorf("expected match; got none: %s", test) | |
175 case test.matches != nil && result != nil: | |
176 expect := test.matches[0] | |
177 if expect[0] != result[0] || expect[1] != result[1] { | |
178 t.Errorf("expected %v got %v: %s", expect, result, test) | |
179 } | |
180 } | |
181 } | |
182 | |
183 func TestFindIndex(t *testing.T) { | |
184 for _, test := range findTests { | |
185 testFindIndex(&test, MustCompile(test.pat).FindIndex([]byte(test
.text)), t) | |
186 } | |
187 } | |
188 | |
189 func TestFindStringIndex(t *testing.T) { | |
190 for _, test := range findTests { | |
191 testFindIndex(&test, MustCompile(test.pat).FindStringIndex(test.
text), t) | |
192 } | |
193 } | |
194 | |
195 func TestFindReaderIndex(t *testing.T) { | |
196 for _, test := range findTests { | |
197 testFindIndex(&test, MustCompile(test.pat).FindReaderIndex(strin
gs.NewReader(test.text)), t) | |
198 } | |
199 } | |
200 | |
201 // Now come the simple All cases. | |
202 | |
203 func TestFindAll(t *testing.T) { | |
204 for _, test := range findTests { | |
205 result := MustCompile(test.pat).FindAll([]byte(test.text), -1) | |
206 switch { | |
207 case test.matches == nil && result == nil: | |
208 // ok | |
209 case test.matches == nil && result != nil: | |
210 t.Errorf("expected no match; got one: %s", test) | |
211 case test.matches != nil && result == nil: | |
212 t.Errorf("expected match; got none: %s", test) | |
213 case test.matches != nil && result != nil: | |
214 if len(test.matches) != len(result) { | |
215 t.Errorf("expected %d matches; got %d: %s", len(
test.matches), len(result), test) | |
216 continue | |
217 } | |
218 for k, e := range test.matches { | |
219 expect := test.text[e[0]:e[1]] | |
220 if expect != string(result[k]) { | |
221 t.Errorf("match %d: expected %q got %q:
%s", k, expect, result[k], test) | |
222 } | |
223 } | |
224 } | |
225 } | |
226 } | |
227 | |
228 func TestFindAllString(t *testing.T) { | |
229 for _, test := range findTests { | |
230 result := MustCompile(test.pat).FindAllString(test.text, -1) | |
231 switch { | |
232 case test.matches == nil && result == nil: | |
233 // ok | |
234 case test.matches == nil && result != nil: | |
235 t.Errorf("expected no match; got one: %s", test) | |
236 case test.matches != nil && result == nil: | |
237 t.Errorf("expected match; got none: %s", test) | |
238 case test.matches != nil && result != nil: | |
239 if len(test.matches) != len(result) { | |
240 t.Errorf("expected %d matches; got %d: %s", len(
test.matches), len(result), test) | |
241 continue | |
242 } | |
243 for k, e := range test.matches { | |
244 expect := test.text[e[0]:e[1]] | |
245 if expect != result[k] { | |
246 t.Errorf("expected %q got %q: %s", expec
t, result, test) | |
247 } | |
248 } | |
249 } | |
250 } | |
251 } | |
252 | |
253 func testFindAllIndex(test *FindTest, result [][]int, t *testing.T) { | |
254 switch { | |
255 case test.matches == nil && result == nil: | |
256 // ok | |
257 case test.matches == nil && result != nil: | |
258 t.Errorf("expected no match; got one: %s", test) | |
259 case test.matches != nil && result == nil: | |
260 t.Errorf("expected match; got none: %s", test) | |
261 case test.matches != nil && result != nil: | |
262 if len(test.matches) != len(result) { | |
263 t.Errorf("expected %d matches; got %d: %s", len(test.mat
ches), len(result), test) | |
264 return | |
265 } | |
266 for k, e := range test.matches { | |
267 if e[0] != result[k][0] || e[1] != result[k][1] { | |
268 t.Errorf("match %d: expected %v got %v: %s", k,
e, result[k], test) | |
269 } | |
270 } | |
271 } | |
272 } | |
273 | |
274 func TestFindAllIndex(t *testing.T) { | |
275 for _, test := range findTests { | |
276 testFindAllIndex(&test, MustCompile(test.pat).FindAllIndex([]byt
e(test.text), -1), t) | |
277 } | |
278 } | |
279 | |
280 func TestFindAllStringIndex(t *testing.T) { | |
281 for _, test := range findTests { | |
282 testFindAllIndex(&test, MustCompile(test.pat).FindAllStringIndex
(test.text, -1), t) | |
283 } | |
284 } | |
285 | |
286 // Now come the Submatch cases. | |
287 | |
288 func testSubmatchBytes(test *FindTest, n int, submatches []int, result [][]byte,
t *testing.T) { | |
289 if len(submatches) != len(result)*2 { | |
290 t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(
submatches)/2, len(result), test) | |
291 return | |
292 } | |
293 for k := 0; k < len(submatches); k += 2 { | |
294 if submatches[k] == -1 { | |
295 if result[k/2] != nil { | |
296 t.Errorf("match %d: expected nil got %q: %s", n,
result, test) | |
297 } | |
298 continue | |
299 } | |
300 expect := test.text[submatches[k]:submatches[k+1]] | |
301 if expect != string(result[k/2]) { | |
302 t.Errorf("match %d: expected %q got %q: %s", n, expect,
result, test) | |
303 return | |
304 } | |
305 } | |
306 } | |
307 | |
308 func TestFindSubmatch(t *testing.T) { | |
309 for _, test := range findTests { | |
310 result := MustCompile(test.pat).FindSubmatch([]byte(test.text)) | |
311 switch { | |
312 case test.matches == nil && result == nil: | |
313 // ok | |
314 case test.matches == nil && result != nil: | |
315 t.Errorf("expected no match; got one: %s", test) | |
316 case test.matches != nil && result == nil: | |
317 t.Errorf("expected match; got none: %s", test) | |
318 case test.matches != nil && result != nil: | |
319 testSubmatchBytes(&test, 0, test.matches[0], result, t) | |
320 } | |
321 } | |
322 } | |
323 | |
324 func testSubmatchString(test *FindTest, n int, submatches []int, result []string
, t *testing.T) { | |
325 if len(submatches) != len(result)*2 { | |
326 t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(
submatches)/2, len(result), test) | |
327 return | |
328 } | |
329 for k := 0; k < len(submatches); k += 2 { | |
330 if submatches[k] == -1 { | |
331 if result[k/2] != "" { | |
332 t.Errorf("match %d: expected nil got %q: %s", n,
result, test) | |
333 } | |
334 continue | |
335 } | |
336 expect := test.text[submatches[k]:submatches[k+1]] | |
337 if expect != result[k/2] { | |
338 t.Errorf("match %d: expected %q got %q: %s", n, expect,
result, test) | |
339 return | |
340 } | |
341 } | |
342 } | |
343 | |
344 func TestFindStringSubmatch(t *testing.T) { | |
345 for _, test := range findTests { | |
346 result := MustCompile(test.pat).FindStringSubmatch(test.text) | |
347 switch { | |
348 case test.matches == nil && result == nil: | |
349 // ok | |
350 case test.matches == nil && result != nil: | |
351 t.Errorf("expected no match; got one: %s", test) | |
352 case test.matches != nil && result == nil: | |
353 t.Errorf("expected match; got none: %s", test) | |
354 case test.matches != nil && result != nil: | |
355 testSubmatchString(&test, 0, test.matches[0], result, t) | |
356 } | |
357 } | |
358 } | |
359 | |
360 func testSubmatchIndices(test *FindTest, n int, expect, result []int, t *testing
.T) { | |
361 if len(expect) != len(result) { | |
362 t.Errorf("match %d: expected %d matches; got %d: %s", n, len(exp
ect)/2, len(result)/2, test) | |
363 return | |
364 } | |
365 for k, e := range expect { | |
366 if e != result[k] { | |
367 t.Errorf("match %d: submatch error: expected %v got %v:
%s", n, expect, result, test) | |
368 } | |
369 } | |
370 } | |
371 | |
372 func testFindSubmatchIndex(test *FindTest, result []int, t *testing.T) { | |
373 switch { | |
374 case test.matches == nil && result == nil: | |
375 // ok | |
376 case test.matches == nil && result != nil: | |
377 t.Errorf("expected no match; got one: %s", test) | |
378 case test.matches != nil && result == nil: | |
379 t.Errorf("expected match; got none: %s", test) | |
380 case test.matches != nil && result != nil: | |
381 testSubmatchIndices(test, 0, test.matches[0], result, t) | |
382 } | |
383 } | |
384 | |
385 func TestFindSubmatchIndex(t *testing.T) { | |
386 for _, test := range findTests { | |
387 testFindSubmatchIndex(&test, MustCompile(test.pat).FindSubmatchI
ndex([]byte(test.text)), t) | |
388 } | |
389 } | |
390 | |
391 func TestFindStringSubmatchIndex(t *testing.T) { | |
392 for _, test := range findTests { | |
393 testFindSubmatchIndex(&test, MustCompile(test.pat).FindStringSub
matchIndex(test.text), t) | |
394 } | |
395 } | |
396 | |
397 func TestFindReaderSubmatchIndex(t *testing.T) { | |
398 for _, test := range findTests { | |
399 testFindSubmatchIndex(&test, MustCompile(test.pat).FindReaderSub
matchIndex(strings.NewReader(test.text)), t) | |
400 } | |
401 } | |
402 | |
403 // Now come the monster AllSubmatch cases. | |
404 | |
405 func TestFindAllSubmatch(t *testing.T) { | |
406 for _, test := range findTests { | |
407 result := MustCompile(test.pat).FindAllSubmatch([]byte(test.text
), -1) | |
408 switch { | |
409 case test.matches == nil && result == nil: | |
410 // ok | |
411 case test.matches == nil && result != nil: | |
412 t.Errorf("expected no match; got one: %s", test) | |
413 case test.matches != nil && result == nil: | |
414 t.Errorf("expected match; got none: %s", test) | |
415 case len(test.matches) != len(result): | |
416 t.Errorf("expected %d matches; got %d: %s", len(test.mat
ches), len(result), test) | |
417 case test.matches != nil && result != nil: | |
418 for k, match := range test.matches { | |
419 testSubmatchBytes(&test, k, match, result[k], t) | |
420 } | |
421 } | |
422 } | |
423 } | |
424 | |
425 func TestFindAllStringSubmatch(t *testing.T) { | |
426 for _, test := range findTests { | |
427 result := MustCompile(test.pat).FindAllStringSubmatch(test.text,
-1) | |
428 switch { | |
429 case test.matches == nil && result == nil: | |
430 // ok | |
431 case test.matches == nil && result != nil: | |
432 t.Errorf("expected no match; got one: %s", test) | |
433 case test.matches != nil && result == nil: | |
434 t.Errorf("expected match; got none: %s", test) | |
435 case len(test.matches) != len(result): | |
436 t.Errorf("expected %d matches; got %d: %s", len(test.mat
ches), len(result), test) | |
437 case test.matches != nil && result != nil: | |
438 for k, match := range test.matches { | |
439 testSubmatchString(&test, k, match, result[k], t
) | |
440 } | |
441 } | |
442 } | |
443 } | |
444 | |
445 func testFindAllSubmatchIndex(test *FindTest, result [][]int, t *testing.T) { | |
446 switch { | |
447 case test.matches == nil && result == nil: | |
448 // ok | |
449 case test.matches == nil && result != nil: | |
450 t.Errorf("expected no match; got one: %s", test) | |
451 case test.matches != nil && result == nil: | |
452 t.Errorf("expected match; got none: %s", test) | |
453 case len(test.matches) != len(result): | |
454 t.Errorf("expected %d matches; got %d: %s", len(test.matches), l
en(result), test) | |
455 case test.matches != nil && result != nil: | |
456 for k, match := range test.matches { | |
457 testSubmatchIndices(test, k, match, result[k], t) | |
458 } | |
459 } | |
460 } | |
461 | |
462 func TestFindAllSubmatchIndex(t *testing.T) { | |
463 for _, test := range findTests { | |
464 testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllSub
matchIndex([]byte(test.text), -1), t) | |
465 } | |
466 } | |
467 | |
468 func TestFindAllStringSubmatchIndex(t *testing.T) { | |
469 for _, test := range findTests { | |
470 testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllStr
ingSubmatchIndex(test.text, -1), t) | |
471 } | |
472 } | |
LEFT | RIGHT |