1 use regex_automata::{DenseDFA, Regex, RegexBuilder, SparseDFA};
2
3 use collection::{RegexTester, SUITE};
4
5 #[test]
unminimized_standard()6 fn unminimized_standard() {
7 let mut builder = RegexBuilder::new();
8 builder.minimize(false).premultiply(false).byte_classes(false);
9
10 let mut tester = RegexTester::new().skip_expensive();
11 tester.test_all(builder, SUITE.tests());
12 tester.assert();
13 }
14
15 #[test]
unminimized_premultiply()16 fn unminimized_premultiply() {
17 let mut builder = RegexBuilder::new();
18 builder.minimize(false).premultiply(true).byte_classes(false);
19
20 let mut tester = RegexTester::new().skip_expensive();
21 tester.test_all(builder, SUITE.tests());
22 tester.assert();
23 }
24
25 #[test]
unminimized_byte_class()26 fn unminimized_byte_class() {
27 let mut builder = RegexBuilder::new();
28 builder.minimize(false).premultiply(false).byte_classes(true);
29
30 let mut tester = RegexTester::new();
31 tester.test_all(builder, SUITE.tests());
32 tester.assert();
33 }
34
35 #[test]
unminimized_premultiply_byte_class()36 fn unminimized_premultiply_byte_class() {
37 let mut builder = RegexBuilder::new();
38 builder.minimize(false).premultiply(true).byte_classes(true);
39
40 let mut tester = RegexTester::new();
41 tester.test_all(builder, SUITE.tests());
42 tester.assert();
43 }
44
45 #[test]
unminimized_standard_no_nfa_shrink()46 fn unminimized_standard_no_nfa_shrink() {
47 let mut builder = RegexBuilder::new();
48 builder
49 .minimize(false)
50 .premultiply(false)
51 .byte_classes(false)
52 .shrink(false);
53
54 let mut tester = RegexTester::new().skip_expensive();
55 tester.test_all(builder, SUITE.tests());
56 tester.assert();
57 }
58
59 #[test]
minimized_standard()60 fn minimized_standard() {
61 let mut builder = RegexBuilder::new();
62 builder.minimize(true).premultiply(false).byte_classes(false);
63
64 let mut tester = RegexTester::new().skip_expensive();
65 tester.test_all(builder, SUITE.tests());
66 tester.assert();
67 }
68
69 #[test]
minimized_premultiply()70 fn minimized_premultiply() {
71 let mut builder = RegexBuilder::new();
72 builder.minimize(true).premultiply(true).byte_classes(false);
73
74 let mut tester = RegexTester::new().skip_expensive();
75 tester.test_all(builder, SUITE.tests());
76 tester.assert();
77 }
78
79 #[test]
minimized_byte_class()80 fn minimized_byte_class() {
81 let mut builder = RegexBuilder::new();
82 builder.minimize(true).premultiply(false).byte_classes(true);
83
84 let mut tester = RegexTester::new();
85 tester.test_all(builder, SUITE.tests());
86 tester.assert();
87 }
88
89 #[test]
minimized_premultiply_byte_class()90 fn minimized_premultiply_byte_class() {
91 let mut builder = RegexBuilder::new();
92 builder.minimize(true).premultiply(true).byte_classes(true);
93
94 let mut tester = RegexTester::new();
95 tester.test_all(builder, SUITE.tests());
96 tester.assert();
97 }
98
99 #[test]
minimized_standard_no_nfa_shrink()100 fn minimized_standard_no_nfa_shrink() {
101 let mut builder = RegexBuilder::new();
102 builder
103 .minimize(true)
104 .premultiply(false)
105 .byte_classes(false)
106 .shrink(false);
107
108 let mut tester = RegexTester::new().skip_expensive();
109 tester.test_all(builder, SUITE.tests());
110 tester.assert();
111 }
112
113 // A basic sanity test that checks we can convert a regex to a smaller
114 // representation and that the resulting regex still passes our tests.
115 //
116 // If tests grow minimal regexes that cannot be represented in 16 bits, then
117 // we'll either want to skip those or increase the size to test to u32.
118 #[test]
u16()119 fn u16() {
120 let mut builder = RegexBuilder::new();
121 builder.minimize(true).premultiply(false).byte_classes(true);
122
123 let mut tester = RegexTester::new().skip_expensive();
124 for test in SUITE.tests() {
125 let builder = builder.clone();
126 let re: Regex = match tester.build_regex(builder, test) {
127 None => continue,
128 Some(re) => re,
129 };
130 let small_re = Regex::from_dfas(
131 re.forward().to_u16().unwrap(),
132 re.reverse().to_u16().unwrap(),
133 );
134
135 tester.test(test, &small_re);
136 }
137 tester.assert();
138 }
139
140 // Test that sparse DFAs work using the standard configuration.
141 #[test]
sparse_unminimized_standard()142 fn sparse_unminimized_standard() {
143 let mut builder = RegexBuilder::new();
144 builder.minimize(false).premultiply(false).byte_classes(false);
145
146 let mut tester = RegexTester::new().skip_expensive();
147 for test in SUITE.tests() {
148 let builder = builder.clone();
149 let re: Regex = match tester.build_regex(builder, test) {
150 None => continue,
151 Some(re) => re,
152 };
153 let fwd = re.forward().to_sparse().unwrap();
154 let rev = re.reverse().to_sparse().unwrap();
155 let sparse_re = Regex::from_dfas(fwd, rev);
156
157 tester.test(test, &sparse_re);
158 }
159 tester.assert();
160 }
161
162 // Test that sparse DFAs work after converting them to a different state ID
163 // representation.
164 #[test]
sparse_u16()165 fn sparse_u16() {
166 let mut builder = RegexBuilder::new();
167 builder.minimize(true).premultiply(false).byte_classes(false);
168
169 let mut tester = RegexTester::new().skip_expensive();
170 for test in SUITE.tests() {
171 let builder = builder.clone();
172 let re: Regex = match tester.build_regex(builder, test) {
173 None => continue,
174 Some(re) => re,
175 };
176 let fwd = re.forward().to_sparse().unwrap().to_u16().unwrap();
177 let rev = re.reverse().to_sparse().unwrap().to_u16().unwrap();
178 let sparse_re = Regex::from_dfas(fwd, rev);
179
180 tester.test(test, &sparse_re);
181 }
182 tester.assert();
183 }
184
185 // Another basic sanity test that checks we can serialize and then deserialize
186 // a regex, and that the resulting regex can be used for searching correctly.
187 #[test]
serialization_roundtrip()188 fn serialization_roundtrip() {
189 let mut builder = RegexBuilder::new();
190 builder.premultiply(false).byte_classes(true);
191
192 let mut tester = RegexTester::new().skip_expensive();
193 for test in SUITE.tests() {
194 let builder = builder.clone();
195 let re: Regex = match tester.build_regex(builder, test) {
196 None => continue,
197 Some(re) => re,
198 };
199
200 let fwd_bytes = re.forward().to_bytes_native_endian().unwrap();
201 let rev_bytes = re.reverse().to_bytes_native_endian().unwrap();
202 let fwd: DenseDFA<&[usize], usize> =
203 unsafe { DenseDFA::from_bytes(&fwd_bytes) };
204 let rev: DenseDFA<&[usize], usize> =
205 unsafe { DenseDFA::from_bytes(&rev_bytes) };
206 let re = Regex::from_dfas(fwd, rev);
207
208 tester.test(test, &re);
209 }
210 tester.assert();
211 }
212
213 // A basic sanity test that checks we can serialize and then deserialize a
214 // regex using sparse DFAs, and that the resulting regex can be used for
215 // searching correctly.
216 #[test]
sparse_serialization_roundtrip()217 fn sparse_serialization_roundtrip() {
218 let mut builder = RegexBuilder::new();
219 builder.byte_classes(true);
220
221 let mut tester = RegexTester::new().skip_expensive();
222 for test in SUITE.tests() {
223 let builder = builder.clone();
224 let re: Regex = match tester.build_regex(builder, test) {
225 None => continue,
226 Some(re) => re,
227 };
228
229 let fwd_bytes = re
230 .forward()
231 .to_sparse()
232 .unwrap()
233 .to_bytes_native_endian()
234 .unwrap();
235 let rev_bytes = re
236 .reverse()
237 .to_sparse()
238 .unwrap()
239 .to_bytes_native_endian()
240 .unwrap();
241 let fwd: SparseDFA<&[u8], usize> =
242 unsafe { SparseDFA::from_bytes(&fwd_bytes) };
243 let rev: SparseDFA<&[u8], usize> =
244 unsafe { SparseDFA::from_bytes(&rev_bytes) };
245 let re = Regex::from_dfas(fwd, rev);
246
247 tester.test(test, &re);
248 }
249 tester.assert();
250 }
251