...
Run Format

Source file src/regexp/all_test.go

     1	// Copyright 2009 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		"reflect"
     9		"regexp/syntax"
    10		"strings"
    11		"testing"
    12	)
    13	
    14	var good_re = []string{
    15		``,
    16		`.`,
    17		`^.$`,
    18		`a`,
    19		`a*`,
    20		`a+`,
    21		`a?`,
    22		`a|b`,
    23		`a*|b*`,
    24		`(a*|b)(c*|d)`,
    25		`[a-z]`,
    26		`[a-abc-c\-\]\[]`,
    27		`[a-z]+`,
    28		`[abc]`,
    29		`[^1234]`,
    30		`[^\n]`,
    31		`\!\\`,
    32	}
    33	
    34	type stringError struct {
    35		re  string
    36		err string
    37	}
    38	
    39	var bad_re = []stringError{
    40		{`*`, "missing argument to repetition operator: `*`"},
    41		{`+`, "missing argument to repetition operator: `+`"},
    42		{`?`, "missing argument to repetition operator: `?`"},
    43		{`(abc`, "missing closing ): `(abc`"},
    44		{`abc)`, "unexpected ): `abc)`"},
    45		{`x[a-z`, "missing closing ]: `[a-z`"},
    46		{`[z-a]`, "invalid character class range: `z-a`"},
    47		{`abc\`, "trailing backslash at end of expression"},
    48		{`a**`, "invalid nested repetition operator: `**`"},
    49		{`a*+`, "invalid nested repetition operator: `*+`"},
    50		{`\x`, "invalid escape sequence: `\\x`"},
    51	}
    52	
    53	func compileTest(t *testing.T, expr string, error string) *Regexp {
    54		re, err := Compile(expr)
    55		if error == "" && err != nil {
    56			t.Error("compiling `", expr, "`; unexpected error: ", err.Error())
    57		}
    58		if error != "" && err == nil {
    59			t.Error("compiling `", expr, "`; missing error")
    60		} else if error != "" && !strings.Contains(err.Error(), error) {
    61			t.Error("compiling `", expr, "`; wrong error: ", err.Error(), "; want ", error)
    62		}
    63		return re
    64	}
    65	
    66	func TestGoodCompile(t *testing.T) {
    67		for i := 0; i < len(good_re); i++ {
    68			compileTest(t, good_re[i], "")
    69		}
    70	}
    71	
    72	func TestBadCompile(t *testing.T) {
    73		for i := 0; i < len(bad_re); i++ {
    74			compileTest(t, bad_re[i].re, bad_re[i].err)
    75		}
    76	}
    77	
    78	func matchTest(t *testing.T, test *FindTest) {
    79		re := compileTest(t, test.pat, "")
    80		if re == nil {
    81			return
    82		}
    83		m := re.MatchString(test.text)
    84		if m != (len(test.matches) > 0) {
    85			t.Errorf("MatchString failure on %s: %t should be %t", test, m, len(test.matches) > 0)
    86		}
    87		// now try bytes
    88		m = re.Match([]byte(test.text))
    89		if m != (len(test.matches) > 0) {
    90			t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
    91		}
    92	}
    93	
    94	func TestMatch(t *testing.T) {
    95		for _, test := range findTests {
    96			matchTest(t, &test)
    97		}
    98	}
    99	
   100	func matchFunctionTest(t *testing.T, test *FindTest) {
   101		m, err := MatchString(test.pat, test.text)
   102		if err == nil {
   103			return
   104		}
   105		if m != (len(test.matches) > 0) {
   106			t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
   107		}
   108	}
   109	
   110	func TestMatchFunction(t *testing.T) {
   111		for _, test := range findTests {
   112			matchFunctionTest(t, &test)
   113		}
   114	}
   115	
   116	type ReplaceTest struct {
   117		pattern, replacement, input, output string
   118	}
   119	
   120	var replaceTests = []ReplaceTest{
   121		// Test empty input and/or replacement, with pattern that matches the empty string.
   122		{"", "", "", ""},
   123		{"", "x", "", "x"},
   124		{"", "", "abc", "abc"},
   125		{"", "x", "abc", "xaxbxcx"},
   126	
   127		// Test empty input and/or replacement, with pattern that does not match the empty string.
   128		{"b", "", "", ""},
   129		{"b", "x", "", ""},
   130		{"b", "", "abc", "ac"},
   131		{"b", "x", "abc", "axc"},
   132		{"y", "", "", ""},
   133		{"y", "x", "", ""},
   134		{"y", "", "abc", "abc"},
   135		{"y", "x", "abc", "abc"},
   136	
   137		// Multibyte characters -- verify that we don't try to match in the middle
   138		// of a character.
   139		{"[a-c]*", "x", "\u65e5", "x\u65e5x"},
   140		{"[^\u65e5]", "x", "abc\u65e5def", "xxx\u65e5xxx"},
   141	
   142		// Start and end of a string.
   143		{"^[a-c]*", "x", "abcdabc", "xdabc"},
   144		{"[a-c]*$", "x", "abcdabc", "abcdx"},
   145		{"^[a-c]*$", "x", "abcdabc", "abcdabc"},
   146		{"^[a-c]*", "x", "abc", "x"},
   147		{"[a-c]*$", "x", "abc", "x"},
   148		{"^[a-c]*$", "x", "abc", "x"},
   149		{"^[a-c]*", "x", "dabce", "xdabce"},
   150		{"[a-c]*$", "x", "dabce", "dabcex"},
   151		{"^[a-c]*$", "x", "dabce", "dabce"},
   152		{"^[a-c]*", "x", "", "x"},
   153		{"[a-c]*$", "x", "", "x"},
   154		{"^[a-c]*$", "x", "", "x"},
   155	
   156		{"^[a-c]+", "x", "abcdabc", "xdabc"},
   157		{"[a-c]+$", "x", "abcdabc", "abcdx"},
   158		{"^[a-c]+$", "x", "abcdabc", "abcdabc"},
   159		{"^[a-c]+", "x", "abc", "x"},
   160		{"[a-c]+$", "x", "abc", "x"},
   161		{"^[a-c]+$", "x", "abc", "x"},
   162		{"^[a-c]+", "x", "dabce", "dabce"},
   163		{"[a-c]+$", "x", "dabce", "dabce"},
   164		{"^[a-c]+$", "x", "dabce", "dabce"},
   165		{"^[a-c]+", "x", "", ""},
   166		{"[a-c]+$", "x", "", ""},
   167		{"^[a-c]+$", "x", "", ""},
   168	
   169		// Other cases.
   170		{"abc", "def", "abcdefg", "defdefg"},
   171		{"bc", "BC", "abcbcdcdedef", "aBCBCdcdedef"},
   172		{"abc", "", "abcdabc", "d"},
   173		{"x", "xXx", "xxxXxxx", "xXxxXxxXxXxXxxXxxXx"},
   174		{"abc", "d", "", ""},
   175		{"abc", "d", "abc", "d"},
   176		{".+", "x", "abc", "x"},
   177		{"[a-c]*", "x", "def", "xdxexfx"},
   178		{"[a-c]+", "x", "abcbcdcdedef", "xdxdedef"},
   179		{"[a-c]*", "x", "abcbcdcdedef", "xdxdxexdxexfx"},
   180	
   181		// Substitutions
   182		{"a+", "($0)", "banana", "b(a)n(a)n(a)"},
   183		{"a+", "(${0})", "banana", "b(a)n(a)n(a)"},
   184		{"a+", "(${0})$0", "banana", "b(a)an(a)an(a)a"},
   185		{"a+", "(${0})$0", "banana", "b(a)an(a)an(a)a"},
   186		{"hello, (.+)", "goodbye, ${1}", "hello, world", "goodbye, world"},
   187		{"hello, (.+)", "goodbye, $1x", "hello, world", "goodbye, "},
   188		{"hello, (.+)", "goodbye, ${1}x", "hello, world", "goodbye, worldx"},
   189		{"hello, (.+)", "<$0><$1><$2><$3>", "hello, world", "<hello, world><world><><>"},
   190		{"hello, (?P<noun>.+)", "goodbye, $noun!", "hello, world", "goodbye, world!"},
   191		{"hello, (?P<noun>.+)", "goodbye, ${noun}", "hello, world", "goodbye, world"},
   192		{"(?P<x>hi)|(?P<x>bye)", "$x$x$x", "hi", "hihihi"},
   193		{"(?P<x>hi)|(?P<x>bye)", "$x$x$x", "bye", "byebyebye"},
   194		{"(?P<x>hi)|(?P<x>bye)", "$xyz", "hi", ""},
   195		{"(?P<x>hi)|(?P<x>bye)", "${x}yz", "hi", "hiyz"},
   196		{"(?P<x>hi)|(?P<x>bye)", "hello $$x", "hi", "hello $x"},
   197		{"a+", "${oops", "aaa", "${oops"},
   198		{"a+", "$$", "aaa", "$"},
   199		{"a+", "$", "aaa", "$"},
   200	
   201		// Substitution when subexpression isn't found
   202		{"(x)?", "$1", "123", "123"},
   203		{"abc", "$1", "123", "123"},
   204	}
   205	
   206	var replaceLiteralTests = []ReplaceTest{
   207		// Substitutions
   208		{"a+", "($0)", "banana", "b($0)n($0)n($0)"},
   209		{"a+", "(${0})", "banana", "b(${0})n(${0})n(${0})"},
   210		{"a+", "(${0})$0", "banana", "b(${0})$0n(${0})$0n(${0})$0"},
   211		{"a+", "(${0})$0", "banana", "b(${0})$0n(${0})$0n(${0})$0"},
   212		{"hello, (.+)", "goodbye, ${1}", "hello, world", "goodbye, ${1}"},
   213		{"hello, (?P<noun>.+)", "goodbye, $noun!", "hello, world", "goodbye, $noun!"},
   214		{"hello, (?P<noun>.+)", "goodbye, ${noun}", "hello, world", "goodbye, ${noun}"},
   215		{"(?P<x>hi)|(?P<x>bye)", "$x$x$x", "hi", "$x$x$x"},
   216		{"(?P<x>hi)|(?P<x>bye)", "$x$x$x", "bye", "$x$x$x"},
   217		{"(?P<x>hi)|(?P<x>bye)", "$xyz", "hi", "$xyz"},
   218		{"(?P<x>hi)|(?P<x>bye)", "${x}yz", "hi", "${x}yz"},
   219		{"(?P<x>hi)|(?P<x>bye)", "hello $$x", "hi", "hello $$x"},
   220		{"a+", "${oops", "aaa", "${oops"},
   221		{"a+", "$$", "aaa", "$$"},
   222		{"a+", "$", "aaa", "$"},
   223	}
   224	
   225	type ReplaceFuncTest struct {
   226		pattern       string
   227		replacement   func(string) string
   228		input, output string
   229	}
   230	
   231	var replaceFuncTests = []ReplaceFuncTest{
   232		{"[a-c]", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxayxbyxcydef"},
   233		{"[a-c]+", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxabcydef"},
   234		{"[a-c]*", func(s string) string { return "x" + s + "y" }, "defabcdef", "xydxyexyfxabcydxyexyfxy"},
   235	}
   236	
   237	func TestReplaceAll(t *testing.T) {
   238		for _, tc := range replaceTests {
   239			re, err := Compile(tc.pattern)
   240			if err != nil {
   241				t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
   242				continue
   243			}
   244			actual := re.ReplaceAllString(tc.input, tc.replacement)
   245			if actual != tc.output {
   246				t.Errorf("%q.ReplaceAllString(%q,%q) = %q; want %q",
   247					tc.pattern, tc.input, tc.replacement, actual, tc.output)
   248			}
   249			// now try bytes
   250			actual = string(re.ReplaceAll([]byte(tc.input), []byte(tc.replacement)))
   251			if actual != tc.output {
   252				t.Errorf("%q.ReplaceAll(%q,%q) = %q; want %q",
   253					tc.pattern, tc.input, tc.replacement, actual, tc.output)
   254			}
   255		}
   256	}
   257	
   258	func TestReplaceAllLiteral(t *testing.T) {
   259		// Run ReplaceAll tests that do not have $ expansions.
   260		for _, tc := range replaceTests {
   261			if strings.Contains(tc.replacement, "$") {
   262				continue
   263			}
   264			re, err := Compile(tc.pattern)
   265			if err != nil {
   266				t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
   267				continue
   268			}
   269			actual := re.ReplaceAllLiteralString(tc.input, tc.replacement)
   270			if actual != tc.output {
   271				t.Errorf("%q.ReplaceAllLiteralString(%q,%q) = %q; want %q",
   272					tc.pattern, tc.input, tc.replacement, actual, tc.output)
   273			}
   274			// now try bytes
   275			actual = string(re.ReplaceAllLiteral([]byte(tc.input), []byte(tc.replacement)))
   276			if actual != tc.output {
   277				t.Errorf("%q.ReplaceAllLiteral(%q,%q) = %q; want %q",
   278					tc.pattern, tc.input, tc.replacement, actual, tc.output)
   279			}
   280		}
   281	
   282		// Run literal-specific tests.
   283		for _, tc := range replaceLiteralTests {
   284			re, err := Compile(tc.pattern)
   285			if err != nil {
   286				t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
   287				continue
   288			}
   289			actual := re.ReplaceAllLiteralString(tc.input, tc.replacement)
   290			if actual != tc.output {
   291				t.Errorf("%q.ReplaceAllLiteralString(%q,%q) = %q; want %q",
   292					tc.pattern, tc.input, tc.replacement, actual, tc.output)
   293			}
   294			// now try bytes
   295			actual = string(re.ReplaceAllLiteral([]byte(tc.input), []byte(tc.replacement)))
   296			if actual != tc.output {
   297				t.Errorf("%q.ReplaceAllLiteral(%q,%q) = %q; want %q",
   298					tc.pattern, tc.input, tc.replacement, actual, tc.output)
   299			}
   300		}
   301	}
   302	
   303	func TestReplaceAllFunc(t *testing.T) {
   304		for _, tc := range replaceFuncTests {
   305			re, err := Compile(tc.pattern)
   306			if err != nil {
   307				t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
   308				continue
   309			}
   310			actual := re.ReplaceAllStringFunc(tc.input, tc.replacement)
   311			if actual != tc.output {
   312				t.Errorf("%q.ReplaceFunc(%q,fn) = %q; want %q",
   313					tc.pattern, tc.input, actual, tc.output)
   314			}
   315			// now try bytes
   316			actual = string(re.ReplaceAllFunc([]byte(tc.input), func(s []byte) []byte { return []byte(tc.replacement(string(s))) }))
   317			if actual != tc.output {
   318				t.Errorf("%q.ReplaceFunc(%q,fn) = %q; want %q",
   319					tc.pattern, tc.input, actual, tc.output)
   320			}
   321		}
   322	}
   323	
   324	type MetaTest struct {
   325		pattern, output, literal string
   326		isLiteral                bool
   327	}
   328	
   329	var metaTests = []MetaTest{
   330		{``, ``, ``, true},
   331		{`foo`, `foo`, `foo`, true},
   332		{`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator
   333		{`foo.\$`, `foo\.\\\$`, `foo`, false},     // has escaped operators and real operators
   334		{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[\{\]\}\\\|,<\.>/\?~`, `!@#`, false},
   335	}
   336	
   337	func TestQuoteMeta(t *testing.T) {
   338		for _, tc := range metaTests {
   339			// Verify that QuoteMeta returns the expected string.
   340			quoted := QuoteMeta(tc.pattern)
   341			if quoted != tc.output {
   342				t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`",
   343					tc.pattern, quoted, tc.output)
   344				continue
   345			}
   346	
   347			// Verify that the quoted string is in fact treated as expected
   348			// by Compile -- i.e. that it matches the original, unquoted string.
   349			if tc.pattern != "" {
   350				re, err := Compile(quoted)
   351				if err != nil {
   352					t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err)
   353					continue
   354				}
   355				src := "abc" + tc.pattern + "def"
   356				repl := "xyz"
   357				replaced := re.ReplaceAllString(src, repl)
   358				expected := "abcxyzdef"
   359				if replaced != expected {
   360					t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`",
   361						tc.pattern, src, repl, replaced, expected)
   362				}
   363			}
   364		}
   365	}
   366	
   367	func TestLiteralPrefix(t *testing.T) {
   368		for _, tc := range metaTests {
   369			// Literal method needs to scan the pattern.
   370			re := MustCompile(tc.pattern)
   371			str, complete := re.LiteralPrefix()
   372			if complete != tc.isLiteral {
   373				t.Errorf("LiteralPrefix(`%s`) = %t; want %t", tc.pattern, complete, tc.isLiteral)
   374			}
   375			if str != tc.literal {
   376				t.Errorf("LiteralPrefix(`%s`) = `%s`; want `%s`", tc.pattern, str, tc.literal)
   377			}
   378		}
   379	}
   380	
   381	type subexpCase struct {
   382		input string
   383		num   int
   384		names []string
   385	}
   386	
   387	var subexpCases = []subexpCase{
   388		{``, 0, nil},
   389		{`.*`, 0, nil},
   390		{`abba`, 0, nil},
   391		{`ab(b)a`, 1, []string{"", ""}},
   392		{`ab(.*)a`, 1, []string{"", ""}},
   393		{`(.*)ab(.*)a`, 2, []string{"", "", ""}},
   394		{`(.*)(ab)(.*)a`, 3, []string{"", "", "", ""}},
   395		{`(.*)((a)b)(.*)a`, 4, []string{"", "", "", "", ""}},
   396		{`(.*)(\(ab)(.*)a`, 3, []string{"", "", "", ""}},
   397		{`(.*)(\(a\)b)(.*)a`, 3, []string{"", "", "", ""}},
   398		{`(?P<foo>.*)(?P<bar>(a)b)(?P<foo>.*)a`, 4, []string{"", "foo", "bar", "", "foo"}},
   399	}
   400	
   401	func TestSubexp(t *testing.T) {
   402		for _, c := range subexpCases {
   403			re := MustCompile(c.input)
   404			n := re.NumSubexp()
   405			if n != c.num {
   406				t.Errorf("%q: NumSubexp = %d, want %d", c.input, n, c.num)
   407				continue
   408			}
   409			names := re.SubexpNames()
   410			if len(names) != 1+n {
   411				t.Errorf("%q: len(SubexpNames) = %d, want %d", c.input, len(names), n)
   412				continue
   413			}
   414			if c.names != nil {
   415				for i := 0; i < 1+n; i++ {
   416					if names[i] != c.names[i] {
   417						t.Errorf("%q: SubexpNames[%d] = %q, want %q", c.input, i, names[i], c.names[i])
   418					}
   419				}
   420			}
   421		}
   422	}
   423	
   424	var splitTests = []struct {
   425		s   string
   426		r   string
   427		n   int
   428		out []string
   429	}{
   430		{"foo:and:bar", ":", -1, []string{"foo", "and", "bar"}},
   431		{"foo:and:bar", ":", 1, []string{"foo:and:bar"}},
   432		{"foo:and:bar", ":", 2, []string{"foo", "and:bar"}},
   433		{"foo:and:bar", "foo", -1, []string{"", ":and:bar"}},
   434		{"foo:and:bar", "bar", -1, []string{"foo:and:", ""}},
   435		{"foo:and:bar", "baz", -1, []string{"foo:and:bar"}},
   436		{"baabaab", "a", -1, []string{"b", "", "b", "", "b"}},
   437		{"baabaab", "a*", -1, []string{"b", "b", "b"}},
   438		{"baabaab", "ba*", -1, []string{"", "", "", ""}},
   439		{"foobar", "f*b*", -1, []string{"", "o", "o", "a", "r"}},
   440		{"foobar", "f+.*b+", -1, []string{"", "ar"}},
   441		{"foobooboar", "o{2}", -1, []string{"f", "b", "boar"}},
   442		{"a,b,c,d,e,f", ",", 3, []string{"a", "b", "c,d,e,f"}},
   443		{"a,b,c,d,e,f", ",", 0, nil},
   444		{",", ",", -1, []string{"", ""}},
   445		{",,,", ",", -1, []string{"", "", "", ""}},
   446		{"", ",", -1, []string{""}},
   447		{"", ".*", -1, []string{""}},
   448		{"", ".+", -1, []string{""}},
   449		{"", "", -1, []string{}},
   450		{"foobar", "", -1, []string{"f", "o", "o", "b", "a", "r"}},
   451		{"abaabaccadaaae", "a*", 5, []string{"", "b", "b", "c", "cadaaae"}},
   452		{":x:y:z:", ":", -1, []string{"", "x", "y", "z", ""}},
   453	}
   454	
   455	func TestSplit(t *testing.T) {
   456		for i, test := range splitTests {
   457			re, err := Compile(test.r)
   458			if err != nil {
   459				t.Errorf("#%d: %q: compile error: %s", i, test.r, err.Error())
   460				continue
   461			}
   462	
   463			split := re.Split(test.s, test.n)
   464			if !reflect.DeepEqual(split, test.out) {
   465				t.Errorf("#%d: %q: got %q; want %q", i, test.r, split, test.out)
   466			}
   467	
   468			if QuoteMeta(test.r) == test.r {
   469				strsplit := strings.SplitN(test.s, test.r, test.n)
   470				if !reflect.DeepEqual(split, strsplit) {
   471					t.Errorf("#%d: Split(%q, %q, %d): regexp vs strings mismatch\nregexp=%q\nstrings=%q", i, test.s, test.r, test.n, split, strsplit)
   472				}
   473			}
   474		}
   475	}
   476	
   477	// Check that one-pass cutoff does trigger.
   478	func TestOnePassCutoff(t *testing.T) {
   479		re, err := syntax.Parse(`^x{1,1000}y{1,1000}$`, syntax.Perl)
   480		if err != nil {
   481			t.Fatalf("parse: %v", err)
   482		}
   483		p, err := syntax.Compile(re.Simplify())
   484		if err != nil {
   485			t.Fatalf("compile: %v", err)
   486		}
   487		if compileOnePass(p) != notOnePass {
   488			t.Fatalf("makeOnePass succeeded; wanted notOnePass")
   489		}
   490	}
   491	
   492	func BenchmarkLiteral(b *testing.B) {
   493		x := strings.Repeat("x", 50) + "y"
   494		b.StopTimer()
   495		re := MustCompile("y")
   496		b.StartTimer()
   497		for i := 0; i < b.N; i++ {
   498			if !re.MatchString(x) {
   499				b.Fatalf("no match!")
   500			}
   501		}
   502	}
   503	
   504	func BenchmarkNotLiteral(b *testing.B) {
   505		x := strings.Repeat("x", 50) + "y"
   506		b.StopTimer()
   507		re := MustCompile(".y")
   508		b.StartTimer()
   509		for i := 0; i < b.N; i++ {
   510			if !re.MatchString(x) {
   511				b.Fatalf("no match!")
   512			}
   513		}
   514	}
   515	
   516	func BenchmarkMatchClass(b *testing.B) {
   517		b.StopTimer()
   518		x := strings.Repeat("xxxx", 20) + "w"
   519		re := MustCompile("[abcdw]")
   520		b.StartTimer()
   521		for i := 0; i < b.N; i++ {
   522			if !re.MatchString(x) {
   523				b.Fatalf("no match!")
   524			}
   525		}
   526	}
   527	
   528	func BenchmarkMatchClass_InRange(b *testing.B) {
   529		b.StopTimer()
   530		// 'b' is between 'a' and 'c', so the charclass
   531		// range checking is no help here.
   532		x := strings.Repeat("bbbb", 20) + "c"
   533		re := MustCompile("[ac]")
   534		b.StartTimer()
   535		for i := 0; i < b.N; i++ {
   536			if !re.MatchString(x) {
   537				b.Fatalf("no match!")
   538			}
   539		}
   540	}
   541	
   542	func BenchmarkReplaceAll(b *testing.B) {
   543		x := "abcdefghijklmnopqrstuvwxyz"
   544		b.StopTimer()
   545		re := MustCompile("[cjrw]")
   546		b.StartTimer()
   547		for i := 0; i < b.N; i++ {
   548			re.ReplaceAllString(x, "")
   549		}
   550	}
   551	
   552	func BenchmarkAnchoredLiteralShortNonMatch(b *testing.B) {
   553		b.StopTimer()
   554		x := []byte("abcdefghijklmnopqrstuvwxyz")
   555		re := MustCompile("^zbc(d|e)")
   556		b.StartTimer()
   557		for i := 0; i < b.N; i++ {
   558			re.Match(x)
   559		}
   560	}
   561	
   562	func BenchmarkAnchoredLiteralLongNonMatch(b *testing.B) {
   563		b.StopTimer()
   564		x := []byte("abcdefghijklmnopqrstuvwxyz")
   565		for i := 0; i < 15; i++ {
   566			x = append(x, x...)
   567		}
   568		re := MustCompile("^zbc(d|e)")
   569		b.StartTimer()
   570		for i := 0; i < b.N; i++ {
   571			re.Match(x)
   572		}
   573	}
   574	
   575	func BenchmarkAnchoredShortMatch(b *testing.B) {
   576		b.StopTimer()
   577		x := []byte("abcdefghijklmnopqrstuvwxyz")
   578		re := MustCompile("^.bc(d|e)")
   579		b.StartTimer()
   580		for i := 0; i < b.N; i++ {
   581			re.Match(x)
   582		}
   583	}
   584	
   585	func BenchmarkAnchoredLongMatch(b *testing.B) {
   586		b.StopTimer()
   587		x := []byte("abcdefghijklmnopqrstuvwxyz")
   588		for i := 0; i < 15; i++ {
   589			x = append(x, x...)
   590		}
   591		re := MustCompile("^.bc(d|e)")
   592		b.StartTimer()
   593		for i := 0; i < b.N; i++ {
   594			re.Match(x)
   595		}
   596	}
   597	
   598	func BenchmarkOnePassShortA(b *testing.B) {
   599		b.StopTimer()
   600		x := []byte("abcddddddeeeededd")
   601		re := MustCompile("^.bc(d|e)*$")
   602		b.StartTimer()
   603		for i := 0; i < b.N; i++ {
   604			re.Match(x)
   605		}
   606	}
   607	
   608	func BenchmarkNotOnePassShortA(b *testing.B) {
   609		b.StopTimer()
   610		x := []byte("abcddddddeeeededd")
   611		re := MustCompile(".bc(d|e)*$")
   612		b.StartTimer()
   613		for i := 0; i < b.N; i++ {
   614			re.Match(x)
   615		}
   616	}
   617	
   618	func BenchmarkOnePassShortB(b *testing.B) {
   619		b.StopTimer()
   620		x := []byte("abcddddddeeeededd")
   621		re := MustCompile("^.bc(?:d|e)*$")
   622		b.StartTimer()
   623		for i := 0; i < b.N; i++ {
   624			re.Match(x)
   625		}
   626	}
   627	
   628	func BenchmarkNotOnePassShortB(b *testing.B) {
   629		b.StopTimer()
   630		x := []byte("abcddddddeeeededd")
   631		re := MustCompile(".bc(?:d|e)*$")
   632		b.StartTimer()
   633		for i := 0; i < b.N; i++ {
   634			re.Match(x)
   635		}
   636	}
   637	
   638	func BenchmarkOnePassLongPrefix(b *testing.B) {
   639		b.StopTimer()
   640		x := []byte("abcdefghijklmnopqrstuvwxyz")
   641		re := MustCompile("^abcdefghijklmnopqrstuvwxyz.*$")
   642		b.StartTimer()
   643		for i := 0; i < b.N; i++ {
   644			re.Match(x)
   645		}
   646	}
   647	
   648	func BenchmarkOnePassLongNotPrefix(b *testing.B) {
   649		b.StopTimer()
   650		x := []byte("abcdefghijklmnopqrstuvwxyz")
   651		re := MustCompile("^.bcdefghijklmnopqrstuvwxyz.*$")
   652		b.StartTimer()
   653		for i := 0; i < b.N; i++ {
   654			re.Match(x)
   655		}
   656	}
   657	

View as plain text