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