all_test.go 18 KB

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