1// Copyright 2011 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
5package syntax
6
7import "testing"
8
9var compileTests = []struct {
10	Regexp string
11	Prog   string
12}{
13	{"a", `  0	fail
14  1*	rune1 "a" -> 2
15  2	match
16`},
17	{"[A-M][n-z]", `  0	fail
18  1*	rune "AM" -> 2
19  2	rune "nz" -> 3
20  3	match
21`},
22	{"", `  0	fail
23  1*	nop -> 2
24  2	match
25`},
26	{"a?", `  0	fail
27  1	rune1 "a" -> 3
28  2*	alt -> 1, 3
29  3	match
30`},
31	{"a??", `  0	fail
32  1	rune1 "a" -> 3
33  2*	alt -> 3, 1
34  3	match
35`},
36	{"a+", `  0	fail
37  1*	rune1 "a" -> 2
38  2	alt -> 1, 3
39  3	match
40`},
41	{"a+?", `  0	fail
42  1*	rune1 "a" -> 2
43  2	alt -> 3, 1
44  3	match
45`},
46	{"a*", `  0	fail
47  1	rune1 "a" -> 2
48  2*	alt -> 1, 3
49  3	match
50`},
51	{"a*?", `  0	fail
52  1	rune1 "a" -> 2
53  2*	alt -> 3, 1
54  3	match
55`},
56	{"a+b+", `  0	fail
57  1*	rune1 "a" -> 2
58  2	alt -> 1, 3
59  3	rune1 "b" -> 4
60  4	alt -> 3, 5
61  5	match
62`},
63	{"(a+)(b+)", `  0	fail
64  1*	cap 2 -> 2
65  2	rune1 "a" -> 3
66  3	alt -> 2, 4
67  4	cap 3 -> 5
68  5	cap 4 -> 6
69  6	rune1 "b" -> 7
70  7	alt -> 6, 8
71  8	cap 5 -> 9
72  9	match
73`},
74	{"a+|b+", `  0	fail
75  1	rune1 "a" -> 2
76  2	alt -> 1, 6
77  3	rune1 "b" -> 4
78  4	alt -> 3, 6
79  5*	alt -> 1, 3
80  6	match
81`},
82	{"A[Aa]", `  0	fail
83  1*	rune1 "A" -> 2
84  2	rune "A"/i -> 3
85  3	match
86`},
87	{"(?:(?:^).)", `  0	fail
88  1*	empty 4 -> 2
89  2	anynotnl -> 3
90  3	match
91`},
92	{"(?:|a)+", `  0	fail
93  1	nop -> 4
94  2	rune1 "a" -> 4
95  3*	alt -> 1, 2
96  4	alt -> 3, 5
97  5	match
98`},
99	{"(?:|a)*", `  0	fail
100  1	nop -> 4
101  2	rune1 "a" -> 4
102  3	alt -> 1, 2
103  4	alt -> 3, 6
104  5*	alt -> 3, 6
105  6	match
106`},
107}
108
109func TestCompile(t *testing.T) {
110	for _, tt := range compileTests {
111		re, _ := Parse(tt.Regexp, Perl)
112		p, _ := Compile(re)
113		s := p.String()
114		if s != tt.Prog {
115			t.Errorf("compiled %#q:\n--- have\n%s---\n--- want\n%s---", tt.Regexp, s, tt.Prog)
116		}
117	}
118}
119
120func BenchmarkEmptyOpContext(b *testing.B) {
121	for i := 0; i < b.N; i++ {
122		var r1 rune = -1
123		for _, r2 := range "foo, bar, baz\nsome input text.\n" {
124			EmptyOpContext(r1, r2)
125			r1 = r2
126		}
127		EmptyOpContext(r1, -1)
128	}
129}
130
131var sink any
132
133func BenchmarkIsWordChar(b *testing.B) {
134	const chars = "Don't communicate by sharing memory, share memory by communicating."
135	for i := 0; i < b.N; i++ {
136		for _, r := range chars {
137			sink = IsWordChar(r)
138		}
139	}
140	if sink == nil {
141		b.Fatal("Benchmark did not run")
142	}
143	sink = nil
144}
145