1// We have a similar config in the regex-automata crate root. Basically, it is
2// just too annoying to deal with dead code when a subset of features is
3// enabled.
4#![cfg_attr(
5 not(all(
6 feature = "std",
7 feature = "nfa",
8 feature = "dfa",
9 feature = "hybrid",
10 feature = "perf-literal-substring",
11 feature = "perf-literal-multisubstring",
12 )),
13 allow(dead_code, unused_imports, unused_variables)
14)]
15// Similar deal with Miri. Just let dead code warnings be.
16#![cfg_attr(miri, allow(dead_code, unused_imports, unused_variables))]
17
18#[cfg(any(feature = "dfa-search", feature = "dfa-onepass"))]
19mod dfa;
20#[cfg(feature = "dfa-search")]
21mod fuzz;
22#[cfg(feature = "dfa-search")]
23mod gen;
24#[cfg(feature = "hybrid")]
25mod hybrid;
26#[cfg(feature = "meta")]
27mod meta;
28#[cfg(any(feature = "nfa-backtrack", feature = "nfa-pikevm"))]
29mod nfa;
30
31fn suite() -> anyhow::Result<regex_test::RegexTests> {
32 let _ = env_logger::try_init();
33
34 let mut tests = regex_test::RegexTests::new();
35 macro_rules! load {
36 ($name:expr) => {{
37 const DATA: &[u8] =
38 include_bytes!(concat!("../../testdata/", $name, ".toml"));
39 tests.load_slice($name, DATA)?;
40 }};
41 }
42
43 load!("anchored");
44 load!("bytes");
45 load!("crazy");
46 load!("crlf");
47 load!("earliest");
48 load!("empty");
49 load!("expensive");
50 load!("flags");
51 load!("iter");
52 load!("leftmost-all");
53 load!("line-terminator");
54 load!("misc");
55 load!("multiline");
56 load!("no-unicode");
57 load!("overlapping");
58 load!("regression");
59 load!("set");
60 load!("substring");
61 load!("unicode");
62 load!("utf8");
63 load!("word-boundary");
64 load!("word-boundary-special");
65 load!("fowler/basic");
66 load!("fowler/nullsubexpr");
67 load!("fowler/repetition");
68
69 Ok(tests)
70}
71
72/// Configure a regex_automata::Input with the given test configuration.
73fn create_input<'h>(
74 test: &'h regex_test::RegexTest,
75) -> regex_automata::Input<'h> {
76 use regex_automata::Anchored;
77
78 let bounds = test.bounds();
79 let anchored = if test.anchored() { Anchored::Yes } else { Anchored::No };
80 regex_automata::Input::new(test.haystack())
81 .range(bounds.start..bounds.end)
82 .anchored(anchored)
83}
84
85/// Convert capture matches into the test suite's capture values.
86///
87/// The given captures must represent a valid match, where the first capturing
88/// group has a non-None span. Otherwise this panics.
89fn testify_captures(
90 caps: &regex_automata::util::captures::Captures,
91) -> regex_test::Captures {
92 assert!(caps.is_match(), "expected captures to represent a match");
93 let spans = caps.iter().map(|group| {
94 group.map(|m| regex_test::Span { start: m.start, end: m.end })
95 });
96 // These unwraps are OK because we assume our 'caps' represents a match,
97 // and a match always gives a non-zero number of groups with the first
98 // group being non-None.
99 regex_test::Captures::new(caps.pattern().unwrap().as_usize(), spans)
100 .unwrap()
101}
102
103/// Convert a test harness match kind to a regex-automata match kind. If
104/// regex-automata doesn't support the harness kind, then `None` is returned.
105fn untestify_kind(
106 kind: regex_test::MatchKind,
107) -> Option<regex_automata::MatchKind> {
108 match kind {
109 regex_test::MatchKind::All => Some(regex_automata::MatchKind::All),
110 regex_test::MatchKind::LeftmostFirst => {
111 Some(regex_automata::MatchKind::LeftmostFirst)
112 }
113 regex_test::MatchKind::LeftmostLongest => None,
114 }
115}
116