1use {
2 anyhow::Result,
3 regex::{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 let hay = match std::str::from_utf8(test.haystack()) {
21 Ok(hay) => hay,
22 Err(err) => {
23 return TestResult::fail(&format!(
24 "haystack is not valid UTF-8: {}",
25 err
26 ));
27 }
28 };
29 match test.additional_name() {
30 "is_match" => TestResult::matched(re.is_match(hay)),
31 "which" => TestResult::which(re.matches(hay).iter()),
32 name => TestResult::fail(&format!("unrecognized test name: {}", name)),
33 }
34}
35
36/// Converts the given regex test to a closure that searches with a
37/// `bytes::Regex`. If the test configuration is unsupported, then a
38/// `CompiledRegex` that skips the test is returned.
39fn compiler(
40 test: &RegexTest,
41 _patterns: &[String],
42) -> anyhow::Result<CompiledRegex> {
43 let skip = Ok(CompiledRegex::skip());
44
45 // The top-level RegexSet API only supports "overlapping" semantics.
46 if !matches!(test.search_kind(), regex_test::SearchKind::Overlapping) {
47 return skip;
48 }
49 // The top-level RegexSet API only supports "all" semantics.
50 if !matches!(test.match_kind(), regex_test::MatchKind::All) {
51 return skip;
52 }
53 // The top-level RegexSet API always runs unanchored searches.
54 if test.anchored() {
55 return skip;
56 }
57 // We don't support tests with explicit search bounds.
58 let bounds = test.bounds();
59 if !(bounds.start == 0 && bounds.end == test.haystack().len()) {
60 return skip;
61 }
62 // The Regex API specifically does not support disabling UTF-8 mode because
63 // it can only search &str which is always valid UTF-8.
64 if !test.utf8() {
65 return skip;
66 }
67 // If the test requires Unicode but the Unicode feature isn't enabled,
68 // skip it. This is a little aggressive, but the test suite doesn't
69 // have any easy way of communicating which Unicode features are needed.
70 if test.unicode() && !cfg!(feature = "unicode") {
71 return skip;
72 }
73 let re = RegexSetBuilder::new(test.regexes())
74 .case_insensitive(test.case_insensitive())
75 .unicode(test.unicode())
76 .line_terminator(test.line_terminator())
77 .build()?;
78 Ok(CompiledRegex::compiled(move |test| run_test(&re, test)))
79}
80