/// A description of a single test against a multi-pattern searcher. /// /// A single test may not necessarily pass on every configuration of a /// searcher. The tests are categorized and grouped appropriately below. #[derive(Clone, Debug, Eq, PartialEq)] struct SearchTest { /// The name of this test, for debugging.
name: &'static str, /// The patterns to search for.
patterns: &'static [&'static str], /// The text to search.
haystack: &'static str, /// Each match is a triple of (pattern_index, start, end), where /// pattern_index is an index into `patterns` and `start`/`end` are indices /// into `haystack`.
matches: &'static [(usize, usize, usize)],
}
/// Short-hand constructor for SearchTest. We use it a lot below.
macro_rules! t {
($name:ident, $patterns:expr, $haystack:expr, $matches:expr) => {
SearchTest {
name: stringify!($name),
patterns: $patterns,
haystack: $haystack,
matches: $matches,
}
};
}
/// A collection of test groups. type TestCollection = &'static [&'static [SearchTest]];
// Define several collections corresponding to the different type of match // semantics supported. These collections have some overlap, but each // collection should have some tests that no other collection has.
/// Tests for leftmost-first match semantics. const PACKED_LEFTMOST_FIRST: TestCollection =
&[BASICS, LEFTMOST, LEFTMOST_FIRST, REGRESSION, TEDDY];
/// Tests for leftmost-longest match semantics. const PACKED_LEFTMOST_LONGEST: TestCollection =
&[BASICS, LEFTMOST, LEFTMOST_LONGEST, REGRESSION, TEDDY];
// Now define the individual tests that make up the collections above.
// Now define a test for each combination of things above that we want to run. // Since there are a few different combinations for each collection of tests, // we define a couple of macros to avoid repetition drudgery. The testconfig // macro constructs the automaton from a given match kind, and runs the search // tests one-by-one over the given collection. The `with` parameter allows one // to configure the config with additional parameters. The testcombo macro // invokes testconfig in precisely this way: it sets up several tests where // each one turns a different knob on Config.
macro_rules! testconfig {
($name:ident, $collection:expr, $with:expr) => { #[test] fn $name() {
run_search_tests($collection, |test| { letmut config = Config::new();
$with(&mut config); letmut builder = config.builder();
builder.extend(test.patterns.iter().map(|p| p.as_bytes())); let searcher = match builder.build() {
Some(searcher) => searcher,
None => { // For x86-64 and aarch64, not building a searcher is // probably a bug, so be loud. if cfg!(any(
target_arch = "x86_64",
target_arch = "aarch64"
)) {
panic!("failed to build packed searcher")
} return None;
}
};
Some(searcher.find_iter(&test.haystack).collect())
});
}
};
}
#[test] fn search_tests_have_unique_names() { let assert = |constname, tests: &[SearchTest]| { letmut seen = HashMap::new(); // map from test name to position for (i, test) in tests.iter().enumerate() { if !seen.contains_key(test.name) {
seen.insert(test.name, i);
} else { let last = seen[test.name];
panic!( "{} tests have duplicate names at positions {} and {}",
constname, last, i
);
}
}
};
assert("BASICS", BASICS);
assert("LEFTMOST", LEFTMOST);
assert("LEFTMOST_FIRST", LEFTMOST_FIRST);
assert("LEFTMOST_LONGEST", LEFTMOST_LONGEST);
assert("REGRESSION", REGRESSION);
assert("TEDDY", TEDDY);
}
fn run_search_tests<F: FnMut(&SearchTestOwned) -> Option<Vec<Match>>>(
which: TestCollection, mut f: F,
) { let get_match_triples =
|matches: Vec<Match>| -> Vec<(usize, usize, usize)> {
matches
.into_iter()
.map(|m| (m.pattern().as_usize(), m.start(), m.end()))
.collect()
}; for &tests in which { for spec in tests { for test in spec.variations() { let results = match f(&test) {
None => continue,
Some(results) => results,
};
assert_eq!(
test.matches,
get_match_triples(results).as_slice(), "test: {}, patterns: {:?}, haystack(len={:?}): {:?}, \
offset: {:?}",
test.name,
test.patterns,
test.haystack.len(),
test.haystack,
test.offset,
);
}
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.