]> Cypherpunks.ru repositories - gostls13.git/blob - src/regexp/find_test.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / regexp / find_test.go
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' results,
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\f\n\r\t\v`, "\a\f\n\r\t\v", build(1, 0, 6)},
62         {`[\a\f\n\r\t\v]+`, "\a\f\n\r\t\v", build(1, 0, 6)},
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         {`ab$`, "abcab", build(1, 3, 5)},
84         {`(aa)*$`, "a", build(1, 1, 1, -1, -1)},
85         {`(?:.|(?:.a))`, "", nil},
86         {`(?:A(?:A|a))`, "Aa", build(1, 0, 2)},
87         {`(?:A|(?:A|a))`, "a", build(1, 0, 1)},
88         {`(a){0}`, "", build(1, 0, 0, -1, -1)},
89         {`(?-s)(?:(?:^).)`, "\n", nil},
90         {`(?s)(?:(?:^).)`, "\n", build(1, 0, 1)},
91         {`(?:(?:^).)`, "\n", nil},
92         {`\b`, "x", build(2, 0, 0, 1, 1)},
93         {`\b`, "xx", build(2, 0, 0, 2, 2)},
94         {`\b`, "x y", build(4, 0, 0, 1, 1, 2, 2, 3, 3)},
95         {`\b`, "xx yy", build(4, 0, 0, 2, 2, 3, 3, 5, 5)},
96         {`\B`, "x", nil},
97         {`\B`, "xx", build(1, 1, 1)},
98         {`\B`, "x y", nil},
99         {`\B`, "xx yy", build(2, 1, 1, 4, 4)},
100         {`(|a)*`, "aa", build(3, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2)},
101
102         // RE2 tests
103         {`[^\S\s]`, "abcd", nil},
104         {`[^\S[:space:]]`, "abcd", nil},
105         {`[^\D\d]`, "abcd", nil},
106         {`[^\D[:digit:]]`, "abcd", nil},
107         {`(?i)\W`, "x", nil},
108         {`(?i)\W`, "k", nil},
109         {`(?i)\W`, "s", nil},
110
111         // can backslash-escape any punctuation
112         {`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
113                 `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
114         {`[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~]+`,
115                 `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
116         {"\\`", "`", build(1, 0, 1)},
117         {"[\\`]+", "`", build(1, 0, 1)},
118
119         {"\ufffd", "\xff", build(1, 0, 1)},
120         {"\ufffd", "hello\xffworld", build(1, 5, 6)},
121         {`.*`, "hello\xffworld", build(1, 0, 11)},
122         {`\x{fffd}`, "\xc2\x00", build(1, 0, 1)},
123         {"[\ufffd]", "\xff", build(1, 0, 1)},
124         {`[\x{fffd}]`, "\xc2\x00", build(1, 0, 1)},
125
126         // long set of matches (longer than startSize)
127         {
128                 ".",
129                 "qwertyuiopasdfghjklzxcvbnm1234567890",
130                 build(36, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
131                         10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
132                         20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30,
133                         30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36),
134         },
135 }
136
137 // build is a helper to construct a [][]int by extracting n sequences from x.
138 // This represents n matches with len(x)/n submatches each.
139 func build(n int, x ...int) [][]int {
140         ret := make([][]int, n)
141         runLength := len(x) / n
142         j := 0
143         for i := range ret {
144                 ret[i] = make([]int, runLength)
145                 copy(ret[i], x[j:])
146                 j += runLength
147                 if j > len(x) {
148                         panic("invalid build entry")
149                 }
150         }
151         return ret
152 }
153
154 // First the simple cases.
155
156 func TestFind(t *testing.T) {
157         for _, test := range findTests {
158                 re := MustCompile(test.pat)
159                 if re.String() != test.pat {
160                         t.Errorf("String() = `%s`; should be `%s`", re.String(), test.pat)
161                 }
162                 result := re.Find([]byte(test.text))
163                 switch {
164                 case len(test.matches) == 0 && len(result) == 0:
165                         // ok
166                 case test.matches == nil && result != nil:
167                         t.Errorf("expected no match; got one: %s", test)
168                 case test.matches != nil && result == nil:
169                         t.Errorf("expected match; got none: %s", test)
170                 case test.matches != nil && result != nil:
171                         expect := test.text[test.matches[0][0]:test.matches[0][1]]
172                         if len(result) != cap(result) {
173                                 t.Errorf("expected capacity %d got %d: %s", len(result), cap(result), test)
174                         }
175                         if expect != string(result) {
176                                 t.Errorf("expected %q got %q: %s", expect, result, test)
177                         }
178                 }
179         }
180 }
181
182 func TestFindString(t *testing.T) {
183         for _, test := range findTests {
184                 result := MustCompile(test.pat).FindString(test.text)
185                 switch {
186                 case len(test.matches) == 0 && len(result) == 0:
187                         // ok
188                 case test.matches == nil && result != "":
189                         t.Errorf("expected no match; got one: %s", test)
190                 case test.matches != nil && result == "":
191                         // Tricky because an empty result has two meanings: no match or empty match.
192                         if test.matches[0][0] != test.matches[0][1] {
193                                 t.Errorf("expected match; got none: %s", test)
194                         }
195                 case test.matches != nil && result != "":
196                         expect := test.text[test.matches[0][0]:test.matches[0][1]]
197                         if expect != result {
198                                 t.Errorf("expected %q got %q: %s", expect, result, test)
199                         }
200                 }
201         }
202 }
203
204 func testFindIndex(test *FindTest, result []int, t *testing.T) {
205         switch {
206         case len(test.matches) == 0 && len(result) == 0:
207                 // ok
208         case test.matches == nil && result != nil:
209                 t.Errorf("expected no match; got one: %s", test)
210         case test.matches != nil && result == nil:
211                 t.Errorf("expected match; got none: %s", test)
212         case test.matches != nil && result != nil:
213                 expect := test.matches[0]
214                 if expect[0] != result[0] || expect[1] != result[1] {
215                         t.Errorf("expected %v got %v: %s", expect, result, test)
216                 }
217         }
218 }
219
220 func TestFindIndex(t *testing.T) {
221         for _, test := range findTests {
222                 testFindIndex(&test, MustCompile(test.pat).FindIndex([]byte(test.text)), t)
223         }
224 }
225
226 func TestFindStringIndex(t *testing.T) {
227         for _, test := range findTests {
228                 testFindIndex(&test, MustCompile(test.pat).FindStringIndex(test.text), t)
229         }
230 }
231
232 func TestFindReaderIndex(t *testing.T) {
233         for _, test := range findTests {
234                 testFindIndex(&test, MustCompile(test.pat).FindReaderIndex(strings.NewReader(test.text)), t)
235         }
236 }
237
238 // Now come the simple All cases.
239
240 func TestFindAll(t *testing.T) {
241         for _, test := range findTests {
242                 result := MustCompile(test.pat).FindAll([]byte(test.text), -1)
243                 switch {
244                 case test.matches == nil && result == nil:
245                         // ok
246                 case test.matches == nil && result != nil:
247                         t.Errorf("expected no match; got one: %s", test)
248                 case test.matches != nil && result == nil:
249                         t.Fatalf("expected match; got none: %s", test)
250                 case test.matches != nil && result != nil:
251                         if len(test.matches) != len(result) {
252                                 t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
253                                 continue
254                         }
255                         for k, e := range test.matches {
256                                 got := result[k]
257                                 if len(got) != cap(got) {
258                                         t.Errorf("match %d: expected capacity %d got %d: %s", k, len(got), cap(got), test)
259                                 }
260                                 expect := test.text[e[0]:e[1]]
261                                 if expect != string(got) {
262                                         t.Errorf("match %d: expected %q got %q: %s", k, expect, got, test)
263                                 }
264                         }
265                 }
266         }
267 }
268
269 func TestFindAllString(t *testing.T) {
270         for _, test := range findTests {
271                 result := MustCompile(test.pat).FindAllString(test.text, -1)
272                 switch {
273                 case test.matches == nil && result == nil:
274                         // ok
275                 case test.matches == nil && result != nil:
276                         t.Errorf("expected no match; got one: %s", test)
277                 case test.matches != nil && result == nil:
278                         t.Errorf("expected match; got none: %s", test)
279                 case test.matches != nil && result != nil:
280                         if len(test.matches) != len(result) {
281                                 t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
282                                 continue
283                         }
284                         for k, e := range test.matches {
285                                 expect := test.text[e[0]:e[1]]
286                                 if expect != result[k] {
287                                         t.Errorf("expected %q got %q: %s", expect, result, test)
288                                 }
289                         }
290                 }
291         }
292 }
293
294 func testFindAllIndex(test *FindTest, result [][]int, t *testing.T) {
295         switch {
296         case test.matches == nil && result == nil:
297                 // ok
298         case test.matches == nil && result != nil:
299                 t.Errorf("expected no match; got one: %s", test)
300         case test.matches != nil && result == nil:
301                 t.Errorf("expected match; got none: %s", test)
302         case test.matches != nil && result != nil:
303                 if len(test.matches) != len(result) {
304                         t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
305                         return
306                 }
307                 for k, e := range test.matches {
308                         if e[0] != result[k][0] || e[1] != result[k][1] {
309                                 t.Errorf("match %d: expected %v got %v: %s", k, e, result[k], test)
310                         }
311                 }
312         }
313 }
314
315 func TestFindAllIndex(t *testing.T) {
316         for _, test := range findTests {
317                 testFindAllIndex(&test, MustCompile(test.pat).FindAllIndex([]byte(test.text), -1), t)
318         }
319 }
320
321 func TestFindAllStringIndex(t *testing.T) {
322         for _, test := range findTests {
323                 testFindAllIndex(&test, MustCompile(test.pat).FindAllStringIndex(test.text, -1), t)
324         }
325 }
326
327 // Now come the Submatch cases.
328
329 func testSubmatchBytes(test *FindTest, n int, submatches []int, result [][]byte, t *testing.T) {
330         if len(submatches) != len(result)*2 {
331                 t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
332                 return
333         }
334         for k := 0; k < len(submatches); k += 2 {
335                 if submatches[k] == -1 {
336                         if result[k/2] != nil {
337                                 t.Errorf("match %d: expected nil got %q: %s", n, result, test)
338                         }
339                         continue
340                 }
341                 got := result[k/2]
342                 if len(got) != cap(got) {
343                         t.Errorf("match %d: expected capacity %d got %d: %s", n, len(got), cap(got), test)
344                         return
345                 }
346                 expect := test.text[submatches[k]:submatches[k+1]]
347                 if expect != string(got) {
348                         t.Errorf("match %d: expected %q got %q: %s", n, expect, got, test)
349                         return
350                 }
351         }
352 }
353
354 func TestFindSubmatch(t *testing.T) {
355         for _, test := range findTests {
356                 result := MustCompile(test.pat).FindSubmatch([]byte(test.text))
357                 switch {
358                 case test.matches == nil && result == nil:
359                         // ok
360                 case test.matches == nil && result != nil:
361                         t.Errorf("expected no match; got one: %s", test)
362                 case test.matches != nil && result == nil:
363                         t.Errorf("expected match; got none: %s", test)
364                 case test.matches != nil && result != nil:
365                         testSubmatchBytes(&test, 0, test.matches[0], result, t)
366                 }
367         }
368 }
369
370 func testSubmatchString(test *FindTest, n int, submatches []int, result []string, t *testing.T) {
371         if len(submatches) != len(result)*2 {
372                 t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
373                 return
374         }
375         for k := 0; k < len(submatches); k += 2 {
376                 if submatches[k] == -1 {
377                         if result[k/2] != "" {
378                                 t.Errorf("match %d: expected nil got %q: %s", n, result, test)
379                         }
380                         continue
381                 }
382                 expect := test.text[submatches[k]:submatches[k+1]]
383                 if expect != result[k/2] {
384                         t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test)
385                         return
386                 }
387         }
388 }
389
390 func TestFindStringSubmatch(t *testing.T) {
391         for _, test := range findTests {
392                 result := MustCompile(test.pat).FindStringSubmatch(test.text)
393                 switch {
394                 case test.matches == nil && result == nil:
395                         // ok
396                 case test.matches == nil && result != nil:
397                         t.Errorf("expected no match; got one: %s", test)
398                 case test.matches != nil && result == nil:
399                         t.Errorf("expected match; got none: %s", test)
400                 case test.matches != nil && result != nil:
401                         testSubmatchString(&test, 0, test.matches[0], result, t)
402                 }
403         }
404 }
405
406 func testSubmatchIndices(test *FindTest, n int, expect, result []int, t *testing.T) {
407         if len(expect) != len(result) {
408                 t.Errorf("match %d: expected %d matches; got %d: %s", n, len(expect)/2, len(result)/2, test)
409                 return
410         }
411         for k, e := range expect {
412                 if e != result[k] {
413                         t.Errorf("match %d: submatch error: expected %v got %v: %s", n, expect, result, test)
414                 }
415         }
416 }
417
418 func testFindSubmatchIndex(test *FindTest, result []int, t *testing.T) {
419         switch {
420         case test.matches == nil && result == nil:
421                 // ok
422         case test.matches == nil && result != nil:
423                 t.Errorf("expected no match; got one: %s", test)
424         case test.matches != nil && result == nil:
425                 t.Errorf("expected match; got none: %s", test)
426         case test.matches != nil && result != nil:
427                 testSubmatchIndices(test, 0, test.matches[0], result, t)
428         }
429 }
430
431 func TestFindSubmatchIndex(t *testing.T) {
432         for _, test := range findTests {
433                 testFindSubmatchIndex(&test, MustCompile(test.pat).FindSubmatchIndex([]byte(test.text)), t)
434         }
435 }
436
437 func TestFindStringSubmatchIndex(t *testing.T) {
438         for _, test := range findTests {
439                 testFindSubmatchIndex(&test, MustCompile(test.pat).FindStringSubmatchIndex(test.text), t)
440         }
441 }
442
443 func TestFindReaderSubmatchIndex(t *testing.T) {
444         for _, test := range findTests {
445                 testFindSubmatchIndex(&test, MustCompile(test.pat).FindReaderSubmatchIndex(strings.NewReader(test.text)), t)
446         }
447 }
448
449 // Now come the monster AllSubmatch cases.
450
451 func TestFindAllSubmatch(t *testing.T) {
452         for _, test := range findTests {
453                 result := MustCompile(test.pat).FindAllSubmatch([]byte(test.text), -1)
454                 switch {
455                 case test.matches == nil && result == nil:
456                         // ok
457                 case test.matches == nil && result != nil:
458                         t.Errorf("expected no match; got one: %s", test)
459                 case test.matches != nil && result == nil:
460                         t.Errorf("expected match; got none: %s", test)
461                 case len(test.matches) != len(result):
462                         t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
463                 case test.matches != nil && result != nil:
464                         for k, match := range test.matches {
465                                 testSubmatchBytes(&test, k, match, result[k], t)
466                         }
467                 }
468         }
469 }
470
471 func TestFindAllStringSubmatch(t *testing.T) {
472         for _, test := range findTests {
473                 result := MustCompile(test.pat).FindAllStringSubmatch(test.text, -1)
474                 switch {
475                 case test.matches == nil && result == nil:
476                         // ok
477                 case test.matches == nil && result != nil:
478                         t.Errorf("expected no match; got one: %s", test)
479                 case test.matches != nil && result == nil:
480                         t.Errorf("expected match; got none: %s", test)
481                 case len(test.matches) != len(result):
482                         t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
483                 case test.matches != nil && result != nil:
484                         for k, match := range test.matches {
485                                 testSubmatchString(&test, k, match, result[k], t)
486                         }
487                 }
488         }
489 }
490
491 func testFindAllSubmatchIndex(test *FindTest, result [][]int, t *testing.T) {
492         switch {
493         case test.matches == nil && result == nil:
494                 // ok
495         case test.matches == nil && result != nil:
496                 t.Errorf("expected no match; got one: %s", test)
497         case test.matches != nil && result == nil:
498                 t.Errorf("expected match; got none: %s", test)
499         case len(test.matches) != len(result):
500                 t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
501         case test.matches != nil && result != nil:
502                 for k, match := range test.matches {
503                         testSubmatchIndices(test, k, match, result[k], t)
504                 }
505         }
506 }
507
508 func TestFindAllSubmatchIndex(t *testing.T) {
509         for _, test := range findTests {
510                 testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllSubmatchIndex([]byte(test.text), -1), t)
511         }
512 }
513
514 func TestFindAllStringSubmatchIndex(t *testing.T) {
515         for _, test := range findTests {
516                 testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllStringSubmatchIndex(test.text, -1), t)
517         }
518 }