Source file
src/regexp/onepass_test.go
1
2
3
4
5 package regexp
6
7 import (
8 "regexp/syntax"
9 "slices"
10 "strings"
11 "testing"
12 )
13
14 var runeMergeTests = []struct {
15 left, right, merged []rune
16 next []uint32
17 leftPC, rightPC uint32
18 }{
19 {
20
21 []rune{69, 69},
22 []rune{},
23 []rune{69, 69},
24 []uint32{1},
25 1, 2,
26 },
27 {
28
29 []rune{69, 69},
30 []rune{69, 69},
31 []rune{},
32 []uint32{mergeFailed},
33 1, 1,
34 },
35 {
36
37 []rune{69, 69},
38 []rune{69, 69},
39 []rune{},
40 []uint32{mergeFailed},
41 1, 2,
42 },
43 {
44
45 []rune{69, 69},
46 []rune{71, 71},
47 []rune{69, 69, 71, 71},
48 []uint32{1, 2},
49 1, 2,
50 },
51 {
52
53 []rune{71, 71},
54 []rune{69, 69},
55 []rune{69, 69, 71, 71},
56 []uint32{2, 1},
57 1, 2,
58 },
59 {
60
61 []rune{60, 60, 71, 71, 101, 101},
62 []rune{69, 69, 88, 88},
63 []rune{60, 60, 69, 69, 71, 71, 88, 88, 101, 101},
64 []uint32{1, 2, 1, 2, 1},
65 1, 2,
66 },
67 {
68
69 []rune{69, 74},
70 []rune{71, 71},
71 []rune{},
72 []uint32{mergeFailed},
73 1, 2,
74 },
75 {
76
77 []rune{69, 74},
78 []rune{68, 75},
79 []rune{},
80 []uint32{mergeFailed},
81 1, 2,
82 },
83 {
84
85 []rune{69, 74},
86 []rune{74, 75},
87 []rune{},
88 []uint32{mergeFailed},
89 1, 2,
90 },
91 {
92
93 []rune{69, 74},
94 []rune{65, 69},
95 []rune{},
96 []uint32{mergeFailed},
97 1, 2,
98 },
99 {
100
101 []rune{69, 74},
102 []rune{71, 74},
103 []rune{},
104 []uint32{mergeFailed},
105 1, 2,
106 },
107 {
108
109 []rune{69, 74},
110 []rune{65, 71},
111 []rune{},
112 []uint32{mergeFailed},
113 1, 2,
114 },
115 {
116
117 []rune{69, 74, 60, 65},
118 []rune{66, 67},
119 []rune{},
120 []uint32{mergeFailed},
121 1, 2,
122 },
123 }
124
125 func TestMergeRuneSet(t *testing.T) {
126 for ix, test := range runeMergeTests {
127 merged, next := mergeRuneSets(&test.left, &test.right, test.leftPC, test.rightPC)
128 if !slices.Equal(merged, test.merged) {
129 t.Errorf("mergeRuneSet :%d (%v, %v) merged\n have\n%v\nwant\n%v", ix, test.left, test.right, merged, test.merged)
130 }
131 if !slices.Equal(next, test.next) {
132 t.Errorf("mergeRuneSet :%d(%v, %v) next\n have\n%v\nwant\n%v", ix, test.left, test.right, next, test.next)
133 }
134 }
135 }
136
137 var onePassTests = []struct {
138 re string
139 isOnePass bool
140 }{
141 {`^(?:a|(?:a*))$`, false},
142 {`^(?:(a)|(?:a*))$`, false},
143 {`^(?:(?:(?:.(?:$))?))$`, true},
144 {`^abcd$`, true},
145 {`^abcd`, true},
146 {`^(?:(?:a{0,})*?)$`, false},
147 {`^(?:(?:a+)*)$`, true},
148 {`^(?:(?:a|(?:aa)))$`, true},
149 {`^(?:[^\s\S])$`, true},
150 {`^(?:(?:a{3,4}){0,})$`, false},
151 {`^(?:(?:(?:a*)+))$`, true},
152 {`^[a-c]+$`, true},
153 {`^[a-c]*$`, true},
154 {`^(?:a*)$`, true},
155 {`^(?:(?:aa)|a)$`, true},
156 {`^[a-c]*`, false},
157 {`^...$`, true},
158 {`^...`, true},
159 {`^(?:a|(?:aa))$`, true},
160 {`^a((b))c$`, true},
161 {`^a.[l-nA-Cg-j]?e$`, true},
162 {`^a((b))$`, true},
163 {`^a(?:(b)|(c))c$`, true},
164 {`^a(?:(b*)|(c))c$`, false},
165 {`^a(?:b|c)$`, true},
166 {`^a(?:b?|c)$`, true},
167 {`^a(?:b?|c?)$`, false},
168 {`^a(?:b?|c+)$`, true},
169 {`^a(?:b+|(bc))d$`, false},
170 {`^a(?:bc)+$`, true},
171 {`^a(?:[bcd])+$`, true},
172 {`^a((?:[bcd])+)$`, true},
173 {`^a(:?b|c)*d$`, true},
174 {`^.bc(d|e)*$`, true},
175 {`^(?:(?:aa)|.)$`, false},
176 {`^(?:(?:a{1,2}){1,2})$`, false},
177 {`^l` + strings.Repeat("o", 2<<8) + `ng$`, true},
178 }
179
180 func TestCompileOnePass(t *testing.T) {
181 var (
182 p *syntax.Prog
183 re *syntax.Regexp
184 err error
185 )
186 for _, test := range onePassTests {
187 if re, err = syntax.Parse(test.re, syntax.Perl); err != nil {
188 t.Errorf("Parse(%q) got err:%s, want success", test.re, err)
189 continue
190 }
191
192 re = re.Simplify()
193 if p, err = syntax.Compile(re); err != nil {
194 t.Errorf("Compile(%q) got err:%s, want success", test.re, err)
195 continue
196 }
197 isOnePass := compileOnePass(p) != nil
198 if isOnePass != test.isOnePass {
199 t.Errorf("CompileOnePass(%q) got isOnePass=%v, expected %v", test.re, isOnePass, test.isOnePass)
200 }
201 }
202 }
203
204
205 var onePassTests1 = []struct {
206 re string
207 match string
208 }{
209 {`^a(/b+(#c+)*)*$`, "a/b#c"},
210 }
211
212 func TestRunOnePass(t *testing.T) {
213 for _, test := range onePassTests1 {
214 re, err := Compile(test.re)
215 if err != nil {
216 t.Errorf("Compile(%q): got err: %s", test.re, err)
217 continue
218 }
219 if re.onepass == nil {
220 t.Errorf("Compile(%q): got nil, want one-pass", test.re)
221 continue
222 }
223 if !re.MatchString(test.match) {
224 t.Errorf("onepass %q did not match %q", test.re, test.match)
225 }
226 }
227 }
228
View as plain text