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