1use {
2 anyhow::Result,
3 regex::bytes::{RegexSet, RegexSetBuilder},
4 regex_test::{CompiledRegex, RegexTest, TestResult, TestRunner},
5};
6
7/// Tests the default configuration of the hybrid NFA/DFA.
8#[test]
9fn default() -> Result<()> {
10 let mut runner = TestRunner::new()?;
11 runner
12 .expand(&["is_match", "which"], |test| test.compiles())
13 .blacklist_iter(super::BLACKLIST)
14 .test_iter(crate::suite()?.iter(), compiler)
15 .assert();
16 Ok(())
17}
18
19fn run_test(re: &RegexSet, test: &RegexTest) -> TestResult {
20 match test.additional_name() {
21 "is_match" => TestResult::matched(re.is_match(test.haystack())),
22 "which" => TestResult::which(re.matches(test.haystack()).iter()),
23 name => TestResult::fail(&format!("unrecognized test name: {}", name)),
24 }
25}
26
27/// Converts the given regex test to a closure that searches with a
28/// `bytes::Regex`. If the test configuration is unsupported, then a
29/// `CompiledRegex` that skips the test is returned.
30fn compiler(
31 test: &RegexTest,
32 _patterns: &[String],
33) -> anyhow::Result<CompiledRegex> {
34 let skip = Ok(CompiledRegex::skip());
35
36 // The top-level RegexSet API only supports "overlapping" semantics.
37 if !matches!(test.search_kind(), regex_test::SearchKind::Overlapping) {
38 return skip;
39 }
40 // The top-level RegexSet API only supports "all" semantics.
41 if !matches!(test.match_kind(), regex_test::MatchKind::All) {
42 return skip;
43 }
44 // The top-level RegexSet API always runs unanchored searches.
45 if test.anchored() {
46 return skip;
47 }
48 // We don't support tests with explicit search bounds.
49 let bounds = test.bounds();
50 if !(bounds.start == 0 && bounds.end == test.haystack().len()) {
51 return skip;
52 }
53 // The bytes::Regex API specifically does not support enabling UTF-8 mode.
54 // It could I suppose, but currently it does not. That is, it permits
55 // matches to have offsets that split codepoints.
56 if test.utf8() {
57 return skip;
58 }
59 // If the test requires Unicode but the Unicode feature isn't enabled,
60 // skip it. This is a little aggressive, but the test suite doesn't
61 // have any easy way of communicating which Unicode features are needed.
62 if test.unicode() && !cfg!(feature = "unicode") {
63 return skip;
64 }
65 let re = RegexSetBuilder::new(test.regexes())
66 .case_insensitive(test.case_insensitive())
67 .unicode(test.unicode())
68 .line_terminator(test.line_terminator())
69 .build()?;
70 Ok(CompiledRegex::compiled(move |test| run_test(&re, test)))
71}
72