summaryrefslogtreecommitdiffstats
path: root/third_party/rust/regex-automata/tests/meta/suite.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/regex-automata/tests/meta/suite.rs')
-rw-r--r--third_party/rust/regex-automata/tests/meta/suite.rs200
1 files changed, 200 insertions, 0 deletions
diff --git a/third_party/rust/regex-automata/tests/meta/suite.rs b/third_party/rust/regex-automata/tests/meta/suite.rs
new file mode 100644
index 0000000000..20f97b4bb9
--- /dev/null
+++ b/third_party/rust/regex-automata/tests/meta/suite.rs
@@ -0,0 +1,200 @@
+use {
+ anyhow::Result,
+ regex_automata::{
+ meta::{self, Regex},
+ util::syntax,
+ MatchKind, PatternSet,
+ },
+ regex_test::{
+ CompiledRegex, Match, RegexTest, SearchKind, Span, TestResult,
+ TestRunner,
+ },
+};
+
+use crate::{create_input, suite, testify_captures};
+
+const BLACKLIST: &[&str] = &[
+ // These 'earliest' tests are blacklisted because the meta searcher doesn't
+ // give the same offsets that the test expects. This is legal because the
+ // 'earliest' routines don't guarantee a particular match offset other
+ // than "the earliest the regex engine can report a match." Some regex
+ // engines will quit earlier than others. The backtracker, for example,
+ // can't really quit before finding the full leftmost-first match. Many of
+ // the literal searchers also don't have the ability to quit fully or it's
+ // otherwise not worth doing. (A literal searcher not quitting as early as
+ // possible usually means looking at a few more bytes. That's no biggie.)
+ "earliest/",
+];
+
+/// Tests the default configuration of the meta regex engine.
+#[test]
+fn default() -> Result<()> {
+ let builder = Regex::builder();
+ let mut runner = TestRunner::new()?;
+ runner
+ .expand(&["is_match", "find", "captures"], |test| test.compiles())
+ .blacklist_iter(BLACKLIST)
+ .test_iter(suite()?.iter(), compiler(builder))
+ .assert();
+ Ok(())
+}
+
+/// Tests the default configuration minus the full DFA.
+#[test]
+fn no_dfa() -> Result<()> {
+ let mut builder = Regex::builder();
+ builder.configure(Regex::config().dfa(false));
+ let mut runner = TestRunner::new()?;
+ runner
+ .expand(&["is_match", "find", "captures"], |test| test.compiles())
+ .blacklist_iter(BLACKLIST)
+ .test_iter(suite()?.iter(), compiler(builder))
+ .assert();
+ Ok(())
+}
+
+/// Tests the default configuration minus the full DFA and lazy DFA.
+#[test]
+fn no_dfa_hybrid() -> Result<()> {
+ let mut builder = Regex::builder();
+ builder.configure(Regex::config().dfa(false).hybrid(false));
+ let mut runner = TestRunner::new()?;
+ runner
+ .expand(&["is_match", "find", "captures"], |test| test.compiles())
+ .blacklist_iter(BLACKLIST)
+ .test_iter(suite()?.iter(), compiler(builder))
+ .assert();
+ Ok(())
+}
+
+/// Tests the default configuration minus the full DFA, lazy DFA and one-pass
+/// DFA.
+#[test]
+fn no_dfa_hybrid_onepass() -> Result<()> {
+ let mut builder = Regex::builder();
+ builder.configure(Regex::config().dfa(false).hybrid(false).onepass(false));
+ let mut runner = TestRunner::new()?;
+ runner
+ .expand(&["is_match", "find", "captures"], |test| test.compiles())
+ .blacklist_iter(BLACKLIST)
+ .test_iter(suite()?.iter(), compiler(builder))
+ .assert();
+ Ok(())
+}
+
+/// Tests the default configuration minus the full DFA, lazy DFA, one-pass
+/// DFA and backtracker.
+#[test]
+fn no_dfa_hybrid_onepass_backtrack() -> Result<()> {
+ let mut builder = Regex::builder();
+ builder.configure(
+ Regex::config()
+ .dfa(false)
+ .hybrid(false)
+ .onepass(false)
+ .backtrack(false),
+ );
+ let mut runner = TestRunner::new()?;
+ runner
+ .expand(&["is_match", "find", "captures"], |test| test.compiles())
+ .blacklist_iter(BLACKLIST)
+ .test_iter(suite()?.iter(), compiler(builder))
+ .assert();
+ Ok(())
+}
+
+fn compiler(
+ mut builder: meta::Builder,
+) -> impl FnMut(&RegexTest, &[String]) -> Result<CompiledRegex> {
+ move |test, regexes| {
+ if !configure_meta_builder(test, &mut builder) {
+ return Ok(CompiledRegex::skip());
+ }
+ let re = builder.build_many(&regexes)?;
+ Ok(CompiledRegex::compiled(move |test| -> TestResult {
+ run_test(&re, test)
+ }))
+ }
+}
+
+fn run_test(re: &Regex, test: &RegexTest) -> TestResult {
+ let input = create_input(test);
+ match test.additional_name() {
+ "is_match" => TestResult::matched(re.is_match(input)),
+ "find" => match test.search_kind() {
+ SearchKind::Earliest => TestResult::matches(
+ re.find_iter(input.earliest(true))
+ .take(test.match_limit().unwrap_or(std::usize::MAX))
+ .map(|m| Match {
+ id: m.pattern().as_usize(),
+ span: Span { start: m.start(), end: m.end() },
+ }),
+ ),
+ SearchKind::Leftmost => TestResult::matches(
+ re.find_iter(input)
+ .take(test.match_limit().unwrap_or(std::usize::MAX))
+ .map(|m| Match {
+ id: m.pattern().as_usize(),
+ span: Span { start: m.start(), end: m.end() },
+ }),
+ ),
+ SearchKind::Overlapping => {
+ let mut patset = PatternSet::new(re.pattern_len());
+ re.which_overlapping_matches(&input, &mut patset);
+ TestResult::which(patset.iter().map(|p| p.as_usize()))
+ }
+ },
+ "captures" => match test.search_kind() {
+ SearchKind::Earliest => {
+ let it = re
+ .captures_iter(input.earliest(true))
+ .take(test.match_limit().unwrap_or(std::usize::MAX))
+ .map(|caps| testify_captures(&caps));
+ TestResult::captures(it)
+ }
+ SearchKind::Leftmost => {
+ let it = re
+ .captures_iter(input)
+ .take(test.match_limit().unwrap_or(std::usize::MAX))
+ .map(|caps| testify_captures(&caps));
+ TestResult::captures(it)
+ }
+ SearchKind::Overlapping => {
+ // There is no overlapping regex API that supports captures.
+ TestResult::skip()
+ }
+ },
+ name => TestResult::fail(&format!("unrecognized test name: {}", name)),
+ }
+}
+
+/// Configures the given regex builder with all relevant settings on the given
+/// regex test.
+///
+/// If the regex test has a setting that is unsupported, then this returns
+/// false (implying the test should be skipped).
+fn configure_meta_builder(
+ test: &RegexTest,
+ builder: &mut meta::Builder,
+) -> bool {
+ let match_kind = match test.match_kind() {
+ regex_test::MatchKind::All => MatchKind::All,
+ regex_test::MatchKind::LeftmostFirst => MatchKind::LeftmostFirst,
+ regex_test::MatchKind::LeftmostLongest => return false,
+ };
+ let meta_config = Regex::config()
+ .match_kind(match_kind)
+ .utf8_empty(test.utf8())
+ .line_terminator(test.line_terminator());
+ builder.configure(meta_config).syntax(config_syntax(test));
+ true
+}
+
+/// Configuration of the regex parser from a regex test.
+fn config_syntax(test: &RegexTest) -> syntax::Config {
+ syntax::Config::new()
+ .case_insensitive(test.case_insensitive())
+ .unicode(test.unicode())
+ .utf8(test.utf8())
+ .line_terminator(test.line_terminator())
+}