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