1 /*
2 * Copyright © 2019-today Peter M. Stahl pemistahl@gmail.com
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 use grex::RegExpBuilder;
18 use indoc::indoc;
19 use regex::Regex;
20 use rstest::rstest;
21 use std::io::Write;
22 use tempfile::NamedTempFile;
23
24 mod no_conversion {
25 use super::*;
26
27 mod no_repetition {
28 use super::*;
29
30 #[rstest(test_cases, expected_output,
31 case(vec![""], "^$"),
32 case(vec![" "], "^ $"),
33 case(vec![" "], "^ $"),
34 case(vec!["["], "^\\[$"),
35 case(vec!["a", "("], "^[(a]$"),
36 case(vec!["a", "\n"], "^[\\na]$"),
37 case(vec!["a", "["], "^[\\[a]$"),
38 case(vec!["a", "-", "c", "!"], "^[!\\-ac]$"),
39 case(vec!["a", "b"], "^[ab]$"),
40 case(vec!["a", "b", "c"], "^[a-c]$"),
41 case(vec!["a", "c", "d", "e", "f"], "^[ac-f]$"),
42 case(vec!["a", "b", "x", "d", "e"], "^[abdex]$"),
43 case(vec!["a", "b", "x", "de"], "^(?:de|[abx])$"),
44 case(vec!["a", "b", "c", "x", "d", "e"], "^[a-ex]$"),
45 case(vec!["a", "b", "c", "x", "de"], "^(?:de|[a-cx])$"),
46 case(vec!["a", "b", "c", "d", "e", "f", "o", "x", "y", "z"], "^[a-fox-z]$"),
47 case(vec!["a", "b", "d", "e", "f", "o", "x", "y", "z"], "^[abd-fox-z]$"),
48 case(vec!["1", "2"], "^[12]$"),
49 case(vec!["1", "2", "3"], "^[1-3]$"),
50 case(vec!["1", "3", "4", "5", "6"], "^[13-6]$"),
51 case(vec!["1", "2", "8", "4", "5"], "^[12458]$"),
52 case(vec!["1", "2", "8", "45"], "^(?:45|[128])$"),
53 case(vec!["1", "2", "3", "8", "4", "5"], "^[1-58]$"),
54 case(vec!["1", "2", "3", "8", "45"], "^(?:45|[1-38])$"),
55 case(vec!["1", "2", "3", "5", "7", "8", "9"], "^[1-357-9]$"),
56 case(vec!["a", "b", "bc"], "^(?:bc?|a)$"),
57 case(vec!["a", "b", "bcd"], "^(?:b(?:cd)?|a)$"),
58 case(vec!["a", "ab", "abc"], "^a(?:bc?)?$"),
59 case(vec!["ac", "bc"], "^[ab]c$"),
60 case(vec!["ab", "ac"], "^a[bc]$"),
61 case(vec!["bc", "abc"], "^a?bc$"),
62 case(vec!["ac", "abc"], "^ab?c$"),
63 case(vec!["abc", "abxyc"], "^ab(?:xy)?c$"),
64 case(vec!["ab", "abc"], "^abc?$"),
65 case(vec!["abx", "cdx"], "^(?:ab|cd)x$"),
66 case(vec!["abd", "acd"], "^a[bc]d$"),
67 case(vec!["abc", "abcd"], "^abcd?$"),
68 case(vec!["abc", "abcde"], "^abc(?:de)?$"),
69 case(vec!["ade", "abcde"], "^a(?:bc)?de$"),
70 case(vec!["abcxy", "adexy"], "^a(?:bc|de)xy$"),
71 case(vec!["axy", "abcxy", "adexy"], "^a(?:(?:bc)?|de)xy$"), // goal: "^a(bc|de)?xy$"
72 case(vec!["abcxy", "abcw", "efgh"], "^(?:abc(?:xy|w)|efgh)$"),
73 case(vec!["abcxy", "efgh", "abcw"], "^(?:abc(?:xy|w)|efgh)$"),
74 case(vec!["efgh", "abcxy", "abcw"], "^(?:abc(?:xy|w)|efgh)$"),
75 case(vec!["abxy", "cxy", "efgh"], "^(?:(?:ab|c)xy|efgh)$"),
76 case(vec!["abxy", "efgh", "cxy"], "^(?:(?:ab|c)xy|efgh)$"),
77 case(vec!["efgh", "abxy", "cxy"], "^(?:(?:ab|c)xy|efgh)$"),
78 case(vec!["a", "ä", "o", "ö", "u", "ü"], "^[aouäöü]$"),
79 case(vec!["y̆", "a", "z"], "^(?:y̆|[az])$"), // goal: "^[az]|y\\u{306}$"
80 case(vec!["a", "b\n", "c"], "^(?:b\\n|[ac])$"),
81 case(vec!["a", "b\\n", "c"], "^(?:b\\\\n|[ac])$"),
82 case(vec!["[a-z]", "(d,e,f)"], "^(?:\\(d,e,f\\)|\\[a\\-z\\])$"),
83 case(vec!["3.5", "4.5", "4,5"], "^(?:3\\.5|4[,.]5)$"),
84 case(vec!["\u{b}"], "^\\v$"), // U+000B Line Tabulation
85 case(vec!["\\u{b}"], "^\\\\u\\{b\\}$"),
86 case(vec!["I ♥ cake"], "^I ♥ cake$"),
87 case(vec!["I \u{2665} cake"], "^I ♥ cake$"),
88 case(vec!["I \\u{2665} cake"], "^I \\\\u\\{2665\\} cake$"),
89 case(vec!["I \\u2665 cake"], "^I \\\\u2665 cake$"),
90 case(vec!["My ♥ is yours.", "My is yours."], "^My [♥] is yours\\.$"),
91 case(vec!["[\u{c3e}"], "^\\[\u{c3e}$"),
92 case(vec!["\\\u{10376}"], "^\\\\\u{10376}$"),
93 case(vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."], "^I ♥♥♥ 36 and ٣ and y̆y̆ and \\.$")
94 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)95 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
96 let regexp = RegExpBuilder::from(&test_cases).build();
97 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
98 assert_that_regexp_matches_test_cases(expected_output, test_cases);
99 }
100
101 #[rstest(test_cases, expected_output,
102 case(vec!["ABC", "abc", "AbC", "aBc"], "(?i)^abc$"),
103 case(vec!["ABC", "zBC", "abc", "AbC", "aBc"], "(?i)^[az]bc$"),
104 case(vec!["Ä@Ö€Ü", "ä@ö€ü", "Ä@ö€Ü", "ä@Ö€ü"], "(?i)^ä@ö€ü$"),
105 )]
succeeds_with_ignore_case_option(test_cases: Vec<&str>, expected_output: &str)106 fn succeeds_with_ignore_case_option(test_cases: Vec<&str>, expected_output: &str) {
107 let regexp = RegExpBuilder::from(&test_cases)
108 .with_case_insensitive_matching()
109 .build();
110 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
111 assert_that_regexp_matches_test_cases(expected_output, test_cases);
112 }
113
114 #[rstest(test_cases, expected_output,
115 case(vec!["My ♥ and is yours."], "^My \\u{2665} and \\u{1f4a9} is yours\\.$"),
116 case(vec!["My ♥ is yours.", "My is yours."], "^My (?:\\u{2665}|\\u{1f4a9}) is yours\\.$"),
117 case(
118 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
119 "^I \\u{2665}\\u{2665}\\u{2665} 36 and \\u{663} and y\\u{306}y\\u{306} and \\u{1f4a9}\\u{1f4a9}\\.$"
120 )
121 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)122 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
123 let regexp = RegExpBuilder::from(&test_cases)
124 .with_escaping_of_non_ascii_chars(false)
125 .build();
126 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
127 assert_that_regexp_matches_test_cases(expected_output, test_cases);
128 }
129
130 #[rstest(test_cases, expected_output,
131 case(vec!["My ♥ and is yours."], "^My \\u{2665} and \\u{d83d}\\u{dca9} is yours\\.$"),
132 case(vec!["My ♥ is yours.", "My is yours."], "^My (?:\\u{2665}|\\u{d83d}\\u{dca9}) is yours\\.$"),
133 case(
134 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
135 "^I \\u{2665}\\u{2665}\\u{2665} 36 and \\u{663} and y\\u{306}y\\u{306} and \\u{d83d}\\u{dca9}\\u{d83d}\\u{dca9}\\.$"
136 )
137 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)138 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
139 let regexp = RegExpBuilder::from(&test_cases)
140 .with_escaping_of_non_ascii_chars(true)
141 .build();
142 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
143 }
144
145 #[rstest(test_cases, expected_output,
146 case(vec!["a", "b", "bc"], "^(bc?|a)$"),
147 case(vec!["a", "b", "bcd"], "^(b(cd)?|a)$"),
148 case(vec!["a", "ab", "abc"], "^a(bc?)?$"),
149 case(vec!["efgh", "abcxy", "abcw"], "^(abc(xy|w)|efgh)$"),
150 )]
succeeds_with_capturing_groups_option(test_cases: Vec<&str>, expected_output: &str)151 fn succeeds_with_capturing_groups_option(test_cases: Vec<&str>, expected_output: &str) {
152 let regexp = RegExpBuilder::from(&test_cases)
153 .with_capturing_groups()
154 .build();
155 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
156 assert_that_regexp_matches_test_cases(expected_output, test_cases);
157 }
158
159 #[rstest(test_cases, expected_output,
160 case(vec![""], indoc!(
161 r#"
162 (?x)
163 ^
164 $"#
165 )),
166 case(vec![" "], indoc!(
167 r#"
168 (?x)
169 ^
170 \
171 $"#
172 )),
173 case(vec![" "], indoc!(
174 r#"
175 (?x)
176 ^
177 \ \ \
178 $"#
179 )),
180 case(vec!["a", "b", "c"], indoc!(
181 r#"
182 (?x)
183 ^
184 [a-c]
185 $"#
186 )),
187 case(vec!["a", "b", "bc"], indoc!(
188 r#"
189 (?x)
190 ^
191 (?:
192 bc?
193 |
194 a
195 )
196 $"#
197 )),
198 case(vec!["a", "ab", "abc"], indoc!(
199 r#"
200 (?x)
201 ^
202 a
203 (?:
204 bc?
205 )?
206 $"#
207 )),
208 case(vec!["a", "b", "bcd"], indoc!(
209 r#"
210 (?x)
211 ^
212 (?:
213 b
214 (?:
215 cd
216 )?
217 |
218 a
219 )
220 $"#
221 )),
222 case(vec!["a", "b", "x", "de"], indoc!(
223 r#"
224 (?x)
225 ^
226 (?:
227 de
228 |
229 [abx]
230 )
231 $"#
232 )),
233 case(vec!["[a-z]", "(d,e,f)"], indoc!(
234 r#"
235 (?x)
236 ^
237 (?:
238 \(d,e,f\)
239 |
240 \[a\-z\]
241 )
242 $"#
243 )),
244 case(vec!["3.5", "4.5", "4,5"], indoc!(
245 r#"
246 (?x)
247 ^
248 (?:
249 3\.5
250 |
251 4[,.]5
252 )
253 $"#
254 ))
255 )]
succeeds_with_verbose_mode_option(test_cases: Vec<&str>, expected_output: &str)256 fn succeeds_with_verbose_mode_option(test_cases: Vec<&str>, expected_output: &str) {
257 let regexp = RegExpBuilder::from(&test_cases).with_verbose_mode().build();
258 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
259 assert_that_regexp_matches_test_cases(expected_output, test_cases);
260 }
261
262 #[rstest(test_cases, expected_output,
263 case(vec!["ABC", "abc", "AbC", "aBc"], indoc!(
264 r#"
265 (?ix)
266 ^
267 abc
268 $"#
269 )),
270 case(vec!["ABC", "zBC", "abc", "AbC", "aBc"], indoc!(
271 r#"
272 (?ix)
273 ^
274 [az]bc
275 $"#
276 )),
277 case(vec!["Ä@Ö€Ü", "ä@ö€ü", "Ä@ö€Ü", "ä@Ö€ü"], indoc!(
278 r#"
279 (?ix)
280 ^
281 ä@ö€ü
282 $"#
283 ))
284 )]
succeeds_with_ignore_case_and_verbose_mode_option( test_cases: Vec<&str>, expected_output: &str, )285 fn succeeds_with_ignore_case_and_verbose_mode_option(
286 test_cases: Vec<&str>,
287 expected_output: &str,
288 ) {
289 let regexp = RegExpBuilder::from(&test_cases)
290 .with_case_insensitive_matching()
291 .with_verbose_mode()
292 .build();
293 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
294 assert_that_regexp_matches_test_cases(expected_output, test_cases);
295 }
296
297 #[test]
succeeds_with_file_input()298 fn succeeds_with_file_input() {
299 let mut file = NamedTempFile::new().unwrap();
300 writeln!(file, "a\nb\nc\r\nxyz").unwrap();
301
302 let expected_output = "^(?:xyz|[a-c])$";
303 let test_cases = vec!["a", "b", "c", "xyz"];
304
305 let regexp = RegExpBuilder::from_file(file.path()).build();
306 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
307 assert_that_regexp_matches_test_cases(expected_output, test_cases);
308 }
309
310 #[rstest(test_cases, expected_output,
311 case(vec!["bab", "b", "cb", "bba"], "(?:b(?:ba|ab)?|cb)"),
312 case(vec!["a", "aba", "baaa", "aaab"], "(?:baaa|a(?:aab|ba)?)"),
313 case(vec!["a", "abab", "bbb", "aaac"], "(?:a(?:bab|aac)?|bbb)"),
314 case(
315 // https://github.com/pemistahl/grex/issues/31
316 vec!["agbhd", "eibcd", "egbcd", "fbjbf", "agbh", "eibc", "egbc", "ebc", "fbc", "cd", "f", "c", "abcd", "ebcd", "fbcd"],
317 "(?:a(?:gbhd?|bcd)|e(?:ibcd?|gbcd?|bcd?)|f(?:b(?:jbf|cd?))?|cd?)")
318 )]
succeeds_without_anchors(test_cases: Vec<&str>, expected_output: &str)319 fn succeeds_without_anchors(test_cases: Vec<&str>, expected_output: &str) {
320 let regexp = RegExpBuilder::from(&test_cases).without_anchors().build();
321 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
322 assert_that_regexp_matches_test_cases(expected_output, test_cases);
323 }
324 }
325
326 mod repetition {
327 use super::*;
328
329 #[rstest(test_cases, expected_output,
330 case(vec![""], "^$"),
331 case(vec![" "], "^ $"),
332 case(vec![" "], "^ {3}$"),
333 case(vec!["a"], "^a$"),
334 case(vec!["aa"], "^a{2}$"),
335 case(vec!["aaa"], "^a{3}$"),
336 case(vec!["aaa aaa"], "^a{3} a{3}$"),
337 case(vec!["ababab ababab"], "^(?:ab){3} (?:ab){3}$"),
338 case(vec!["ababab ababab"], "^(?:ab){3} {2}(?:ab){3}$"),
339 case(vec!["a ababab ababab"], "^a(?: (?:ab){3}){2}$"),
340 case(vec!["ababab ababab a"], "^a(?:b(?:ab){2} a){2}$"),
341 case(vec!["ababababab abab ababab"], "^ababab(?:(?:ab){2} ){2}(?:ab){3}$"),
342 case(vec!["a", "aa"], "^a{1,2}$"),
343 case(vec!["aaa", "a", "aa"], "^a{1,3}$"),
344 case(vec!["aaaa", "a", "aa"], "^(?:a{1,2}|a{4})$"),
345 case(vec!["a", "aa", "aaa", "aaaa", "aaab"], "^(?:a{3}b|a{1,4})$"),
346 case(vec!["baabaaaaaabb"], "^ba{2}ba{6}b{2}$"),
347 case(vec!["aabbaabbaaa"], "^(?:a{2}b{2}){2}a{3}$"),
348 case(vec!["aabbaa"], "^a{2}b{2}a{2}$"),
349 case(vec!["aabbabb"], "^a(?:ab{2}){2}$"),
350 case(vec!["ababab"], "^(?:ab){3}$"),
351 case(vec!["abababa"], "^a(?:ba){3}$"),
352 case(vec!["aababab"], "^a(?:ab){3}$"),
353 case(vec!["abababaa"], "^(?:ab){3}a{2}$"),
354 case(vec!["aaaaaabbbbb"], "^a{6}b{5}$"),
355 case(vec!["aabaababab"], "^a{2}ba(?:ab){3}$"),
356 case(vec!["aaaaaaabbbbbba"], "^a{7}b{6}a$"),
357 case(vec!["abaaaabaaba"], "^abaaa(?:aba){2}$"),
358 case(vec!["bbaababb"], "^b{2}a{2}bab{2}$"),
359 case(vec!["b", "ba"], "^ba?$"),
360 case(vec!["b", "ba", "baa"], "^b(?:a{1,2})?$"),
361 case(vec!["b", "ba", "baaa", "baa"], "^b(?:a{1,3})?$"),
362 case(vec!["b", "ba", "baaaa", "baa"], "^b(?:a{1,2}|a{4})?$"),
363 case(vec!["axy", "abcxyxy", "adexy"], "^a(?:(?:de)?xy|bc(?:xy){2})$"),
364 case(vec!["xy̆y̆y̆y̆z"], "^x(?:y̆){4}z$"),
365 case(vec!["xy̆y̆z", "xy̆y̆y̆z"], "^x(?:y̆){2,3}z$"),
366 case(vec!["xy̆y̆z", "xy̆y̆y̆y̆z"], "^x(?:(?:y̆){2}|(?:y̆){4})z$"),
367 case(vec!["zyxx", "yxx"], "^z?yx{2}$"),
368 case(vec!["zyxx", "yxx", "yxxx"], "^(?:zyx{2}|yx{2,3})$"),
369 case(vec!["zyxxx", "yxx", "yxxx"], "^(?:zyx{3}|yx{2,3})$"),
370 case(vec!["a", "b\n\n", "c"], "^(?:b\\n{2}|[ac])$"),
371 case(vec!["a", "b\nb\nb", "c"], "^(?:b(?:\\nb){2}|[ac])$"),
372 case(vec!["a", "b\nx\nx", "c"], "^(?:b(?:\\nx){2}|[ac])$"),
373 case(vec!["a", "b\n\t\n\t", "c"], "^(?:b(?:\\n\\t){2}|[ac])$"),
374 case(vec!["a", "b\n", "b\n\n", "b\n\n\n", "c"], "^(?:b\\n{1,3}|[ac])$"),
375 case(vec!["4.5", "3.55"], "^(?:4\\.5|3\\.5{2})$"),
376 case(vec!["4.5", "4.55"], "^4\\.5{1,2}$"),
377 case(vec!["4.5", "4.55", "3.5"], "^(?:3\\.5|4\\.5{1,2})$"),
378 case(vec!["4.5", "44.5", "44.55", "4.55"], "^4{1,2}\\.5{1,2}$"),
379 case(vec!["I ♥♥ cake"], "^I ♥{2} cake$"),
380 case(vec!["I ♥ cake", "I ♥♥ cake"], "^I ♥{1,2} cake$"),
381 case(vec!["I \u{2665}\u{2665} cake"], "^I ♥{2} cake$"),
382 case(vec!["I \\u{2665} cake"], "^I \\\\u\\{26{2}5\\} cake$"),
383 case(vec!["I \\u{2665}\\u{2665} cake"], "^I (?:\\\\u\\{26{2}5\\}){2} cake$"),
384 case(vec!["I \\u2665\\u2665 cake"], "^I (?:\\\\u26{2}5){2} cake$"),
385 case(vec!["My ♥♥♥ is yours.", "My is yours."], "^My (?:{2}|♥{3}) is yours\\.$"),
386 case(vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."], "^I {3}♥{3} 36 and ٣ and (?:y̆){2} and {2}\\.$")
387 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)388 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
389 let regexp = RegExpBuilder::from(&test_cases)
390 .with_conversion_of_repetitions()
391 .build();
392 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
393 assert_that_regexp_matches_test_cases(expected_output, test_cases);
394 }
395
396 #[rstest(test_cases, expected_output,
397 case(vec!["AAAAB", "aaaab", "AaAaB", "aAaAB"], "(?i)^a{4}b$"),
398 case(vec!["ÄÖÜäöü@Ö€", "äöüÄöÜ@ö€"], "(?i)^(?:äöü){2}@ö€$"),
399 )]
succeeds_with_ignore_case_option(test_cases: Vec<&str>, expected_output: &str)400 fn succeeds_with_ignore_case_option(test_cases: Vec<&str>, expected_output: &str) {
401 let regexp = RegExpBuilder::from(&test_cases)
402 .with_conversion_of_repetitions()
403 .with_case_insensitive_matching()
404 .build();
405 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
406 assert_that_regexp_matches_test_cases(expected_output, test_cases);
407 }
408
409 #[rstest(test_cases, expected_output,
410 case(vec!["My ♥♥♥ and is yours."], "^My \\u{2665}{3} and \\u{1f4a9}{2} is yours\\.$"),
411 case(vec!["My ♥♥♥ is yours.", "My is yours."], "^My (?:\\u{1f4a9}{2}|\\u{2665}{3}) is yours\\.$"),
412 case(
413 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
414 "^I {3}\\u{2665}{3} 36 and \\u{663} and (?:y\\u{306}){2} and \\u{1f4a9}{2}\\.$"
415 )
416 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)417 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
418 let regexp = RegExpBuilder::from(&test_cases)
419 .with_conversion_of_repetitions()
420 .with_escaping_of_non_ascii_chars(false)
421 .build();
422 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
423 assert_that_regexp_matches_test_cases(expected_output, test_cases);
424 }
425
426 #[rstest(test_cases, expected_output,
427 case(vec!["My ♥♥♥ and is yours."], "^My \\u{2665}{3} and (?:\\u{d83d}\\u{dca9}){2} is yours\\.$"),
428 case(vec!["My ♥♥♥ is yours.", "My is yours."], "^My (?:(?:\\u{d83d}\\u{dca9}){2}|\\u{2665}{3}) is yours\\.$"),
429 case(
430 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
431 "^I {3}\\u{2665}{3} 36 and \\u{663} and (?:y\\u{306}){2} and (?:\\u{d83d}\\u{dca9}){2}\\.$"
432 )
433 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)434 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
435 let regexp = RegExpBuilder::from(&test_cases)
436 .with_conversion_of_repetitions()
437 .with_escaping_of_non_ascii_chars(true)
438 .build();
439 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
440 }
441
442 #[rstest(test_cases, expected_output,
443 case(vec![" "], indoc!(
444 r#"
445 (?x)
446 ^
447 \ {3}
448 $"#
449 )),
450 case(vec!["aa"], indoc!(
451 r#"
452 (?x)
453 ^
454 a{2}
455 $"#
456 )),
457 case(vec!["aaa", "a", "aa"], indoc!(
458 r#"
459 (?x)
460 ^
461 a{1,3}
462 $"#
463 )),
464 case(vec!["aaaa", "a", "aa"], indoc!(
465 r#"
466 (?x)
467 ^
468 (?:
469 a{1,2}
470 |
471 a{4}
472 )
473 $"#
474 )),
475 case(vec!["ababab"], indoc!(
476 r#"
477 (?x)
478 ^
479 (?:
480 ab
481 ){3}
482 $"#
483 )),
484 case(vec!["abababa"], indoc!(
485 r#"
486 (?x)
487 ^
488 a
489 (?:
490 ba
491 ){3}
492 $"#
493 )),
494 case(vec!["abababaa"], indoc!(
495 r#"
496 (?x)
497 ^
498 (?:
499 ab
500 ){3}
501 a{2}
502 $"#
503 )),
504 case(vec!["aabaababab"], indoc!(
505 r#"
506 (?x)
507 ^
508 a{2}ba
509 (?:
510 ab
511 ){3}
512 $"#
513 )),
514 case(vec!["abaaaabaaba"], indoc!(
515 r#"
516 (?x)
517 ^
518 abaaa
519 (?:
520 aba
521 ){2}
522 $"#
523 )),
524 case(vec!["xy̆y̆z", "xy̆y̆y̆y̆z"], indoc!(
525 r#"
526 (?x)
527 ^
528 x
529 (?:
530 (?:
531 y̆
532 ){2}
533 |
534 (?:
535 y̆
536 ){4}
537 )
538 z
539 $"#
540 )),
541 case(vec!["a", "b\n\t\n\t", "c"], indoc!(
542 r#"
543 (?x)
544 ^
545 (?:
546 b
547 (?:
548 \n\t
549 ){2}
550 |
551 [ac]
552 )
553 $"#
554 )),
555 case(vec!["My ♥♥♥ is yours.", "My is yours."], indoc!(
556 r#"
557 (?x)
558 ^
559 My\
560 (?:
561 {2}
562 |
563 ♥{3}
564 )
565 \ is\ yours\.
566 $"#
567 ))
568 )]
succeeds_with_verbose_mode_option(test_cases: Vec<&str>, expected_output: &str)569 fn succeeds_with_verbose_mode_option(test_cases: Vec<&str>, expected_output: &str) {
570 let regexp = RegExpBuilder::from(&test_cases)
571 .with_conversion_of_repetitions()
572 .with_verbose_mode()
573 .build();
574 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
575 assert_that_regexp_matches_test_cases(expected_output, test_cases);
576 }
577
578 #[rstest(test_cases, expected_output,
579 case(vec![""], "^$"),
580 case(vec![" "], "^ $"),
581 case(vec![" "], "^ $"),
582 case(vec![" "], "^ {4}$"),
583 case(vec![" "], "^ {6}$"),
584 case(vec!["a"], "^a$"),
585 case(vec!["aa"], "^aa$"),
586 case(vec!["aaa"], "^aaa$"),
587 case(vec!["aaaa"], "^a{4}$"),
588 case(vec!["aaaaa"], "^a{5}$"),
589 case(vec!["ababababab abab ababab"], "^(?:ab){5} abab ababab$"),
590 case(vec!["aabbaaaabbbabbbbba"], "^aabba{4}bbbab{5}a$"),
591 case(vec!["baabaaaaaabb"], "^baaba{6}bb$"),
592 case(vec!["ababab"], "^ababab$"),
593 case(vec!["abababab"], "^(?:ab){4}$"),
594 case(vec!["abababa"], "^abababa$"),
595 case(vec!["ababababa"], "^a(?:ba){4}$"),
596 case(vec!["aababab"], "^aababab$"),
597 case(vec!["aabababab"], "^a(?:ab){4}$"),
598 case(vec!["xy̆y̆z", "xy̆y̆y̆y̆z"], "^x(?:y̆y̆|(?:y̆){4})z$"),
599 case(vec!["aaa", "a", "aa"], "^a(?:aa?)?$"),
600 case(vec!["a", "aa", "aaa", "aaaa"], "^(?:aaa|aa?|a{4})$"),
601 case(vec!["a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa"], "^(?:aaa|aa?|a{4,6})$")
602 )]
succeeds_with_increased_minimum_repetitions( test_cases: Vec<&str>, expected_output: &str, )603 fn succeeds_with_increased_minimum_repetitions(
604 test_cases: Vec<&str>,
605 expected_output: &str,
606 ) {
607 let regexp = RegExpBuilder::from(&test_cases)
608 .with_conversion_of_repetitions()
609 .with_minimum_repetitions(3)
610 .build();
611 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
612 assert_that_regexp_matches_test_cases(expected_output, test_cases);
613 }
614
615 #[rstest(test_cases, expected_output,
616 case(vec!["aaa"], "^aaa$"),
617 case(vec!["ababab"], "^ababab$"),
618 case(vec!["abcabcabc"], "^(?:abc){3}$"),
619 case(vec!["abcabcabc", "dede"], "^(?:dede|(?:abc){3})$"),
620 case(vec!["abcabcabc", "defgdefg"], "^(?:(?:defg){2}|(?:abc){3})$"),
621 case(vec!["ababababab abab ababab"], "^ababab(?:abab ){2}ababab$")
622 )]
succeeds_with_increased_minimum_substring_length( test_cases: Vec<&str>, expected_output: &str, )623 fn succeeds_with_increased_minimum_substring_length(
624 test_cases: Vec<&str>,
625 expected_output: &str,
626 ) {
627 let regexp = RegExpBuilder::from(&test_cases)
628 .with_conversion_of_repetitions()
629 .with_minimum_substring_length(3)
630 .build();
631 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
632 assert_that_regexp_matches_test_cases(expected_output, test_cases);
633 }
634
635 #[rstest(test_cases, expected_output,
636 case(vec!["abababab"], "^abababab$"),
637 case(vec!["abcabcabc"], "^abcabcabc$"),
638 case(vec!["abcabcabcabc"], "^(?:abc){4}$"),
639 case(vec!["aaaaaaaaaaaa"], "^aaaaaaaaaaaa$"),
640 case(vec!["abababab", "abcabcabcabc"], "^(?:abababab|(?:abc){4})$"),
641 case(vec!["ababababab abab ababab"], "^ababababab abab ababab$")
642 )]
succeeds_with_increased_minimum_repetitions_and_substring_length( test_cases: Vec<&str>, expected_output: &str, )643 fn succeeds_with_increased_minimum_repetitions_and_substring_length(
644 test_cases: Vec<&str>,
645 expected_output: &str,
646 ) {
647 let regexp = RegExpBuilder::from(&test_cases)
648 .with_conversion_of_repetitions()
649 .with_minimum_repetitions(3)
650 .with_minimum_substring_length(3)
651 .build();
652 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
653 assert_that_regexp_matches_test_cases(expected_output, test_cases);
654 }
655 }
656 }
657
658 mod digit_conversion {
659 use super::*;
660
661 mod no_repetition {
662 use super::*;
663
664 #[rstest(test_cases, expected_output,
665 case(vec![""], "^$"),
666 case(vec!["a"], "^a$"),
667 case(vec!["1"], "^\\d$"),
668 case(vec!["-1"], "^\\-\\d$"),
669 case(vec!["12"], "^\\d\\d$"),
670 case(vec!["1", "2"], "^\\d$"),
671 case(vec!["1", "23"], "^\\d(?:\\d)?$"),
672 case(vec!["1", "234"], "^\\d(?:\\d\\d)?$"),
673 case(vec!["8", "234"], "^\\d(?:\\d\\d)?$"),
674 case(vec!["890", "34"], "^\\d\\d(?:\\d)?$"),
675 case(vec!["abc123"], "^abc\\d\\d\\d$"),
676 case(vec!["a1b2c3"], "^a\\db\\dc\\d$"),
677 case(vec!["abc", "123"], "^(?:\\d\\d\\d|abc)$"),
678 case(vec!["١", "٣", "٥"], "^\\d$"), // Arabic digits: ١ = 1, ٣ = 3, ٥ = 5
679 case(vec!["١٣٥"], "^\\d\\d\\d$"),
680 case(vec!["a٣3", "b5٥"], "^[ab]\\d\\d$"),
681 case(vec!["I ♥ 123"], "^I ♥ \\d\\d\\d$"),
682 case(vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."], "^I ♥♥♥ \\d\\d and \\d and y̆y̆ and \\.$")
683 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)684 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
685 let regexp = RegExpBuilder::from(&test_cases)
686 .with_conversion_of_digits()
687 .build();
688 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
689 assert_that_regexp_matches_test_cases(expected_output, test_cases);
690 }
691
692 #[rstest(test_cases, expected_output,
693 case(
694 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
695 "^I \\u{2665}\\u{2665}\\u{2665} \\d\\d and \\d and y\\u{306}y\\u{306} and \\u{1f4a9}\\u{1f4a9}\\.$"
696 )
697 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)698 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
699 let regexp = RegExpBuilder::from(&test_cases)
700 .with_conversion_of_digits()
701 .with_escaping_of_non_ascii_chars(false)
702 .build();
703 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
704 assert_that_regexp_matches_test_cases(expected_output, test_cases);
705 }
706
707 #[rstest(test_cases, expected_output,
708 case(
709 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
710 "^I \\u{2665}\\u{2665}\\u{2665} \\d\\d and \\d and y\\u{306}y\\u{306} and \\u{d83d}\\u{dca9}\\u{d83d}\\u{dca9}\\.$"
711 )
712 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)713 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
714 let regexp = RegExpBuilder::from(&test_cases)
715 .with_conversion_of_digits()
716 .with_escaping_of_non_ascii_chars(true)
717 .build();
718 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
719 }
720 }
721
722 mod repetition {
723 use super::*;
724
725 #[rstest(test_cases, expected_output,
726 case(
727 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
728 "^I {3}♥{3} \\d(?:\\d and ){2}(?:y̆){2} and {2}\\.$"
729 )
730 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)731 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
732 let regexp = RegExpBuilder::from(&test_cases)
733 .with_conversion_of_repetitions()
734 .with_conversion_of_digits()
735 .build();
736 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
737 assert_that_regexp_matches_test_cases(expected_output, test_cases);
738 }
739
740 #[rstest(test_cases, expected_output,
741 case(
742 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
743 "^I {3}\\u{2665}{3} \\d(?:\\d and ){2}(?:y\\u{306}){2} and \\u{1f4a9}{2}\\.$"
744 )
745 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)746 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
747 let regexp = RegExpBuilder::from(&test_cases)
748 .with_conversion_of_repetitions()
749 .with_conversion_of_digits()
750 .with_escaping_of_non_ascii_chars(false)
751 .build();
752 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
753 assert_that_regexp_matches_test_cases(expected_output, test_cases);
754 }
755
756 #[rstest(test_cases, expected_output,
757 case(
758 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
759 "^I {3}\\u{2665}{3} \\d(?:\\d and ){2}(?:y\\u{306}){2} and (?:\\u{d83d}\\u{dca9}){2}\\.$"
760 )
761 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)762 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
763 let regexp = RegExpBuilder::from(&test_cases)
764 .with_conversion_of_repetitions()
765 .with_conversion_of_digits()
766 .with_escaping_of_non_ascii_chars(true)
767 .build();
768 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
769 }
770
771 #[rstest(test_cases, expected_output,
772 case(vec!["1"], "^\\d$"),
773 case(vec!["12"], "^\\d\\d$"),
774 case(vec!["123"], "^\\d{3}$"),
775 case(vec!["1", "12", "123"], "^(?:\\d\\d|\\d|\\d{3})$"),
776 case(vec!["12", "123", "1234"], "^(?:\\d\\d|\\d{3,4})$"),
777 case(vec!["123", "1234", "12345"], "^\\d{3,5}$"),
778 case(vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."], "^I {3}♥{3} \\d\\d and \\d and y̆y̆ and \\.$")
779 )]
succeeds_with_increased_minimum_repetitions( test_cases: Vec<&str>, expected_output: &str, )780 fn succeeds_with_increased_minimum_repetitions(
781 test_cases: Vec<&str>,
782 expected_output: &str,
783 ) {
784 let regexp = RegExpBuilder::from(&test_cases)
785 .with_conversion_of_repetitions()
786 .with_conversion_of_digits()
787 .with_minimum_repetitions(2)
788 .build();
789 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
790 assert_that_regexp_matches_test_cases(expected_output, test_cases);
791 }
792 }
793 }
794
795 mod space_conversion {
796 use super::*;
797
798 mod no_repetition {
799 use super::*;
800
801 #[rstest(test_cases, expected_output,
802 case(vec![""], "^$"),
803 case(vec![" "], "^\\s$"),
804 case(vec![" "], "^\\s\\s\\s$"),
805 case(vec!["\n"], "^\\s$"),
806 case(vec!["\u{c}"], "^\\s$"), // form feed \f
807 case(vec!["\u{b}"], "^\\s$"), // vertical tab \v
808 case(vec!["\n", "\r"], "^\\s$"),
809 case(vec!["\n\t", "\r"], "^\\s(?:\\s)?$"),
810 case(vec!["a"], "^a$"),
811 case(vec!["1"], "^1$"),
812 case(vec!["I ♥ 123"], "^I\\s♥\\s123$"),
813 case(vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."], "^I\\s\\s\\s♥♥♥\\s36\\sand\\s٣\\sand\\sy̆y̆\\sand\\s\\.$")
814 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)815 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
816 let regexp = RegExpBuilder::from(&test_cases)
817 .with_conversion_of_whitespace()
818 .build();
819 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
820 assert_that_regexp_matches_test_cases(expected_output, test_cases);
821 }
822
823 #[rstest(test_cases, expected_output,
824 case(
825 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
826 "^I\\s\\s\\s\\u{2665}\\u{2665}\\u{2665}\\s36\\sand\\s\\u{663}\\sand\\sy\\u{306}y\\u{306}\\sand\\s\\u{1f4a9}\\u{1f4a9}\\.$"
827 )
828 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)829 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
830 let regexp = RegExpBuilder::from(&test_cases)
831 .with_conversion_of_whitespace()
832 .with_escaping_of_non_ascii_chars(false)
833 .build();
834 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
835 assert_that_regexp_matches_test_cases(expected_output, test_cases);
836 }
837
838 #[rstest(test_cases, expected_output,
839 case(
840 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
841 "^I\\s\\s\\s\\u{2665}\\u{2665}\\u{2665}\\s36\\sand\\s\\u{663}\\sand\\sy\\u{306}y\\u{306}\\sand\\s\\u{d83d}\\u{dca9}\\u{d83d}\\u{dca9}\\.$"
842 )
843 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)844 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
845 let regexp = RegExpBuilder::from(&test_cases)
846 .with_conversion_of_whitespace()
847 .with_escaping_of_non_ascii_chars(true)
848 .build();
849 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
850 }
851 }
852
853 mod repetition {
854 use super::*;
855
856 #[rstest(test_cases, expected_output,
857 case(
858 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
859 "^I\\s{3}♥{3}\\s36\\sand\\s٣\\sand\\s(?:y̆){2}\\sand\\s{2}\\.$"
860 )
861 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)862 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
863 let regexp = RegExpBuilder::from(&test_cases)
864 .with_conversion_of_repetitions()
865 .with_conversion_of_whitespace()
866 .build();
867 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
868 assert_that_regexp_matches_test_cases(expected_output, test_cases);
869 }
870
871 #[rstest(test_cases, expected_output,
872 case(
873 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
874 "^I\\s{3}\\u{2665}{3}\\s36\\sand\\s\\u{663}\\sand\\s(?:y\\u{306}){2}\\sand\\s\\u{1f4a9}{2}\\.$"
875 )
876 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)877 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
878 let regexp = RegExpBuilder::from(&test_cases)
879 .with_conversion_of_repetitions()
880 .with_conversion_of_whitespace()
881 .with_escaping_of_non_ascii_chars(false)
882 .build();
883 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
884 assert_that_regexp_matches_test_cases(expected_output, test_cases);
885 }
886
887 #[rstest(test_cases, expected_output,
888 case(
889 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
890 "^I\\s{3}\\u{2665}{3}\\s36\\sand\\s\\u{663}\\sand\\s(?:y\\u{306}){2}\\sand\\s(?:\\u{d83d}\\u{dca9}){2}\\.$"
891 )
892 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)893 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
894 let regexp = RegExpBuilder::from(&test_cases)
895 .with_conversion_of_repetitions()
896 .with_conversion_of_whitespace()
897 .with_escaping_of_non_ascii_chars(true)
898 .build();
899 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
900 }
901
902 #[rstest(test_cases, expected_output,
903 case(vec![" "], "^\\s$"),
904 case(vec![" "], "^\\s\\s$"),
905 case(vec![" "], "^\\s{3}$"),
906 case(vec![" ", " ", " "], "^(?:\\s\\s|\\s|\\s{3})$"),
907 case(vec![" ", " ", " "], "^(?:\\s\\s|\\s{3,4})$"),
908 case(vec![" ", " ", " "], "^\\s{3,5}$"),
909 case(
910 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
911 "^I\\s{3}♥{3}\\s36\\sand\\s٣\\sand\\sy\u{306}y\u{306}\\sand\\s\\.$"
912 )
913 )]
succeeds_with_increased_minimum_repetitions( test_cases: Vec<&str>, expected_output: &str, )914 fn succeeds_with_increased_minimum_repetitions(
915 test_cases: Vec<&str>,
916 expected_output: &str,
917 ) {
918 let regexp = RegExpBuilder::from(&test_cases)
919 .with_conversion_of_repetitions()
920 .with_conversion_of_whitespace()
921 .with_minimum_repetitions(2)
922 .build();
923 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
924 assert_that_regexp_matches_test_cases(expected_output, test_cases);
925 }
926 }
927 }
928
929 mod word_conversion {
930 use super::*;
931
932 mod no_repetition {
933 use super::*;
934
935 #[rstest(test_cases, expected_output,
936 case(vec![""], "^$"),
937 case(vec![" "], "^ $"),
938 case(vec!["a"], "^\\w$"),
939 case(vec!["1"], "^\\w$"),
940 case(vec!["-1"], "^\\-\\w$"),
941 case(vec!["1", "2"], "^\\w$"),
942 case(vec!["ä", "ß"], "^\\w$"),
943 case(vec!["abc", "1234"], "^\\w\\w\\w(?:\\w)?$"),
944 case(vec!["١", "٣", "٥"], "^\\w$"), // Arabic digits: ١ = 1, ٣ = 3, ٥ = 5
945 case(vec!["١٣٥"], "^\\w\\w\\w$"),
946 case(vec!["a٣3", "b5٥"], "^\\w\\w\\w$"),
947 case(vec!["I ♥ 123"], "^\\w ♥ \\w\\w\\w$"),
948 case(
949 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
950 "^\\w ♥♥♥ \\w\\w \\w\\w\\w \\w \\w\\w\\w \\w\\w\\w\\w \\w\\w\\w \\.$"
951 )
952 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)953 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
954 let regexp = RegExpBuilder::from(&test_cases)
955 .with_conversion_of_words()
956 .build();
957 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
958 assert_that_regexp_matches_test_cases(expected_output, test_cases);
959 }
960
961 #[rstest(test_cases, expected_output,
962 case(
963 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
964 "^\\w \\u{2665}\\u{2665}\\u{2665} \\w\\w \\w\\w\\w \\w \\w\\w\\w \\w\\w\\w\\w \\w\\w\\w \\u{1f4a9}\\u{1f4a9}\\.$"
965 )
966 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)967 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
968 let regexp = RegExpBuilder::from(&test_cases)
969 .with_conversion_of_words()
970 .with_escaping_of_non_ascii_chars(false)
971 .build();
972 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
973 assert_that_regexp_matches_test_cases(expected_output, test_cases);
974 }
975
976 #[rstest(test_cases, expected_output,
977 case(
978 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
979 "^\\w \\u{2665}\\u{2665}\\u{2665} \\w\\w \\w\\w\\w \\w \\w\\w\\w \\w\\w\\w\\w \\w\\w\\w \\u{d83d}\\u{dca9}\\u{d83d}\\u{dca9}\\.$"
980 )
981 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)982 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
983 let regexp = RegExpBuilder::from(&test_cases)
984 .with_conversion_of_words()
985 .with_escaping_of_non_ascii_chars(true)
986 .build();
987 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
988 }
989 }
990
991 mod repetition {
992 use super::*;
993
994 #[rstest(test_cases, expected_output,
995 case(
996 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
997 "^\\w {3}♥{3} \\w{2}(?: \\w{3} \\w){2}(?:\\w{3} ){2}{2}\\.$"
998 )
999 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1000 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1001 let regexp = RegExpBuilder::from(&test_cases)
1002 .with_conversion_of_repetitions()
1003 .with_conversion_of_words()
1004 .build();
1005 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1006 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1007 }
1008
1009 #[rstest(test_cases, expected_output,
1010 case(
1011 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1012 "^\\w {3}\\u{2665}{3} \\w{2}(?: \\w{3} \\w){2}(?:\\w{3} ){2}\\u{1f4a9}{2}\\.$"
1013 )
1014 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1015 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1016 let regexp = RegExpBuilder::from(&test_cases)
1017 .with_conversion_of_repetitions()
1018 .with_conversion_of_words()
1019 .with_escaping_of_non_ascii_chars(false)
1020 .build();
1021 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1022 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1023 }
1024
1025 #[rstest(test_cases, expected_output,
1026 case(
1027 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1028 "^\\w {3}\\u{2665}{3} \\w{2}(?: \\w{3} \\w){2}(?:\\w{3} ){2}(?:\\u{d83d}\\u{dca9}){2}\\.$"
1029 )
1030 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)1031 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
1032 let regexp = RegExpBuilder::from(&test_cases)
1033 .with_conversion_of_repetitions()
1034 .with_conversion_of_words()
1035 .with_escaping_of_non_ascii_chars(true)
1036 .build();
1037 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1038 }
1039
1040 #[rstest(test_cases, expected_output,
1041 case(vec!["a"], "^\\w$"),
1042 case(vec!["ab"], "^\\w\\w$"),
1043 case(vec!["abc"], "^\\w{3}$"),
1044 case(vec!["a", "ab", "abc"], "^(?:\\w\\w|\\w|\\w{3})$"),
1045 case(vec!["ab", "abc", "abcd"], "^(?:\\w\\w|\\w{3,4})$"),
1046 case(vec!["abc", "abcd", "abcde"], "^\\w{3,5}$"),
1047 case(
1048 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1049 "^\\w {3}♥{3} \\w\\w \\w{3} \\w \\w{3} \\w{4} \\w{3} \\.$"
1050 )
1051 )]
succeeds_with_increased_minimum_repetitions( test_cases: Vec<&str>, expected_output: &str, )1052 fn succeeds_with_increased_minimum_repetitions(
1053 test_cases: Vec<&str>,
1054 expected_output: &str,
1055 ) {
1056 let regexp = RegExpBuilder::from(&test_cases)
1057 .with_conversion_of_repetitions()
1058 .with_conversion_of_words()
1059 .with_minimum_repetitions(2)
1060 .build();
1061 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1062 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1063 }
1064 }
1065 }
1066
1067 mod digit_space_conversion {
1068 use super::*;
1069
1070 mod no_repetition {
1071 use super::*;
1072
1073 #[rstest(test_cases, expected_output,
1074 case(
1075 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1076 "^I\\s\\s\\s♥♥♥\\s\\d\\d\\sand\\s\\d\\sand\\sy̆y̆\\sand\\s\\.$"
1077 )
1078 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1079 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1080 let regexp = RegExpBuilder::from(&test_cases)
1081 .with_conversion_of_digits()
1082 .with_conversion_of_whitespace()
1083 .build();
1084 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1085 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1086 }
1087
1088 #[rstest(test_cases, expected_output,
1089 case(
1090 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1091 "^I\\s\\s\\s\\u{2665}\\u{2665}\\u{2665}\\s\\d\\d\\sand\\s\\d\\sand\\sy\\u{306}y\\u{306}\\sand\\s\\u{1f4a9}\\u{1f4a9}\\.$"
1092 )
1093 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1094 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1095 let regexp = RegExpBuilder::from(&test_cases)
1096 .with_conversion_of_digits()
1097 .with_conversion_of_whitespace()
1098 .with_escaping_of_non_ascii_chars(false)
1099 .build();
1100 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1101 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1102 }
1103
1104 #[rstest(test_cases, expected_output,
1105 case(
1106 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1107 "^I\\s\\s\\s\\u{2665}\\u{2665}\\u{2665}\\s\\d\\d\\sand\\s\\d\\sand\\sy\\u{306}y\\u{306}\\sand\\s\\u{d83d}\\u{dca9}\\u{d83d}\\u{dca9}\\.$"
1108 )
1109 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)1110 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
1111 let regexp = RegExpBuilder::from(&test_cases)
1112 .with_conversion_of_digits()
1113 .with_conversion_of_whitespace()
1114 .with_escaping_of_non_ascii_chars(true)
1115 .build();
1116 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1117 }
1118 }
1119
1120 mod repetition {
1121 use super::*;
1122
1123 #[rstest(test_cases, expected_output,
1124 case(
1125 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1126 "^I\\s{3}♥{3}\\s\\d(?:\\d\\sand\\s){2}(?:y̆){2}\\sand\\s{2}\\.$"
1127 )
1128 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1129 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1130 let regexp = RegExpBuilder::from(&test_cases)
1131 .with_conversion_of_repetitions()
1132 .with_conversion_of_digits()
1133 .with_conversion_of_whitespace()
1134 .build();
1135 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1136 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1137 }
1138
1139 #[rstest(test_cases, expected_output,
1140 case(
1141 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1142 "^I\\s{3}\\u{2665}{3}\\s\\d(?:\\d\\sand\\s){2}(?:y\\u{306}){2}\\sand\\s\\u{1f4a9}{2}\\.$"
1143 )
1144 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1145 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1146 let regexp = RegExpBuilder::from(&test_cases)
1147 .with_conversion_of_repetitions()
1148 .with_conversion_of_digits()
1149 .with_conversion_of_whitespace()
1150 .with_escaping_of_non_ascii_chars(false)
1151 .build();
1152 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1153 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1154 }
1155
1156 #[rstest(test_cases, expected_output,
1157 case(
1158 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1159 "^I\\s{3}\\u{2665}{3}\\s\\d(?:\\d\\sand\\s){2}(?:y\\u{306}){2}\\sand\\s(?:\\u{d83d}\\u{dca9}){2}\\.$"
1160 )
1161 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)1162 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
1163 let regexp = RegExpBuilder::from(&test_cases)
1164 .with_conversion_of_repetitions()
1165 .with_conversion_of_digits()
1166 .with_conversion_of_whitespace()
1167 .with_escaping_of_non_ascii_chars(true)
1168 .build();
1169 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1170 }
1171
1172 #[rstest(test_cases, expected_output,
1173 case(vec!["1\n"], "^\\d\\s$"),
1174 case(vec!["1\n1\n"], "^\\d\\s\\d\\s$"),
1175 case(vec!["1\n1\n1\n"], "^(?:\\d\\s){3}$"),
1176 case(vec!["1\n", "1\n1\n", "1\n1\n1\n"], "^(?:\\d\\s\\d\\s|\\d\\s|(?:\\d\\s){3})$"),
1177 case(vec!["1\n1\n", "1\n1\n1\n", "1\n1\n1\n1\n"], "^(?:\\d\\s\\d\\s|(?:\\d\\s){3,4})$"),
1178 case(vec!["1\n1\n1\n", "1\n1\n1\n1\n", "1\n1\n1\n1\n1\n"], "^(?:\\d\\s){3,5}$"),
1179 case(
1180 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1181 "^I\\s{3}♥{3}\\s\\d\\d\\sand\\s\\d\\sand\\sy̆y̆\\sand\\s\\.$"
1182 )
1183 )]
succeeds_with_increased_minimum_repetitions( test_cases: Vec<&str>, expected_output: &str, )1184 fn succeeds_with_increased_minimum_repetitions(
1185 test_cases: Vec<&str>,
1186 expected_output: &str,
1187 ) {
1188 let regexp = RegExpBuilder::from(&test_cases)
1189 .with_conversion_of_repetitions()
1190 .with_conversion_of_digits()
1191 .with_conversion_of_whitespace()
1192 .with_minimum_repetitions(2)
1193 .build();
1194 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1195 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1196 }
1197
1198 #[rstest(test_cases, expected_output,
1199 case(vec!["1\n1\n"], "^1\\n1\\n$"),
1200 case(vec!["1\n\n1\n\n"], "^(?:1\\n\\n){2}$")
1201 )]
succeeds_with_increased_minimum_substring_length( test_cases: Vec<&str>, expected_output: &str, )1202 fn succeeds_with_increased_minimum_substring_length(
1203 test_cases: Vec<&str>,
1204 expected_output: &str,
1205 ) {
1206 let regexp = RegExpBuilder::from(&test_cases)
1207 .with_conversion_of_repetitions()
1208 .with_minimum_substring_length(3)
1209 .build();
1210 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1211 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1212 }
1213
1214 #[rstest(test_cases, expected_output,
1215 case(vec!["1\n1\n"], "^1\\n1\\n$"),
1216 case(vec!["1\n1\n1\n"], "^1\\n1\\n1\\n$"),
1217 case(vec!["1\n\n1\n\n"], "^1\\n\\n1\\n\\n$"),
1218 case(vec!["1\n\n1\n\n1\n\n"], "^(?:1\\n\\n){3}$")
1219 )]
succeeds_with_increased_minimum_repetitions_and_substring_length( test_cases: Vec<&str>, expected_output: &str, )1220 fn succeeds_with_increased_minimum_repetitions_and_substring_length(
1221 test_cases: Vec<&str>,
1222 expected_output: &str,
1223 ) {
1224 let regexp = RegExpBuilder::from(&test_cases)
1225 .with_conversion_of_repetitions()
1226 .with_minimum_repetitions(2)
1227 .with_minimum_substring_length(3)
1228 .build();
1229 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1230 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1231 }
1232 }
1233 }
1234
1235 mod digit_word_conversion {
1236 use super::*;
1237
1238 mod no_repetition {
1239 use super::*;
1240
1241 #[rstest(test_cases, expected_output,
1242 case(
1243 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1244 "^\\w ♥♥♥ \\d\\d \\w\\w\\w \\d \\w\\w\\w \\w\\w\\w\\w \\w\\w\\w \\.$"
1245 )
1246 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1247 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1248 let regexp = RegExpBuilder::from(&test_cases)
1249 .with_conversion_of_digits()
1250 .with_conversion_of_words()
1251 .build();
1252 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1253 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1254 }
1255
1256 #[rstest(test_cases, expected_output,
1257 case(
1258 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1259 "^\\w \\u{2665}\\u{2665}\\u{2665} \\d\\d \\w\\w\\w \\d \\w\\w\\w \\w\\w\\w\\w \\w\\w\\w \\u{1f4a9}\\u{1f4a9}\\.$"
1260 )
1261 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1262 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1263 let regexp = RegExpBuilder::from(&test_cases)
1264 .with_conversion_of_digits()
1265 .with_conversion_of_words()
1266 .with_escaping_of_non_ascii_chars(false)
1267 .build();
1268 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1269 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1270 }
1271
1272 #[rstest(test_cases, expected_output,
1273 case(
1274 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1275 "^\\w \\u{2665}\\u{2665}\\u{2665} \\d\\d \\w\\w\\w \\d \\w\\w\\w \\w\\w\\w\\w \\w\\w\\w \\u{d83d}\\u{dca9}\\u{d83d}\\u{dca9}\\.$"
1276 )
1277 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)1278 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
1279 let regexp = RegExpBuilder::from(&test_cases)
1280 .with_conversion_of_digits()
1281 .with_conversion_of_words()
1282 .with_escaping_of_non_ascii_chars(true)
1283 .build();
1284 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1285 }
1286 }
1287
1288 mod repetition {
1289 use super::*;
1290
1291 #[rstest(test_cases, expected_output,
1292 case(
1293 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1294 "^\\w {3}♥{3} \\d(?:\\d \\w{3} ){2}\\w(?:\\w{3} ){2}{2}\\.$"
1295 )
1296 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1297 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1298 let regexp = RegExpBuilder::from(&test_cases)
1299 .with_conversion_of_repetitions()
1300 .with_conversion_of_digits()
1301 .with_conversion_of_words()
1302 .build();
1303 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1304 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1305 }
1306
1307 #[rstest(test_cases, expected_output,
1308 case(
1309 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1310 "^\\w {3}\\u{2665}{3} \\d(?:\\d \\w{3} ){2}\\w(?:\\w{3} ){2}\\u{1f4a9}{2}\\.$"
1311 )
1312 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1313 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1314 let regexp = RegExpBuilder::from(&test_cases)
1315 .with_conversion_of_repetitions()
1316 .with_conversion_of_digits()
1317 .with_conversion_of_words()
1318 .with_escaping_of_non_ascii_chars(false)
1319 .build();
1320 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1321 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1322 }
1323
1324 #[rstest(test_cases, expected_output,
1325 case(
1326 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1327 "^\\w {3}\\u{2665}{3} \\d(?:\\d \\w{3} ){2}\\w(?:\\w{3} ){2}(?:\\u{d83d}\\u{dca9}){2}\\.$"
1328 )
1329 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)1330 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
1331 let regexp = RegExpBuilder::from(&test_cases)
1332 .with_conversion_of_repetitions()
1333 .with_conversion_of_digits()
1334 .with_conversion_of_words()
1335 .with_escaping_of_non_ascii_chars(true)
1336 .build();
1337 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1338 }
1339 }
1340 }
1341
1342 mod space_word_conversion {
1343 use super::*;
1344
1345 mod no_repetition {
1346 use super::*;
1347
1348 #[rstest(test_cases, expected_output,
1349 case(
1350 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1351 "^\\w\\s\\s\\s♥♥♥\\s\\w\\w\\s\\w\\w\\w\\s\\w\\s\\w\\w\\w\\s\\w\\w\\w\\w\\s\\w\\w\\w\\s\\.$"
1352 )
1353 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1354 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1355 let regexp = RegExpBuilder::from(&test_cases)
1356 .with_conversion_of_whitespace()
1357 .with_conversion_of_words()
1358 .build();
1359 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1360 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1361 }
1362
1363 #[rstest(test_cases, expected_output,
1364 case(
1365 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1366 "^\\w\\s\\s\\s\\u{2665}\\u{2665}\\u{2665}\\s\\w\\w\\s\\w\\w\\w\\s\\w\\s\\w\\w\\w\\s\\w\\w\\w\\w\\s\\w\\w\\w\\s\\u{1f4a9}\\u{1f4a9}\\.$"
1367 )
1368 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1369 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1370 let regexp = RegExpBuilder::from(&test_cases)
1371 .with_conversion_of_whitespace()
1372 .with_conversion_of_words()
1373 .with_escaping_of_non_ascii_chars(false)
1374 .build();
1375 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1376 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1377 }
1378
1379 #[rstest(test_cases, expected_output,
1380 case(
1381 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1382 "^\\w\\s\\s\\s\\u{2665}\\u{2665}\\u{2665}\\s\\w\\w\\s\\w\\w\\w\\s\\w\\s\\w\\w\\w\\s\\w\\w\\w\\w\\s\\w\\w\\w\\s\\u{d83d}\\u{dca9}\\u{d83d}\\u{dca9}\\.$"
1383 )
1384 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)1385 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
1386 let regexp = RegExpBuilder::from(&test_cases)
1387 .with_conversion_of_whitespace()
1388 .with_conversion_of_words()
1389 .with_escaping_of_non_ascii_chars(true)
1390 .build();
1391 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1392 }
1393 }
1394
1395 mod repetition {
1396 use super::*;
1397
1398 #[rstest(test_cases, expected_output,
1399 case(
1400 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1401 "^\\w\\s{3}♥{3}\\s\\w{2}(?:\\s\\w{3}\\s\\w){2}(?:\\w{3}\\s){2}{2}\\.$"
1402 )
1403 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1404 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1405 let regexp = RegExpBuilder::from(&test_cases)
1406 .with_conversion_of_repetitions()
1407 .with_conversion_of_whitespace()
1408 .with_conversion_of_words()
1409 .build();
1410 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1411 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1412 }
1413
1414 #[rstest(test_cases, expected_output,
1415 case(
1416 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1417 "^\\w\\s{3}\\u{2665}{3}\\s\\w{2}(?:\\s\\w{3}\\s\\w){2}(?:\\w{3}\\s){2}\\u{1f4a9}{2}\\.$"
1418 )
1419 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1420 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1421 let regexp = RegExpBuilder::from(&test_cases)
1422 .with_conversion_of_repetitions()
1423 .with_conversion_of_whitespace()
1424 .with_conversion_of_words()
1425 .with_escaping_of_non_ascii_chars(false)
1426 .build();
1427 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1428 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1429 }
1430
1431 #[rstest(test_cases, expected_output,
1432 case(
1433 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1434 "^\\w\\s{3}\\u{2665}{3}\\s\\w{2}(?:\\s\\w{3}\\s\\w){2}(?:\\w{3}\\s){2}(?:\\u{d83d}\\u{dca9}){2}\\.$"
1435 )
1436 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)1437 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
1438 let regexp = RegExpBuilder::from(&test_cases)
1439 .with_conversion_of_repetitions()
1440 .with_conversion_of_whitespace()
1441 .with_conversion_of_words()
1442 .with_escaping_of_non_ascii_chars(true)
1443 .build();
1444 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1445 }
1446 }
1447 }
1448
1449 mod digit_space_word_conversion {
1450 use super::*;
1451
1452 mod no_repetition {
1453 use super::*;
1454
1455 #[rstest(test_cases, expected_output,
1456 case(
1457 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1458 "^\\w\\s\\s\\s♥♥♥\\s\\d\\d\\s\\w\\w\\w\\s\\d\\s\\w\\w\\w\\s\\w\\w\\w\\w\\s\\w\\w\\w\\s\\.$"
1459 )
1460 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1461 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1462 let regexp = RegExpBuilder::from(&test_cases)
1463 .with_conversion_of_digits()
1464 .with_conversion_of_whitespace()
1465 .with_conversion_of_words()
1466 .build();
1467 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1468 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1469 }
1470
1471 #[rstest(test_cases, expected_output,
1472 case(
1473 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1474 "^\\w\\s\\s\\s\\u{2665}\\u{2665}\\u{2665}\\s\\d\\d\\s\\w\\w\\w\\s\\d\\s\\w\\w\\w\\s\\w\\w\\w\\w\\s\\w\\w\\w\\s\\u{1f4a9}\\u{1f4a9}\\.$"
1475 )
1476 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1477 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1478 let regexp = RegExpBuilder::from(&test_cases)
1479 .with_conversion_of_digits()
1480 .with_conversion_of_whitespace()
1481 .with_conversion_of_words()
1482 .with_escaping_of_non_ascii_chars(false)
1483 .build();
1484 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1485 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1486 }
1487
1488 #[rstest(test_cases, expected_output,
1489 case(
1490 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1491 "^\\w\\s\\s\\s\\u{2665}\\u{2665}\\u{2665}\\s\\d\\d\\s\\w\\w\\w\\s\\d\\s\\w\\w\\w\\s\\w\\w\\w\\w\\s\\w\\w\\w\\s\\u{d83d}\\u{dca9}\\u{d83d}\\u{dca9}\\.$"
1492 )
1493 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)1494 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
1495 let regexp = RegExpBuilder::from(&test_cases)
1496 .with_conversion_of_digits()
1497 .with_conversion_of_whitespace()
1498 .with_conversion_of_words()
1499 .with_escaping_of_non_ascii_chars(true)
1500 .build();
1501 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1502 }
1503 }
1504
1505 mod repetition {
1506 use super::*;
1507
1508 #[rstest(test_cases, expected_output,
1509 case(
1510 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1511 "^\\w\\s{3}♥{3}\\s\\d(?:\\d\\s\\w{3}\\s){2}\\w(?:\\w{3}\\s){2}{2}\\.$"
1512 )
1513 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1514 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1515 let regexp = RegExpBuilder::from(&test_cases)
1516 .with_conversion_of_repetitions()
1517 .with_conversion_of_digits()
1518 .with_conversion_of_whitespace()
1519 .with_conversion_of_words()
1520 .build();
1521 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1522 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1523 }
1524
1525 #[rstest(test_cases, expected_output,
1526 case(
1527 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1528 "^\\w\\s{3}\\u{2665}{3}\\s\\d(?:\\d\\s\\w{3}\\s){2}\\w(?:\\w{3}\\s){2}\\u{1f4a9}{2}\\.$"
1529 )
1530 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1531 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1532 let regexp = RegExpBuilder::from(&test_cases)
1533 .with_conversion_of_repetitions()
1534 .with_conversion_of_digits()
1535 .with_conversion_of_whitespace()
1536 .with_conversion_of_words()
1537 .with_escaping_of_non_ascii_chars(false)
1538 .build();
1539 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1540 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1541 }
1542
1543 #[rstest(test_cases, expected_output,
1544 case(
1545 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1546 "^\\w\\s{3}\\u{2665}{3}\\s\\d(?:\\d\\s\\w{3}\\s){2}\\w(?:\\w{3}\\s){2}(?:\\u{d83d}\\u{dca9}){2}\\.$"
1547 )
1548 )]
succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str)1549 fn succeeds_with_escape_and_surrogate_option(test_cases: Vec<&str>, expected_output: &str) {
1550 let regexp = RegExpBuilder::from(&test_cases)
1551 .with_conversion_of_repetitions()
1552 .with_conversion_of_digits()
1553 .with_conversion_of_whitespace()
1554 .with_conversion_of_words()
1555 .with_escaping_of_non_ascii_chars(true)
1556 .build();
1557 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1558 }
1559 }
1560 }
1561
1562 mod non_digit_conversion {
1563 use super::*;
1564
1565 mod no_repetition {
1566 use super::*;
1567
1568 #[rstest(test_cases, expected_output,
1569 case(
1570 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1571 "^\\D\\D\\D\\D\\D\\D\\D\\D36\\D\\D\\D\\D\\D٣\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D$"
1572 )
1573 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1574 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1575 let regexp = RegExpBuilder::from(&test_cases)
1576 .with_conversion_of_non_digits()
1577 .build();
1578 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1579 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1580 }
1581
1582 #[rstest(test_cases, expected_output,
1583 case(
1584 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1585 "^\\D\\D\\D\\D\\D\\D\\D\\D36\\D\\D\\D\\D\\D\\u{663}\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D$"
1586 )
1587 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1588 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1589 let regexp = RegExpBuilder::from(&test_cases)
1590 .with_conversion_of_non_digits()
1591 .with_escaping_of_non_ascii_chars(false)
1592 .build();
1593 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1594 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1595 }
1596 }
1597
1598 mod repetition {
1599 use super::*;
1600
1601 #[rstest(test_cases, expected_output,
1602 case(vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."], "^\\D{8}36\\D{5}٣\\D{17}$")
1603 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1604 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1605 let regexp = RegExpBuilder::from(&test_cases)
1606 .with_conversion_of_repetitions()
1607 .with_conversion_of_non_digits()
1608 .build();
1609 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1610 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1611 }
1612
1613 #[rstest(test_cases, expected_output,
1614 case(vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."], "^\\D{8}36\\D{5}\\u{663}\\D{17}$")
1615 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1616 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1617 let regexp = RegExpBuilder::from(&test_cases)
1618 .with_conversion_of_repetitions()
1619 .with_conversion_of_non_digits()
1620 .with_escaping_of_non_ascii_chars(false)
1621 .build();
1622 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1623 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1624 }
1625 }
1626 }
1627
1628 mod non_space_conversion {
1629 use super::*;
1630
1631 mod no_repetition {
1632 use super::*;
1633
1634 #[rstest(test_cases, expected_output,
1635 case(
1636 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1637 "^\\S \\S\\S\\S \\S\\S \\S\\S\\S \\S \\S\\S\\S \\S\\S\\S\\S \\S\\S\\S \\S\\S\\S$"
1638 )
1639 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1640 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1641 let regexp = RegExpBuilder::from(&test_cases)
1642 .with_conversion_of_non_whitespace()
1643 .build();
1644 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1645 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1646 }
1647 }
1648
1649 mod repetition {
1650 use super::*;
1651
1652 #[rstest(test_cases, expected_output,
1653 case(
1654 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1655 "^\\S {3}\\S(?:\\S{2} ){2}\\S{3} (?:\\S(?: \\S{3}){2}){2}$"
1656 )
1657 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1658 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1659 let regexp = RegExpBuilder::from(&test_cases)
1660 .with_conversion_of_repetitions()
1661 .with_conversion_of_non_whitespace()
1662 .build();
1663 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1664 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1665 }
1666 }
1667 }
1668
1669 mod non_word_conversion {
1670 use super::*;
1671
1672 mod no_repetition {
1673 use super::*;
1674
1675 #[rstest(test_cases, expected_output,
1676 case(
1677 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1678 "^I\\W\\W\\W\\W\\W\\W\\W36\\Wand\\W٣\\Wand\\Wy̆y̆\\Wand\\W\\W\\W\\W$"
1679 )
1680 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1681 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1682 let regexp = RegExpBuilder::from(&test_cases)
1683 .with_conversion_of_non_words()
1684 .build();
1685 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1686 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1687 }
1688
1689 #[rstest(test_cases, expected_output,
1690 case(
1691 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1692 "^I\\W\\W\\W\\W\\W\\W\\W36\\Wand\\W\\u{663}\\Wand\\Wy\\u{306}y\\u{306}\\Wand\\W\\W\\W\\W$"
1693 )
1694 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1695 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1696 let regexp = RegExpBuilder::from(&test_cases)
1697 .with_conversion_of_non_words()
1698 .with_escaping_of_non_ascii_chars(false)
1699 .build();
1700 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1701 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1702 }
1703 }
1704
1705 mod repetition {
1706 use super::*;
1707
1708 #[rstest(test_cases, expected_output,
1709 case(
1710 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1711 "^I\\W{7}36\\Wand\\W٣\\Wand\\W(?:y̆){2}\\Wand\\W{4}$"
1712 )
1713 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1714 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1715 let regexp = RegExpBuilder::from(&test_cases)
1716 .with_conversion_of_repetitions()
1717 .with_conversion_of_non_words()
1718 .build();
1719 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1720 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1721 }
1722
1723 #[rstest(test_cases, expected_output,
1724 case(
1725 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1726 "^I\\W{7}36\\Wand\\W\\u{663}\\Wand\\W(?:y\\u{306}){2}\\Wand\\W{4}$"
1727 )
1728 )]
succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str)1729 fn succeeds_with_escape_option(test_cases: Vec<&str>, expected_output: &str) {
1730 let regexp = RegExpBuilder::from(&test_cases)
1731 .with_conversion_of_repetitions()
1732 .with_conversion_of_non_words()
1733 .with_escaping_of_non_ascii_chars(false)
1734 .build();
1735 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1736 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1737 }
1738 }
1739 }
1740
1741 mod non_digit_non_space_conversion {
1742 use super::*;
1743
1744 mod no_repetition {
1745 use super::*;
1746
1747 #[rstest(test_cases, expected_output,
1748 case(
1749 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1750 "^\\D\\D\\D\\D\\D\\D\\D\\D\\S\\S\\D\\D\\D\\D\\D\\S\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D$"
1751 )
1752 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1753 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1754 let regexp = RegExpBuilder::from(&test_cases)
1755 .with_conversion_of_non_digits()
1756 .with_conversion_of_non_whitespace()
1757 .build();
1758 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1759 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1760 }
1761 }
1762
1763 mod repetition {
1764 use super::*;
1765
1766 #[rstest(test_cases, expected_output,
1767 case(vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."], "^\\D{8}\\S{2}\\D{5}\\S\\D{17}$")
1768 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1769 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1770 let regexp = RegExpBuilder::from(&test_cases)
1771 .with_conversion_of_repetitions()
1772 .with_conversion_of_non_digits()
1773 .with_conversion_of_non_whitespace()
1774 .build();
1775 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1776 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1777 }
1778 }
1779 }
1780
1781 mod non_digit_non_word_conversion {
1782 use super::*;
1783
1784 mod no_repetition {
1785 use super::*;
1786
1787 #[rstest(test_cases, expected_output,
1788 case(
1789 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1790 "^\\D\\D\\D\\D\\D\\D\\D\\D36\\D\\D\\D\\D\\D٣\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D$"
1791 )
1792 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1793 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1794 let regexp = RegExpBuilder::from(&test_cases)
1795 .with_conversion_of_non_digits()
1796 .with_conversion_of_non_words()
1797 .build();
1798 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1799 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1800 }
1801 }
1802
1803 mod repetition {
1804 use super::*;
1805
1806 #[rstest(test_cases, expected_output,
1807 case(vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."], "^\\D{8}36\\D{5}٣\\D{17}$")
1808 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1809 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1810 let regexp = RegExpBuilder::from(&test_cases)
1811 .with_conversion_of_repetitions()
1812 .with_conversion_of_non_digits()
1813 .with_conversion_of_non_words()
1814 .build();
1815 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1816 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1817 }
1818 }
1819 }
1820
1821 mod non_space_non_word_conversion {
1822 use super::*;
1823
1824 mod no_repetition {
1825 use super::*;
1826
1827 #[rstest(test_cases, expected_output,
1828 case(
1829 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1830 "^\\S\\W\\W\\W\\W\\W\\W\\W\\S\\S\\W\\S\\S\\S\\W\\S\\W\\S\\S\\S\\W\\S\\S\\S\\S\\W\\S\\S\\S\\W\\W\\W\\W$"
1831 )
1832 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1833 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1834 let regexp = RegExpBuilder::from(&test_cases)
1835 .with_conversion_of_non_whitespace()
1836 .with_conversion_of_non_words()
1837 .build();
1838 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1839 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1840 }
1841 }
1842
1843 mod repetition {
1844 use super::*;
1845
1846 #[rstest(test_cases, expected_output,
1847 case(
1848 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1849 "^\\S\\W{7}\\S(?:\\S\\W\\S{3}\\W){2}\\S{4}\\W\\S{3}\\W{4}$"
1850 )
1851 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1852 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1853 let regexp = RegExpBuilder::from(&test_cases)
1854 .with_conversion_of_repetitions()
1855 .with_conversion_of_non_whitespace()
1856 .with_conversion_of_non_words()
1857 .build();
1858 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1859 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1860 }
1861 }
1862 }
1863
1864 mod non_digit_non_space_non_word_conversion {
1865 use super::*;
1866
1867 mod no_repetition {
1868 use super::*;
1869
1870 #[rstest(test_cases, expected_output,
1871 case(
1872 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1873 "^\\D\\D\\D\\D\\D\\D\\D\\D\\S\\S\\D\\D\\D\\D\\D\\S\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D$"
1874 )
1875 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1876 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1877 let regexp = RegExpBuilder::from(&test_cases)
1878 .with_conversion_of_non_digits()
1879 .with_conversion_of_non_whitespace()
1880 .with_conversion_of_non_words()
1881 .build();
1882 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1883 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1884 }
1885 }
1886
1887 mod repetition {
1888 use super::*;
1889
1890 #[rstest(test_cases, expected_output,
1891 case(vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."], "^\\D{8}\\S{2}\\D{5}\\S\\D{17}$")
1892 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1893 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1894 let regexp = RegExpBuilder::from(&test_cases)
1895 .with_conversion_of_repetitions()
1896 .with_conversion_of_non_digits()
1897 .with_conversion_of_non_whitespace()
1898 .with_conversion_of_non_words()
1899 .build();
1900 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1901 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1902 }
1903 }
1904 }
1905
1906 mod digit_non_digit_conversion {
1907 use super::*;
1908
1909 mod no_repetition {
1910 use super::*;
1911
1912 #[rstest(test_cases, expected_output,
1913 case(
1914 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1915 "^\\D\\D\\D\\D\\D\\D\\D\\D\\d\\d\\D\\D\\D\\D\\D\\d\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D\\D$"
1916 )
1917 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1918 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1919 let regexp = RegExpBuilder::from(&test_cases)
1920 .with_conversion_of_digits()
1921 .with_conversion_of_non_digits()
1922 .build();
1923 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1924 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1925 }
1926 }
1927
1928 mod repetition {
1929 use super::*;
1930
1931 #[rstest(test_cases, expected_output,
1932 case(vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."], "^\\D{8}\\d{2}\\D{5}\\d\\D{17}$")
1933 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1934 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1935 let regexp = RegExpBuilder::from(&test_cases)
1936 .with_conversion_of_repetitions()
1937 .with_conversion_of_digits()
1938 .with_conversion_of_non_digits()
1939 .build();
1940 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1941 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1942 }
1943 }
1944 }
1945
1946 mod space_non_space_conversion {
1947 use super::*;
1948
1949 mod no_repetition {
1950 use super::*;
1951
1952 #[rstest(test_cases, expected_output,
1953 case(
1954 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1955 "^\\S\\s\\s\\s\\S\\S\\S\\s\\S\\S\\s\\S\\S\\S\\s\\S\\s\\S\\S\\S\\s\\S\\S\\S\\S\\s\\S\\S\\S\\s\\S\\S\\S$"
1956 )
1957 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1958 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1959 let regexp = RegExpBuilder::from(&test_cases)
1960 .with_conversion_of_whitespace()
1961 .with_conversion_of_non_whitespace()
1962 .build();
1963 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1964 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1965 }
1966 }
1967
1968 mod repetition {
1969 use super::*;
1970
1971 #[rstest(test_cases, expected_output,
1972 case(
1973 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1974 "^\\S\\s{3}\\S(?:\\S{2}\\s){2}\\S{3}\\s(?:\\S(?:\\s\\S{3}){2}){2}$"
1975 )
1976 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)1977 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
1978 let regexp = RegExpBuilder::from(&test_cases)
1979 .with_conversion_of_repetitions()
1980 .with_conversion_of_whitespace()
1981 .with_conversion_of_non_whitespace()
1982 .build();
1983 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
1984 assert_that_regexp_matches_test_cases(expected_output, test_cases);
1985 }
1986 }
1987 }
1988
1989 mod word_non_word_conversion {
1990 use super::*;
1991
1992 mod no_repetition {
1993 use super::*;
1994
1995 #[rstest(test_cases, expected_output,
1996 case(
1997 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
1998 "^\\w\\W\\W\\W\\W\\W\\W\\W\\w\\w\\W\\w\\w\\w\\W\\w\\W\\w\\w\\w\\W\\w\\w\\w\\w\\W\\w\\w\\w\\W\\W\\W\\W$"
1999 )
2000 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)2001 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
2002 let regexp = RegExpBuilder::from(&test_cases)
2003 .with_conversion_of_words()
2004 .with_conversion_of_non_words()
2005 .build();
2006 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
2007 assert_that_regexp_matches_test_cases(expected_output, test_cases);
2008 }
2009 }
2010
2011 mod repetition {
2012 use super::*;
2013
2014 #[rstest(test_cases, expected_output,
2015 case(
2016 vec!["I ♥♥♥ 36 and ٣ and y̆y̆ and ."],
2017 "^\\w\\W{7}\\w(?:\\w\\W\\w{3}\\W){2}\\w{4}\\W\\w{3}\\W{4}$"
2018 )
2019 )]
succeeds(test_cases: Vec<&str>, expected_output: &str)2020 fn succeeds(test_cases: Vec<&str>, expected_output: &str) {
2021 let regexp = RegExpBuilder::from(&test_cases)
2022 .with_conversion_of_repetitions()
2023 .with_conversion_of_words()
2024 .with_conversion_of_non_words()
2025 .build();
2026 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
2027 assert_that_regexp_matches_test_cases(expected_output, test_cases);
2028 }
2029 }
2030 }
2031
2032 mod anchor_conversion {
2033 use super::*;
2034
2035 mod no_verbose {
2036 use super::*;
2037
2038 #[rstest(test_cases, expected_output,
2039 case(vec!["My ♥♥♥ and is yours."], "My ♥♥♥ and is yours\\.$"),
2040 )]
succeeds_with_no_start_anchor_option(test_cases: Vec<&str>, expected_output: &str)2041 fn succeeds_with_no_start_anchor_option(test_cases: Vec<&str>, expected_output: &str) {
2042 let regexp = RegExpBuilder::from(&test_cases)
2043 .without_start_anchor()
2044 .build();
2045 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
2046 }
2047
2048 #[rstest(test_cases, expected_output,
2049 case(vec!["My ♥♥♥ and is yours."], "^My ♥♥♥ and is yours\\."),
2050 )]
succeeds_with_no_end_anchor_option(test_cases: Vec<&str>, expected_output: &str)2051 fn succeeds_with_no_end_anchor_option(test_cases: Vec<&str>, expected_output: &str) {
2052 let regexp = RegExpBuilder::from(&test_cases)
2053 .without_end_anchor()
2054 .build();
2055 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
2056 }
2057
2058 #[rstest(test_cases, expected_output,
2059 case(vec!["My ♥♥♥ and is yours."], "My ♥♥♥ and is yours\\."),
2060 )]
succeeds_with_no_match_line_option(test_cases: Vec<&str>, expected_output: &str)2061 fn succeeds_with_no_match_line_option(test_cases: Vec<&str>, expected_output: &str) {
2062 let regexp = RegExpBuilder::from(&test_cases).without_anchors().build();
2063 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
2064 }
2065 }
2066
2067 mod verbose {
2068 use super::*;
2069
2070 #[rstest(test_cases, expected_output,
2071 case(vec!["My ♥♥♥ and is yours."], indoc!(
2072 r#"
2073 (?x)
2074 My\ ♥♥♥\ and\ \ is\ yours\.
2075 $"#
2076 ))
2077 )]
succeeds_with_verbose_mode_and_no_start_anchor_option( test_cases: Vec<&str>, expected_output: &str, )2078 fn succeeds_with_verbose_mode_and_no_start_anchor_option(
2079 test_cases: Vec<&str>,
2080 expected_output: &str,
2081 ) {
2082 let regexp = RegExpBuilder::from(&test_cases)
2083 .with_verbose_mode()
2084 .without_start_anchor()
2085 .build();
2086 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
2087 }
2088
2089 #[rstest(test_cases, expected_output,
2090 case(vec!["My ♥♥♥ and is yours."], indoc!(
2091 r#"
2092 (?x)
2093 ^
2094 My\ ♥♥♥\ and\ \ is\ yours\."#
2095 ))
2096 )]
succeeds_with_verbose_mode_and_no_end_anchor_option( test_cases: Vec<&str>, expected_output: &str, )2097 fn succeeds_with_verbose_mode_and_no_end_anchor_option(
2098 test_cases: Vec<&str>,
2099 expected_output: &str,
2100 ) {
2101 let regexp = RegExpBuilder::from(&test_cases)
2102 .with_verbose_mode()
2103 .without_end_anchor()
2104 .build();
2105 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
2106 }
2107
2108 #[rstest(test_cases, expected_output,
2109 case(vec!["My ♥♥♥ and is yours."], indoc!(
2110 r#"
2111 (?x)
2112 My\ ♥♥♥\ and\ \ is\ yours\."#
2113 ))
2114 )]
succeeds_with_verbose_mode_and_no_anchors_option( test_cases: Vec<&str>, expected_output: &str, )2115 fn succeeds_with_verbose_mode_and_no_anchors_option(
2116 test_cases: Vec<&str>,
2117 expected_output: &str,
2118 ) {
2119 let regexp = RegExpBuilder::from(&test_cases)
2120 .with_verbose_mode()
2121 .without_anchors()
2122 .build();
2123 assert_that_regexp_is_correct(regexp, expected_output, &test_cases);
2124 }
2125 }
2126 }
2127
assert_that_regexp_is_correct(regexp: String, expected_output: &str, test_cases: &[&str])2128 fn assert_that_regexp_is_correct(regexp: String, expected_output: &str, test_cases: &[&str]) {
2129 assert_eq!(
2130 regexp, expected_output,
2131 "\n\ninput: {:?}\nexpected: {}\nactual: {}\n\n",
2132 test_cases, expected_output, regexp
2133 );
2134 }
2135
assert_that_regexp_matches_test_cases(expected_output: &str, test_cases: Vec<&str>)2136 fn assert_that_regexp_matches_test_cases(expected_output: &str, test_cases: Vec<&str>) {
2137 let re = Regex::new(expected_output).unwrap();
2138 for test_case in test_cases {
2139 assert_eq!(
2140 re.find_iter(test_case).count(),
2141 1,
2142 "\n\n\"{}\" does not match regex {}\n\n",
2143 test_case,
2144 expected_output
2145 );
2146 }
2147 }
2148