Source file 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  	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  	// multiple matches
    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  	// fixed bugs
    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  	// RE2 tests
   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  	// can backslash-escape any punctuation
   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  	// long set of matches (longer than startSize)
   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  // build is a helper to construct a [][]int by extracting n sequences from x.
   149  // This represents n matches with len(x)/n submatches each.
   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  // First the simple cases.
   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  			// do not know whether to match or not; skip
   177  		case len(test.matches) == 0 && len(result) == 0:
   178  			// ok
   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  			// do not know whether to match or not; skip
   201  		case len(test.matches) == 0 && len(result) == 0:
   202  			// ok
   203  		case test.matches == nil && result != "":
   204  			t.Errorf("got match %q, want none: %s", result, test)
   205  		case test.matches != nil && result == "":
   206  			// Tricky because an empty result has two meanings: no match or empty match.
   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  		// do not know whether to match or not; skip
   223  	case len(test.matches) == 0 && len(result) == 0:
   224  		// ok
   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  // Now come the simple All cases.
   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  			// ok
   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  			// ok
   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  		// ok
   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  // Now come the Submatch cases.
   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  			// do not know whether to match or not; skip
   377  		case test.matches == nil && result == nil:
   378  			// ok
   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  			// do not know whether to match or not; skip
   415  		case test.matches == nil && result == nil:
   416  			// ok
   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  		// do not know whether to match or not; skip
   443  	case test.matches == nil && result == nil:
   444  		// ok
   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  // Now come the monster AllSubmatch cases.
   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  			// ok
   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  			// ok
   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  		// ok
   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