Source file
src/regexp/find_test.go
1
2
3
4
5 package regexp
6
7 import (
8 "fmt"
9 "strings"
10 "testing"
11 )
12
13
14
15
16
17
18 type FindTest struct {
19 pat string
20 text string
21 max int
22 matches [][]int
23 }
24
25 func (t FindTest) String() string {
26 return fmt.Sprintf("pat: %#q text: %#q", t.pat, t.text)
27 }
28
29 var findTests = []FindTest{
30 {``, ``, -1, build(1, 0, 0)},
31 {`^abcdefg`, "abcdefg", -1, build(1, 0, 7)},
32 {`a+`, "baaab", -1, build(1, 1, 4)},
33 {`a`, "bababaab", -1, build(4, 1, 2, 3, 4, 5, 6, 6, 7)},
34 {`a`, "bababaab", 0, nil},
35 {`a`, "bababaab", 1, build(1, 1, 2)},
36 {`a`, "bababaab", 2, build(2, 1, 2, 3, 4)},
37 {`a`, "bababaab", 3, build(3, 1, 2, 3, 4, 5, 6)},
38 {`a`, "bababaab", 4, build(4, 1, 2, 3, 4, 5, 6, 6, 7)},
39 {`a`, "bababaab", 5, build(4, 1, 2, 3, 4, 5, 6, 6, 7)},
40 {"abcd..", "abcdef", -1, build(1, 0, 6)},
41 {`a`, "a", -1, build(1, 0, 1)},
42 {`x`, "y", -1, nil},
43 {`b`, "abc", -1, build(1, 1, 2)},
44 {`.`, "a", -1, build(1, 0, 1)},
45 {`.*`, "abcdef", -1, build(1, 0, 6)},
46 {`^`, "abcde", -1, build(1, 0, 0)},
47 {`$`, "abcde", -1, build(1, 5, 5)},
48 {`^abcd$`, "abcd", -1, build(1, 0, 4)},
49 {`^bcd'`, "abcdef", -1, nil},
50 {`^abcd$`, "abcde", -1, nil},
51 {`a+`, "baaab", -1, build(1, 1, 4)},
52 {`a*`, "baaab", -1, build(3, 0, 0, 1, 4, 5, 5)},
53 {`[a-z]+`, "abcd", -1, build(1, 0, 4)},
54 {`[^a-z]+`, "ab1234cd", -1, build(1, 2, 6)},
55 {`[a\-\]z]+`, "az]-bcz", -1, build(2, 0, 4, 6, 7)},
56 {`[^\n]+`, "abcd\n", -1, build(1, 0, 4)},
57 {`[日本語]+`, "日本語日本語", -1, build(1, 0, 18)},
58 {`日本語+`, "日本語", -1, build(1, 0, 9)},
59 {`日本語+`, "日本語語語語", -1, build(1, 0, 18)},
60 {`()`, "", -1, build(1, 0, 0, 0, 0)},
61 {`(a)`, "a", -1, build(1, 0, 1, 0, 1)},
62 {`(.)(.)`, "日a", -1, build(1, 0, 4, 0, 3, 3, 4)},
63 {`(.*)`, "", -1, build(1, 0, 0, 0, 0)},
64 {`(.*)`, "abcd", -1, build(1, 0, 4, 0, 4)},
65 {`(..)(..)`, "abcd", -1, build(1, 0, 4, 0, 2, 2, 4)},
66 {`(([^xyz]*)(d))`, "abcd", -1, build(1, 0, 4, 0, 4, 0, 3, 3, 4)},
67 {`((a|b|c)*(d))`, "abcd", -1, build(1, 0, 4, 0, 4, 2, 3, 3, 4)},
68 {`(((a|b|c)*)(d))`, "abcd", -1, build(1, 0, 4, 0, 4, 0, 3, 2, 3, 3, 4)},
69 {`\a\f\n\r\t\v`, "\a\f\n\r\t\v", -1, build(1, 0, 6)},
70 {`[\a\f\n\r\t\v]+`, "\a\f\n\r\t\v", -1, build(1, 0, 6)},
71
72 {`a*(|(b))c*`, "aacc", -1, build(1, 0, 4, 2, 2, -1, -1)},
73 {`(.*).*`, "ab", -1, build(1, 0, 2, 0, 2)},
74 {`[.]`, ".", -1, build(1, 0, 1)},
75 {`/$`, "/abc/", -1, build(1, 4, 5)},
76 {`/$`, "/abc", -1, nil},
77
78
79 {`.`, "abc", -1, build(3, 0, 1, 1, 2, 2, 3)},
80 {`(.)`, "abc", -1, build(3, 0, 1, 0, 1, 1, 2, 1, 2, 2, 3, 2, 3)},
81 {`.(.)`, "abcd", -1, build(2, 0, 2, 1, 2, 2, 4, 3, 4)},
82 {`ab*`, "abbaab", -1, build(3, 0, 3, 3, 4, 4, 6)},
83 {`a(b*)`, "abbaab", -1, build(3, 0, 3, 1, 3, 3, 4, 4, 4, 4, 6, 5, 6)},
84
85
86 {`ab$`, "cab", -1, build(1, 1, 3)},
87 {`axxb$`, "axxcb", -1, nil},
88 {`data`, "daXY data", -1, build(1, 5, 9)},
89 {`da(.)a$`, "daXY data", -1, build(1, 5, 9, 7, 8)},
90 {`zx+`, "zzx", -1, build(1, 1, 3)},
91 {`ab$`, "abcab", -1, build(1, 3, 5)},
92 {`(aa)*$`, "a", -1, build(1, 1, 1, -1, -1)},
93 {`(?:.|(?:.a))`, "", -1, nil},
94 {`(?:A(?:A|a))`, "Aa", -1, build(1, 0, 2)},
95 {`(?:A|(?:A|a))`, "a", -1, build(1, 0, 1)},
96 {`(a){0}`, "", -1, build(1, 0, 0, -1, -1)},
97 {`(?-s)(?:(?:^).)`, "\n", -1, nil},
98 {`(?s)(?:(?:^).)`, "\n", -1, build(1, 0, 1)},
99 {`(?:(?:^).)`, "\n", -1, nil},
100 {`\b`, "x", -1, build(2, 0, 0, 1, 1)},
101 {`\b`, "xx", -1, build(2, 0, 0, 2, 2)},
102 {`\b`, "x y", -1, build(4, 0, 0, 1, 1, 2, 2, 3, 3)},
103 {`\b`, "xx yy", -1, build(4, 0, 0, 2, 2, 3, 3, 5, 5)},
104 {`\B`, "x", -1, nil},
105 {`\B`, "xx", -1, build(1, 1, 1)},
106 {`\B`, "x y", -1, nil},
107 {`\B`, "xx yy", -1, build(2, 1, 1, 4, 4)},
108 {`(|a)*`, "aa", -1, build(3, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2)},
109 {`0A|0[aA]`, "0a", -1, build(1, 0, 2)},
110 {`0[aA]|0A`, "0a", -1, build(1, 0, 2)},
111
112
113 {`[^\S\s]`, "abcd", -1, nil},
114 {`[^\S[:space:]]`, "abcd", -1, nil},
115 {`[^\D\d]`, "abcd", -1, nil},
116 {`[^\D[:digit:]]`, "abcd", -1, nil},
117 {`(?i)\W`, "x", -1, nil},
118 {`(?i)\W`, "k", -1, nil},
119 {`(?i)\W`, "s", -1, nil},
120
121
122 {`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
123 `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, -1, build(1, 0, 31)},
124 {`[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~]+`,
125 `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, -1, build(1, 0, 31)},
126 {"\\`", "`", -1, build(1, 0, 1)},
127 {"[\\`]+", "`", -1, build(1, 0, 1)},
128
129 {"\ufffd", "\xff", -1, build(1, 0, 1)},
130 {"\ufffd", "hello\xffworld", -1, build(1, 5, 6)},
131 {`.*`, "hello\xffworld", -1, build(1, 0, 11)},
132 {`\x{fffd}`, "\xc2\x00", -1, build(1, 0, 1)},
133 {"[\ufffd]", "\xff", -1, build(1, 0, 1)},
134 {`[\x{fffd}]`, "\xc2\x00", -1, build(1, 0, 1)},
135
136
137 {
138 ".",
139 "qwertyuiopasdfghjklzxcvbnm1234567890",
140 -1,
141 build(36, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
142 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
143 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30,
144 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36),
145 },
146 }
147
148
149
150 func build(n int, x ...int) [][]int {
151 ret := make([][]int, n)
152 runLength := len(x) / n
153 j := 0
154 for i := range ret {
155 ret[i] = make([]int, runLength)
156 copy(ret[i], x[j:])
157 j += runLength
158 if j > len(x) {
159 panic("invalid build entry")
160 }
161 }
162 return ret
163 }
164
165
166
167 func TestFind(t *testing.T) {
168 for _, test := range findTests {
169 re := MustCompile(test.pat)
170 if re.String() != test.pat {
171 t.Errorf("re.String() = %q, want %q", re.String(), test.pat)
172 }
173 result := re.Find([]byte(test.text))
174 switch {
175 case test.max == 0:
176
177 case len(test.matches) == 0 && len(result) == 0:
178
179 case test.matches == nil && result != nil:
180 t.Errorf("got match %q, want none: %s", result, test)
181 case test.matches != nil && result == nil:
182 t.Errorf("got no match, want one: %s", test)
183 case test.matches != nil && result != nil:
184 want := test.text[test.matches[0][0]:test.matches[0][1]]
185 if len(result) != cap(result) {
186 t.Errorf("got capacity %d, want %d: %s", cap(result), len(result), test)
187 }
188 if want != string(result) {
189 t.Errorf("got %q, want %q: %s", result, want, test)
190 }
191 }
192 }
193 }
194
195 func TestFindString(t *testing.T) {
196 for _, test := range findTests {
197 result := MustCompile(test.pat).FindString(test.text)
198 switch {
199 case test.max == 0:
200
201 case len(test.matches) == 0 && len(result) == 0:
202
203 case test.matches == nil && result != "":
204 t.Errorf("got match %q, want none: %s", result, test)
205 case test.matches != nil && result == "":
206
207 if test.matches[0][0] != test.matches[0][1] {
208 t.Errorf("got no match, want one: %s", test)
209 }
210 case test.matches != nil && result != "":
211 want := test.text[test.matches[0][0]:test.matches[0][1]]
212 if want != result {
213 t.Errorf("got %q, want %q: %s", result, want, test)
214 }
215 }
216 }
217 }
218
219 func testFindIndex(test *FindTest, result []int, t *testing.T) {
220 switch {
221 case test.max == 0:
222
223 case len(test.matches) == 0 && len(result) == 0:
224
225 case test.matches == nil && result != nil:
226 t.Errorf("got match %v, want none: %s", result, test)
227 case test.matches != nil && result == nil:
228 t.Errorf("got no match, want one: %s", test)
229 case test.matches != nil && result != nil:
230 want := test.matches[0]
231 if want[0] != result[0] || want[1] != result[1] {
232 t.Errorf("got %v, want %v: %s", result, want, test)
233 }
234 }
235 }
236
237 func TestFindIndex(t *testing.T) {
238 for _, test := range findTests {
239 testFindIndex(&test, MustCompile(test.pat).FindIndex([]byte(test.text)), t)
240 }
241 }
242
243 func TestFindStringIndex(t *testing.T) {
244 for _, test := range findTests {
245 testFindIndex(&test, MustCompile(test.pat).FindStringIndex(test.text), t)
246 }
247 }
248
249 func TestFindReaderIndex(t *testing.T) {
250 for _, test := range findTests {
251 testFindIndex(&test, MustCompile(test.pat).FindReaderIndex(strings.NewReader(test.text)), t)
252 }
253 }
254
255
256
257 func TestFindAll(t *testing.T) {
258 for _, test := range findTests {
259 result := MustCompile(test.pat).FindAll([]byte(test.text), test.max)
260 switch {
261 case test.matches == nil && result == nil:
262
263 case test.matches == nil && result != nil:
264 t.Errorf("got match %q, want none: %s", result, test)
265 case test.matches != nil && result == nil:
266 t.Fatalf("got no match, want one: %s", test)
267 case test.matches != nil && result != nil:
268 if len(test.matches) != len(result) {
269 t.Errorf("got %d matches, want %d: %s", len(result), len(test.matches), test)
270 continue
271 }
272 for k, e := range test.matches {
273 got := result[k]
274 if len(got) != cap(got) {
275 t.Errorf("match %d: got capacity %d, want %d: %s", k, cap(got), len(got), test)
276 }
277 want := test.text[e[0]:e[1]]
278 if want != string(got) {
279 t.Errorf("match %d: got %q, want %q: %s", k, got, want, test)
280 }
281 }
282 }
283 }
284 }
285
286 func TestFindAllString(t *testing.T) {
287 for _, test := range findTests {
288 result := MustCompile(test.pat).FindAllString(test.text, test.max)
289 switch {
290 case test.matches == nil && result == nil:
291
292 case test.matches == nil && result != nil:
293 t.Errorf("got match %q, want none: %s", result, test)
294 case test.matches != nil && result == nil:
295 t.Errorf("got no match, want one: %s", test)
296 case test.matches != nil && result != nil:
297 if len(test.matches) != len(result) {
298 t.Errorf("got %d matches, want %d: %s", len(result), len(test.matches), test)
299 continue
300 }
301 for k, e := range test.matches {
302 want := test.text[e[0]:e[1]]
303 if want != result[k] {
304 t.Errorf("got %q, want %q: %s", result[k], want, test)
305 }
306 }
307 }
308 }
309 }
310
311 func testFindAllIndex(test *FindTest, result [][]int, t *testing.T) {
312 switch {
313 case test.matches == nil && result == nil:
314
315 case test.matches == nil && result != nil:
316 t.Errorf("got match %v, want none: %s", result, test)
317 case test.matches != nil && result == nil:
318 t.Errorf("got no match, want one: %s", test)
319 case test.matches != nil && result != nil:
320 if len(test.matches) != len(result) {
321 t.Errorf("got %d matches, want %d: %s", len(result), len(test.matches), test)
322 return
323 }
324 for k, e := range test.matches {
325 if e[0] != result[k][0] || e[1] != result[k][1] {
326 t.Errorf("match %d: got %v, want %v: %s", k, result[k], e, test)
327 }
328 }
329 }
330 }
331
332 func TestFindAllIndex(t *testing.T) {
333 for _, test := range findTests {
334 testFindAllIndex(&test, MustCompile(test.pat).FindAllIndex([]byte(test.text), test.max), t)
335 }
336 }
337
338 func TestFindAllStringIndex(t *testing.T) {
339 for _, test := range findTests {
340 testFindAllIndex(&test, MustCompile(test.pat).FindAllStringIndex(test.text, test.max), t)
341 }
342 }
343
344
345
346 func testSubmatchBytes(test *FindTest, n int, submatches []int, result [][]byte, t *testing.T) {
347 if len(submatches) != len(result)*2 {
348 t.Errorf("match %d: got %d submatches, want %d: %s", n, len(result), len(submatches)/2, test)
349 return
350 }
351 for k := 0; k < len(submatches); k += 2 {
352 if submatches[k] == -1 {
353 if result[k/2] != nil {
354 t.Errorf("match %d: got %q, want nil: %s", n, result, test)
355 }
356 continue
357 }
358 got := result[k/2]
359 if len(got) != cap(got) {
360 t.Errorf("match %d: got capacity %d, want %d: %s", n, cap(got), len(got), test)
361 return
362 }
363 want := test.text[submatches[k]:submatches[k+1]]
364 if want != string(got) {
365 t.Errorf("match %d: got %q, want %q: %s", n, got, want, test)
366 return
367 }
368 }
369 }
370
371 func TestFindSubmatch(t *testing.T) {
372 for _, test := range findTests {
373 result := MustCompile(test.pat).FindSubmatch([]byte(test.text))
374 switch {
375 case test.max == 0:
376
377 case test.matches == nil && result == nil:
378
379 case test.matches == nil && result != nil:
380 t.Errorf("got match %q, want none: %s", result, test)
381 case test.matches != nil && result == nil:
382 t.Errorf("got no match, want one: %s", test)
383 case test.matches != nil && result != nil:
384 testSubmatchBytes(&test, 0, test.matches[0], result, t)
385 }
386 }
387 }
388
389 func testSubmatchString(test *FindTest, n int, submatches []int, result []string, t *testing.T) {
390 if len(submatches) != len(result)*2 {
391 t.Errorf("match %d: got %d submatches, want %d: %s", n, len(result), len(submatches)/2, test)
392 return
393 }
394 for k := 0; k < len(submatches); k += 2 {
395 if submatches[k] == -1 {
396 if result[k/2] != "" {
397 t.Errorf("match %d: got %q, want empty string: %s", n, result, test)
398 }
399 continue
400 }
401 want := test.text[submatches[k]:submatches[k+1]]
402 if want != result[k/2] {
403 t.Errorf("match %d: got %q, want %q: %s", n, result[k/2], want, test)
404 return
405 }
406 }
407 }
408
409 func TestFindStringSubmatch(t *testing.T) {
410 for _, test := range findTests {
411 result := MustCompile(test.pat).FindStringSubmatch(test.text)
412 switch {
413 case test.max == 0:
414
415 case test.matches == nil && result == nil:
416
417 case test.matches == nil && result != nil:
418 t.Errorf("got match %q, want none: %s", result, test)
419 case test.matches != nil && result == nil:
420 t.Errorf("got no match, want one: %s", test)
421 case test.matches != nil && result != nil:
422 testSubmatchString(&test, 0, test.matches[0], result, t)
423 }
424 }
425 }
426
427 func testSubmatchIndices(test *FindTest, n int, want, result []int, t *testing.T) {
428 if len(want) != len(result) {
429 t.Errorf("match %d: got %d matches, want %d: %s", n, len(result)/2, len(want)/2, test)
430 return
431 }
432 for k, e := range want {
433 if e != result[k] {
434 t.Errorf("match %d: submatch error: got %v, want %v: %s", n, result, want, test)
435 }
436 }
437 }
438
439 func testFindSubmatchIndex(test *FindTest, result []int, t *testing.T) {
440 switch {
441 case test.max == 0:
442
443 case test.matches == nil && result == nil:
444
445 case test.matches == nil && result != nil:
446 t.Errorf("got match %v, want none: %s", result, test)
447 case test.matches != nil && result == nil:
448 t.Errorf("got no match, want one: %s", test)
449 case test.matches != nil && result != nil:
450 testSubmatchIndices(test, 0, test.matches[0], result, t)
451 }
452 }
453
454 func TestFindSubmatchIndex(t *testing.T) {
455 for _, test := range findTests {
456 testFindSubmatchIndex(&test, MustCompile(test.pat).FindSubmatchIndex([]byte(test.text)), t)
457 }
458 }
459
460 func TestFindStringSubmatchIndex(t *testing.T) {
461 for _, test := range findTests {
462 testFindSubmatchIndex(&test, MustCompile(test.pat).FindStringSubmatchIndex(test.text), t)
463 }
464 }
465
466 func TestFindReaderSubmatchIndex(t *testing.T) {
467 for _, test := range findTests {
468 testFindSubmatchIndex(&test, MustCompile(test.pat).FindReaderSubmatchIndex(strings.NewReader(test.text)), t)
469 }
470 }
471
472
473
474 func TestFindAllSubmatch(t *testing.T) {
475 for _, test := range findTests {
476 result := MustCompile(test.pat).FindAllSubmatch([]byte(test.text), test.max)
477 switch {
478 case test.matches == nil && result == nil:
479
480 case test.matches == nil && result != nil:
481 t.Errorf("got match %q, want none: %s", result, test)
482 case test.matches != nil && result == nil:
483 t.Errorf("got no match, want one: %s", test)
484 case len(test.matches) != len(result):
485 t.Errorf("got %d matches, want %d: %s", len(result), len(test.matches), test)
486 case test.matches != nil && result != nil:
487 for k, match := range test.matches {
488 testSubmatchBytes(&test, k, match, result[k], t)
489 }
490 }
491 }
492 }
493
494 func TestFindAllStringSubmatch(t *testing.T) {
495 for _, test := range findTests {
496 result := MustCompile(test.pat).FindAllStringSubmatch(test.text, test.max)
497 switch {
498 case test.matches == nil && result == nil:
499
500 case test.matches == nil && result != nil:
501 t.Errorf("got match %q, want none: %s", result, test)
502 case test.matches != nil && result == nil:
503 t.Errorf("got no match, want one: %s", test)
504 case len(test.matches) != len(result):
505 t.Errorf("got %d matches, want %d: %s", len(result), len(test.matches), test)
506 case test.matches != nil && result != nil:
507 for k, match := range test.matches {
508 testSubmatchString(&test, k, match, result[k], t)
509 }
510 }
511 }
512 }
513
514 func testFindAllSubmatchIndex(test *FindTest, result [][]int, t *testing.T) {
515 switch {
516 case test.matches == nil && result == nil:
517
518 case test.matches == nil && result != nil:
519 t.Errorf("got match %v, want none: %s", result, test)
520 case test.matches != nil && result == nil:
521 t.Errorf("got no match, want one: %s", test)
522 case len(test.matches) != len(result):
523 t.Errorf("got %d matches, want %d: %s", len(result), len(test.matches), test)
524 case test.matches != nil && result != nil:
525 for k, match := range test.matches {
526 testSubmatchIndices(test, k, match, result[k], t)
527 }
528 }
529 }
530
531 func TestFindAllSubmatchIndex(t *testing.T) {
532 for _, test := range findTests {
533 testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllSubmatchIndex([]byte(test.text), test.max), t)
534 }
535 }
536
537 func TestFindAllStringSubmatchIndex(t *testing.T) {
538 for _, test := range findTests {
539 testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllStringSubmatchIndex(test.text, test.max), t)
540 }
541 }
542
View as plain text