106f54294Sopenharmony_ciuse std::collections::HashMap;
206f54294Sopenharmony_ciuse std::io;
306f54294Sopenharmony_ciuse std::usize;
406f54294Sopenharmony_ci
506f54294Sopenharmony_ciuse crate::{AhoCorasickBuilder, Match, MatchKind};
606f54294Sopenharmony_ci
706f54294Sopenharmony_ci/// A description of a single test against an Aho-Corasick automaton.
806f54294Sopenharmony_ci///
906f54294Sopenharmony_ci/// A single test may not necessarily pass on every configuration of an
1006f54294Sopenharmony_ci/// Aho-Corasick automaton. The tests are categorized and grouped appropriately
1106f54294Sopenharmony_ci/// below.
1206f54294Sopenharmony_ci#[derive(Clone, Debug, Eq, PartialEq)]
1306f54294Sopenharmony_cistruct SearchTest {
1406f54294Sopenharmony_ci    /// The name of this test, for debugging.
1506f54294Sopenharmony_ci    name: &'static str,
1606f54294Sopenharmony_ci    /// The patterns to search for.
1706f54294Sopenharmony_ci    patterns: &'static [&'static str],
1806f54294Sopenharmony_ci    /// The text to search.
1906f54294Sopenharmony_ci    haystack: &'static str,
2006f54294Sopenharmony_ci    /// Each match is a triple of (pattern_index, start, end), where
2106f54294Sopenharmony_ci    /// pattern_index is an index into `patterns` and `start`/`end` are indices
2206f54294Sopenharmony_ci    /// into `haystack`.
2306f54294Sopenharmony_ci    matches: &'static [(usize, usize, usize)],
2406f54294Sopenharmony_ci}
2506f54294Sopenharmony_ci
2606f54294Sopenharmony_ci/// Short-hand constructor for SearchTest. We use it a lot below.
2706f54294Sopenharmony_cimacro_rules! t {
2806f54294Sopenharmony_ci    ($name:ident, $patterns:expr, $haystack:expr, $matches:expr) => {
2906f54294Sopenharmony_ci        SearchTest {
3006f54294Sopenharmony_ci            name: stringify!($name),
3106f54294Sopenharmony_ci            patterns: $patterns,
3206f54294Sopenharmony_ci            haystack: $haystack,
3306f54294Sopenharmony_ci            matches: $matches,
3406f54294Sopenharmony_ci        }
3506f54294Sopenharmony_ci    };
3606f54294Sopenharmony_ci}
3706f54294Sopenharmony_ci
3806f54294Sopenharmony_ci/// A collection of test groups.
3906f54294Sopenharmony_citype TestCollection = &'static [&'static [SearchTest]];
4006f54294Sopenharmony_ci
4106f54294Sopenharmony_ci// Define several collections corresponding to the different type of match
4206f54294Sopenharmony_ci// semantics supported by Aho-Corasick. These collections have some overlap,
4306f54294Sopenharmony_ci// but each collection should have some tests that no other collection has.
4406f54294Sopenharmony_ci
4506f54294Sopenharmony_ci/// Tests for Aho-Corasick's standard non-overlapping match semantics.
4606f54294Sopenharmony_ciconst AC_STANDARD_NON_OVERLAPPING: TestCollection =
4706f54294Sopenharmony_ci    &[BASICS, NON_OVERLAPPING, STANDARD, REGRESSION];
4806f54294Sopenharmony_ci
4906f54294Sopenharmony_ci/// Tests for Aho-Corasick's anchored standard non-overlapping match semantics.
5006f54294Sopenharmony_ciconst AC_STANDARD_ANCHORED_NON_OVERLAPPING: TestCollection =
5106f54294Sopenharmony_ci    &[ANCHORED_BASICS, ANCHORED_NON_OVERLAPPING, STANDARD_ANCHORED];
5206f54294Sopenharmony_ci
5306f54294Sopenharmony_ci/// Tests for Aho-Corasick's standard overlapping match semantics.
5406f54294Sopenharmony_ciconst AC_STANDARD_OVERLAPPING: TestCollection =
5506f54294Sopenharmony_ci    &[BASICS, OVERLAPPING, REGRESSION];
5606f54294Sopenharmony_ci
5706f54294Sopenharmony_ci/// Tests for Aho-Corasick's anchored standard overlapping match semantics.
5806f54294Sopenharmony_ciconst AC_STANDARD_ANCHORED_OVERLAPPING: TestCollection =
5906f54294Sopenharmony_ci    &[ANCHORED_BASICS, ANCHORED_OVERLAPPING];
6006f54294Sopenharmony_ci
6106f54294Sopenharmony_ci/// Tests for Aho-Corasick's leftmost-first match semantics.
6206f54294Sopenharmony_ciconst AC_LEFTMOST_FIRST: TestCollection =
6306f54294Sopenharmony_ci    &[BASICS, NON_OVERLAPPING, LEFTMOST, LEFTMOST_FIRST, REGRESSION];
6406f54294Sopenharmony_ci
6506f54294Sopenharmony_ci/// Tests for Aho-Corasick's anchored leftmost-first match semantics.
6606f54294Sopenharmony_ciconst AC_LEFTMOST_FIRST_ANCHORED: TestCollection = &[
6706f54294Sopenharmony_ci    ANCHORED_BASICS,
6806f54294Sopenharmony_ci    ANCHORED_NON_OVERLAPPING,
6906f54294Sopenharmony_ci    ANCHORED_LEFTMOST,
7006f54294Sopenharmony_ci    ANCHORED_LEFTMOST_FIRST,
7106f54294Sopenharmony_ci];
7206f54294Sopenharmony_ci
7306f54294Sopenharmony_ci/// Tests for Aho-Corasick's leftmost-longest match semantics.
7406f54294Sopenharmony_ciconst AC_LEFTMOST_LONGEST: TestCollection =
7506f54294Sopenharmony_ci    &[BASICS, NON_OVERLAPPING, LEFTMOST, LEFTMOST_LONGEST, REGRESSION];
7606f54294Sopenharmony_ci
7706f54294Sopenharmony_ci/// Tests for Aho-Corasick's anchored leftmost-longest match semantics.
7806f54294Sopenharmony_ciconst AC_LEFTMOST_LONGEST_ANCHORED: TestCollection = &[
7906f54294Sopenharmony_ci    ANCHORED_BASICS,
8006f54294Sopenharmony_ci    ANCHORED_NON_OVERLAPPING,
8106f54294Sopenharmony_ci    ANCHORED_LEFTMOST,
8206f54294Sopenharmony_ci    ANCHORED_LEFTMOST_LONGEST,
8306f54294Sopenharmony_ci];
8406f54294Sopenharmony_ci
8506f54294Sopenharmony_ci// Now define the individual tests that make up the collections above.
8606f54294Sopenharmony_ci
8706f54294Sopenharmony_ci/// A collection of tests for the Aho-Corasick algorithm that should always be
8806f54294Sopenharmony_ci/// true regardless of match semantics. That is, all combinations of
8906f54294Sopenharmony_ci/// leftmost-{shortest, first, longest} x {overlapping, non-overlapping}
9006f54294Sopenharmony_ci/// should produce the same answer.
9106f54294Sopenharmony_ciconst BASICS: &'static [SearchTest] = &[
9206f54294Sopenharmony_ci    t!(basic000, &[], "", &[]),
9306f54294Sopenharmony_ci    t!(basic001, &["a"], "", &[]),
9406f54294Sopenharmony_ci    t!(basic010, &["a"], "a", &[(0, 0, 1)]),
9506f54294Sopenharmony_ci    t!(basic020, &["a"], "aa", &[(0, 0, 1), (0, 1, 2)]),
9606f54294Sopenharmony_ci    t!(basic030, &["a"], "aaa", &[(0, 0, 1), (0, 1, 2), (0, 2, 3)]),
9706f54294Sopenharmony_ci    t!(basic040, &["a"], "aba", &[(0, 0, 1), (0, 2, 3)]),
9806f54294Sopenharmony_ci    t!(basic050, &["a"], "bba", &[(0, 2, 3)]),
9906f54294Sopenharmony_ci    t!(basic060, &["a"], "bbb", &[]),
10006f54294Sopenharmony_ci    t!(basic070, &["a"], "bababbbba", &[(0, 1, 2), (0, 3, 4), (0, 8, 9)]),
10106f54294Sopenharmony_ci    t!(basic100, &["aa"], "", &[]),
10206f54294Sopenharmony_ci    t!(basic110, &["aa"], "aa", &[(0, 0, 2)]),
10306f54294Sopenharmony_ci    t!(basic120, &["aa"], "aabbaa", &[(0, 0, 2), (0, 4, 6)]),
10406f54294Sopenharmony_ci    t!(basic130, &["aa"], "abbab", &[]),
10506f54294Sopenharmony_ci    t!(basic140, &["aa"], "abbabaa", &[(0, 5, 7)]),
10606f54294Sopenharmony_ci    t!(basic200, &["abc"], "abc", &[(0, 0, 3)]),
10706f54294Sopenharmony_ci    t!(basic210, &["abc"], "zazabzabcz", &[(0, 6, 9)]),
10806f54294Sopenharmony_ci    t!(basic220, &["abc"], "zazabczabcz", &[(0, 3, 6), (0, 7, 10)]),
10906f54294Sopenharmony_ci    t!(basic300, &["a", "b"], "", &[]),
11006f54294Sopenharmony_ci    t!(basic310, &["a", "b"], "z", &[]),
11106f54294Sopenharmony_ci    t!(basic320, &["a", "b"], "b", &[(1, 0, 1)]),
11206f54294Sopenharmony_ci    t!(basic330, &["a", "b"], "a", &[(0, 0, 1)]),
11306f54294Sopenharmony_ci    t!(
11406f54294Sopenharmony_ci        basic340,
11506f54294Sopenharmony_ci        &["a", "b"],
11606f54294Sopenharmony_ci        "abba",
11706f54294Sopenharmony_ci        &[(0, 0, 1), (1, 1, 2), (1, 2, 3), (0, 3, 4),]
11806f54294Sopenharmony_ci    ),
11906f54294Sopenharmony_ci    t!(
12006f54294Sopenharmony_ci        basic350,
12106f54294Sopenharmony_ci        &["b", "a"],
12206f54294Sopenharmony_ci        "abba",
12306f54294Sopenharmony_ci        &[(1, 0, 1), (0, 1, 2), (0, 2, 3), (1, 3, 4),]
12406f54294Sopenharmony_ci    ),
12506f54294Sopenharmony_ci    t!(basic360, &["abc", "bc"], "xbc", &[(1, 1, 3),]),
12606f54294Sopenharmony_ci    t!(basic400, &["foo", "bar"], "", &[]),
12706f54294Sopenharmony_ci    t!(basic410, &["foo", "bar"], "foobar", &[(0, 0, 3), (1, 3, 6),]),
12806f54294Sopenharmony_ci    t!(basic420, &["foo", "bar"], "barfoo", &[(1, 0, 3), (0, 3, 6),]),
12906f54294Sopenharmony_ci    t!(basic430, &["foo", "bar"], "foofoo", &[(0, 0, 3), (0, 3, 6),]),
13006f54294Sopenharmony_ci    t!(basic440, &["foo", "bar"], "barbar", &[(1, 0, 3), (1, 3, 6),]),
13106f54294Sopenharmony_ci    t!(basic450, &["foo", "bar"], "bafofoo", &[(0, 4, 7),]),
13206f54294Sopenharmony_ci    t!(basic460, &["bar", "foo"], "bafofoo", &[(1, 4, 7),]),
13306f54294Sopenharmony_ci    t!(basic470, &["foo", "bar"], "fobabar", &[(1, 4, 7),]),
13406f54294Sopenharmony_ci    t!(basic480, &["bar", "foo"], "fobabar", &[(0, 4, 7),]),
13506f54294Sopenharmony_ci    t!(basic600, &[""], "", &[(0, 0, 0)]),
13606f54294Sopenharmony_ci    t!(basic610, &[""], "a", &[(0, 0, 0), (0, 1, 1)]),
13706f54294Sopenharmony_ci    t!(basic620, &[""], "abc", &[(0, 0, 0), (0, 1, 1), (0, 2, 2), (0, 3, 3)]),
13806f54294Sopenharmony_ci    t!(basic700, &["yabcdef", "abcdezghi"], "yabcdefghi", &[(0, 0, 7),]),
13906f54294Sopenharmony_ci    t!(basic710, &["yabcdef", "abcdezghi"], "yabcdezghi", &[(1, 1, 10),]),
14006f54294Sopenharmony_ci    t!(
14106f54294Sopenharmony_ci        basic720,
14206f54294Sopenharmony_ci        &["yabcdef", "bcdeyabc", "abcdezghi"],
14306f54294Sopenharmony_ci        "yabcdezghi",
14406f54294Sopenharmony_ci        &[(2, 1, 10),]
14506f54294Sopenharmony_ci    ),
14606f54294Sopenharmony_ci];
14706f54294Sopenharmony_ci
14806f54294Sopenharmony_ci/// A collection of *anchored* tests for the Aho-Corasick algorithm that should
14906f54294Sopenharmony_ci/// always be true regardless of match semantics. That is, all combinations of
15006f54294Sopenharmony_ci/// leftmost-{shortest, first, longest} x {overlapping, non-overlapping} should
15106f54294Sopenharmony_ci/// produce the same answer.
15206f54294Sopenharmony_ciconst ANCHORED_BASICS: &'static [SearchTest] = &[
15306f54294Sopenharmony_ci    t!(abasic000, &[], "", &[]),
15406f54294Sopenharmony_ci    t!(abasic010, &[""], "", &[(0, 0, 0)]),
15506f54294Sopenharmony_ci    t!(abasic020, &[""], "a", &[(0, 0, 0)]),
15606f54294Sopenharmony_ci    t!(abasic030, &[""], "abc", &[(0, 0, 0)]),
15706f54294Sopenharmony_ci    t!(abasic100, &["a"], "a", &[(0, 0, 1)]),
15806f54294Sopenharmony_ci    t!(abasic110, &["a"], "aa", &[(0, 0, 1)]),
15906f54294Sopenharmony_ci    t!(abasic120, &["a", "b"], "ab", &[(0, 0, 1)]),
16006f54294Sopenharmony_ci    t!(abasic130, &["a", "b"], "ba", &[(1, 0, 1)]),
16106f54294Sopenharmony_ci    t!(abasic140, &["foo", "foofoo"], "foo", &[(0, 0, 3)]),
16206f54294Sopenharmony_ci    t!(abasic150, &["foofoo", "foo"], "foo", &[(1, 0, 3)]),
16306f54294Sopenharmony_ci];
16406f54294Sopenharmony_ci
16506f54294Sopenharmony_ci/// Tests for non-overlapping standard match semantics.
16606f54294Sopenharmony_ci///
16706f54294Sopenharmony_ci/// These tests generally shouldn't pass for leftmost-{first,longest}, although
16806f54294Sopenharmony_ci/// some do in order to write clearer tests. For example, standard000 will
16906f54294Sopenharmony_ci/// pass with leftmost-first semantics, but standard010 will not. We write
17006f54294Sopenharmony_ci/// both to emphasize how the match semantics work.
17106f54294Sopenharmony_ciconst STANDARD: &'static [SearchTest] = &[
17206f54294Sopenharmony_ci    t!(standard000, &["ab", "abcd"], "abcd", &[(0, 0, 2)]),
17306f54294Sopenharmony_ci    t!(standard010, &["abcd", "ab"], "abcd", &[(1, 0, 2)]),
17406f54294Sopenharmony_ci    t!(standard020, &["abcd", "ab", "abc"], "abcd", &[(1, 0, 2)]),
17506f54294Sopenharmony_ci    t!(standard030, &["abcd", "abc", "ab"], "abcd", &[(2, 0, 2)]),
17606f54294Sopenharmony_ci    t!(standard040, &["a", ""], "a", &[(1, 0, 0), (1, 1, 1)]),
17706f54294Sopenharmony_ci    t!(
17806f54294Sopenharmony_ci        standard400,
17906f54294Sopenharmony_ci        &["abcd", "bcd", "cd", "b"],
18006f54294Sopenharmony_ci        "abcd",
18106f54294Sopenharmony_ci        &[(3, 1, 2), (2, 2, 4),]
18206f54294Sopenharmony_ci    ),
18306f54294Sopenharmony_ci    t!(standard410, &["", "a"], "a", &[(0, 0, 0), (0, 1, 1),]),
18406f54294Sopenharmony_ci    t!(standard420, &["", "a"], "aa", &[(0, 0, 0), (0, 1, 1), (0, 2, 2),]),
18506f54294Sopenharmony_ci    t!(standard430, &["", "a", ""], "a", &[(0, 0, 0), (0, 1, 1),]),
18606f54294Sopenharmony_ci    t!(standard440, &["a", "", ""], "a", &[(1, 0, 0), (1, 1, 1),]),
18706f54294Sopenharmony_ci    t!(standard450, &["", "", "a"], "a", &[(0, 0, 0), (0, 1, 1),]),
18806f54294Sopenharmony_ci];
18906f54294Sopenharmony_ci
19006f54294Sopenharmony_ci/// Like STANDARD, but for anchored searches.
19106f54294Sopenharmony_ciconst STANDARD_ANCHORED: &'static [SearchTest] = &[
19206f54294Sopenharmony_ci    t!(astandard000, &["ab", "abcd"], "abcd", &[(0, 0, 2)]),
19306f54294Sopenharmony_ci    t!(astandard010, &["abcd", "ab"], "abcd", &[(1, 0, 2)]),
19406f54294Sopenharmony_ci    t!(astandard020, &["abcd", "ab", "abc"], "abcd", &[(1, 0, 2)]),
19506f54294Sopenharmony_ci    t!(astandard030, &["abcd", "abc", "ab"], "abcd", &[(2, 0, 2)]),
19606f54294Sopenharmony_ci    t!(astandard040, &["a", ""], "a", &[(1, 0, 0)]),
19706f54294Sopenharmony_ci    t!(astandard050, &["abcd", "bcd", "cd", "b"], "abcd", &[(0, 0, 4)]),
19806f54294Sopenharmony_ci    t!(astandard410, &["", "a"], "a", &[(0, 0, 0)]),
19906f54294Sopenharmony_ci    t!(astandard420, &["", "a"], "aa", &[(0, 0, 0)]),
20006f54294Sopenharmony_ci    t!(astandard430, &["", "a", ""], "a", &[(0, 0, 0)]),
20106f54294Sopenharmony_ci    t!(astandard440, &["a", "", ""], "a", &[(1, 0, 0)]),
20206f54294Sopenharmony_ci    t!(astandard450, &["", "", "a"], "a", &[(0, 0, 0)]),
20306f54294Sopenharmony_ci];
20406f54294Sopenharmony_ci
20506f54294Sopenharmony_ci/// Tests for non-overlapping leftmost match semantics. These should pass for
20606f54294Sopenharmony_ci/// both leftmost-first and leftmost-longest match kinds. Stated differently,
20706f54294Sopenharmony_ci/// among ambiguous matches, the longest match and the match that appeared
20806f54294Sopenharmony_ci/// first when constructing the automaton should always be the same.
20906f54294Sopenharmony_ciconst LEFTMOST: &'static [SearchTest] = &[
21006f54294Sopenharmony_ci    t!(leftmost000, &["ab", "ab"], "abcd", &[(0, 0, 2)]),
21106f54294Sopenharmony_ci    t!(leftmost010, &["a", ""], "a", &[(0, 0, 1), (1, 1, 1)]),
21206f54294Sopenharmony_ci    t!(leftmost020, &["", ""], "a", &[(0, 0, 0), (0, 1, 1)]),
21306f54294Sopenharmony_ci    t!(leftmost030, &["a", "ab"], "aa", &[(0, 0, 1), (0, 1, 2)]),
21406f54294Sopenharmony_ci    t!(leftmost031, &["ab", "a"], "aa", &[(1, 0, 1), (1, 1, 2)]),
21506f54294Sopenharmony_ci    t!(leftmost032, &["ab", "a"], "xayabbbz", &[(1, 1, 2), (0, 3, 5)]),
21606f54294Sopenharmony_ci    t!(leftmost300, &["abcd", "bce", "b"], "abce", &[(1, 1, 4)]),
21706f54294Sopenharmony_ci    t!(leftmost310, &["abcd", "ce", "bc"], "abce", &[(2, 1, 3)]),
21806f54294Sopenharmony_ci    t!(leftmost320, &["abcd", "bce", "ce", "b"], "abce", &[(1, 1, 4)]),
21906f54294Sopenharmony_ci    t!(leftmost330, &["abcd", "bce", "cz", "bc"], "abcz", &[(3, 1, 3)]),
22006f54294Sopenharmony_ci    t!(leftmost340, &["bce", "cz", "bc"], "bcz", &[(2, 0, 2)]),
22106f54294Sopenharmony_ci    t!(leftmost350, &["abc", "bd", "ab"], "abd", &[(2, 0, 2)]),
22206f54294Sopenharmony_ci    t!(
22306f54294Sopenharmony_ci        leftmost360,
22406f54294Sopenharmony_ci        &["abcdefghi", "hz", "abcdefgh"],
22506f54294Sopenharmony_ci        "abcdefghz",
22606f54294Sopenharmony_ci        &[(2, 0, 8),]
22706f54294Sopenharmony_ci    ),
22806f54294Sopenharmony_ci    t!(
22906f54294Sopenharmony_ci        leftmost370,
23006f54294Sopenharmony_ci        &["abcdefghi", "cde", "hz", "abcdefgh"],
23106f54294Sopenharmony_ci        "abcdefghz",
23206f54294Sopenharmony_ci        &[(3, 0, 8),]
23306f54294Sopenharmony_ci    ),
23406f54294Sopenharmony_ci    t!(
23506f54294Sopenharmony_ci        leftmost380,
23606f54294Sopenharmony_ci        &["abcdefghi", "hz", "abcdefgh", "a"],
23706f54294Sopenharmony_ci        "abcdefghz",
23806f54294Sopenharmony_ci        &[(2, 0, 8),]
23906f54294Sopenharmony_ci    ),
24006f54294Sopenharmony_ci    t!(
24106f54294Sopenharmony_ci        leftmost390,
24206f54294Sopenharmony_ci        &["b", "abcdefghi", "hz", "abcdefgh"],
24306f54294Sopenharmony_ci        "abcdefghz",
24406f54294Sopenharmony_ci        &[(3, 0, 8),]
24506f54294Sopenharmony_ci    ),
24606f54294Sopenharmony_ci    t!(
24706f54294Sopenharmony_ci        leftmost400,
24806f54294Sopenharmony_ci        &["h", "abcdefghi", "hz", "abcdefgh"],
24906f54294Sopenharmony_ci        "abcdefghz",
25006f54294Sopenharmony_ci        &[(3, 0, 8),]
25106f54294Sopenharmony_ci    ),
25206f54294Sopenharmony_ci    t!(
25306f54294Sopenharmony_ci        leftmost410,
25406f54294Sopenharmony_ci        &["z", "abcdefghi", "hz", "abcdefgh"],
25506f54294Sopenharmony_ci        "abcdefghz",
25606f54294Sopenharmony_ci        &[(3, 0, 8), (0, 8, 9),]
25706f54294Sopenharmony_ci    ),
25806f54294Sopenharmony_ci];
25906f54294Sopenharmony_ci
26006f54294Sopenharmony_ci/// Like LEFTMOST, but for anchored searches.
26106f54294Sopenharmony_ciconst ANCHORED_LEFTMOST: &'static [SearchTest] = &[
26206f54294Sopenharmony_ci    t!(aleftmost000, &["ab", "ab"], "abcd", &[(0, 0, 2)]),
26306f54294Sopenharmony_ci    t!(aleftmost010, &["a", ""], "a", &[(0, 0, 1)]),
26406f54294Sopenharmony_ci    t!(aleftmost020, &["", ""], "a", &[(0, 0, 0)]),
26506f54294Sopenharmony_ci    t!(aleftmost030, &["a", "ab"], "aa", &[(0, 0, 1)]),
26606f54294Sopenharmony_ci    t!(aleftmost031, &["ab", "a"], "aa", &[(1, 0, 1)]),
26706f54294Sopenharmony_ci    t!(aleftmost032, &["ab", "a"], "xayabbbz", &[]),
26806f54294Sopenharmony_ci    t!(aleftmost300, &["abcd", "bce", "b"], "abce", &[]),
26906f54294Sopenharmony_ci    t!(aleftmost310, &["abcd", "ce", "bc"], "abce", &[]),
27006f54294Sopenharmony_ci    t!(aleftmost320, &["abcd", "bce", "ce", "b"], "abce", &[]),
27106f54294Sopenharmony_ci    t!(aleftmost330, &["abcd", "bce", "cz", "bc"], "abcz", &[]),
27206f54294Sopenharmony_ci    t!(aleftmost340, &["bce", "cz", "bc"], "bcz", &[(2, 0, 2)]),
27306f54294Sopenharmony_ci    t!(aleftmost350, &["abc", "bd", "ab"], "abd", &[(2, 0, 2)]),
27406f54294Sopenharmony_ci    t!(
27506f54294Sopenharmony_ci        aleftmost360,
27606f54294Sopenharmony_ci        &["abcdefghi", "hz", "abcdefgh"],
27706f54294Sopenharmony_ci        "abcdefghz",
27806f54294Sopenharmony_ci        &[(2, 0, 8),]
27906f54294Sopenharmony_ci    ),
28006f54294Sopenharmony_ci    t!(
28106f54294Sopenharmony_ci        aleftmost370,
28206f54294Sopenharmony_ci        &["abcdefghi", "cde", "hz", "abcdefgh"],
28306f54294Sopenharmony_ci        "abcdefghz",
28406f54294Sopenharmony_ci        &[(3, 0, 8),]
28506f54294Sopenharmony_ci    ),
28606f54294Sopenharmony_ci    t!(
28706f54294Sopenharmony_ci        aleftmost380,
28806f54294Sopenharmony_ci        &["abcdefghi", "hz", "abcdefgh", "a"],
28906f54294Sopenharmony_ci        "abcdefghz",
29006f54294Sopenharmony_ci        &[(2, 0, 8),]
29106f54294Sopenharmony_ci    ),
29206f54294Sopenharmony_ci    t!(
29306f54294Sopenharmony_ci        aleftmost390,
29406f54294Sopenharmony_ci        &["b", "abcdefghi", "hz", "abcdefgh"],
29506f54294Sopenharmony_ci        "abcdefghz",
29606f54294Sopenharmony_ci        &[(3, 0, 8),]
29706f54294Sopenharmony_ci    ),
29806f54294Sopenharmony_ci    t!(
29906f54294Sopenharmony_ci        aleftmost400,
30006f54294Sopenharmony_ci        &["h", "abcdefghi", "hz", "abcdefgh"],
30106f54294Sopenharmony_ci        "abcdefghz",
30206f54294Sopenharmony_ci        &[(3, 0, 8),]
30306f54294Sopenharmony_ci    ),
30406f54294Sopenharmony_ci    t!(
30506f54294Sopenharmony_ci        aleftmost410,
30606f54294Sopenharmony_ci        &["z", "abcdefghi", "hz", "abcdefgh"],
30706f54294Sopenharmony_ci        "abcdefghz",
30806f54294Sopenharmony_ci        &[(3, 0, 8)]
30906f54294Sopenharmony_ci    ),
31006f54294Sopenharmony_ci];
31106f54294Sopenharmony_ci
31206f54294Sopenharmony_ci/// Tests for non-overlapping leftmost-first match semantics. These tests
31306f54294Sopenharmony_ci/// should generally be specific to leftmost-first, which means they should
31406f54294Sopenharmony_ci/// generally fail under leftmost-longest semantics.
31506f54294Sopenharmony_ciconst LEFTMOST_FIRST: &'static [SearchTest] = &[
31606f54294Sopenharmony_ci    t!(leftfirst000, &["ab", "abcd"], "abcd", &[(0, 0, 2)]),
31706f54294Sopenharmony_ci    t!(leftfirst010, &["", "a"], "a", &[(0, 0, 0), (0, 1, 1)]),
31806f54294Sopenharmony_ci    t!(leftfirst011, &["", "a", ""], "a", &[(0, 0, 0), (0, 1, 1),]),
31906f54294Sopenharmony_ci    t!(leftfirst012, &["a", "", ""], "a", &[(0, 0, 1), (1, 1, 1),]),
32006f54294Sopenharmony_ci    t!(leftfirst013, &["", "", "a"], "a", &[(0, 0, 0), (0, 1, 1),]),
32106f54294Sopenharmony_ci    t!(leftfirst020, &["abcd", "ab"], "abcd", &[(0, 0, 4)]),
32206f54294Sopenharmony_ci    t!(leftfirst030, &["ab", "ab"], "abcd", &[(0, 0, 2)]),
32306f54294Sopenharmony_ci    t!(leftfirst040, &["a", "ab"], "xayabbbz", &[(0, 1, 2), (0, 3, 4)]),
32406f54294Sopenharmony_ci    t!(leftfirst100, &["abcdefg", "bcde", "bcdef"], "abcdef", &[(1, 1, 5)]),
32506f54294Sopenharmony_ci    t!(leftfirst110, &["abcdefg", "bcdef", "bcde"], "abcdef", &[(1, 1, 6)]),
32606f54294Sopenharmony_ci    t!(leftfirst300, &["abcd", "b", "bce"], "abce", &[(1, 1, 2)]),
32706f54294Sopenharmony_ci    t!(
32806f54294Sopenharmony_ci        leftfirst310,
32906f54294Sopenharmony_ci        &["abcd", "b", "bce", "ce"],
33006f54294Sopenharmony_ci        "abce",
33106f54294Sopenharmony_ci        &[(1, 1, 2), (3, 2, 4),]
33206f54294Sopenharmony_ci    ),
33306f54294Sopenharmony_ci    t!(
33406f54294Sopenharmony_ci        leftfirst320,
33506f54294Sopenharmony_ci        &["a", "abcdefghi", "hz", "abcdefgh"],
33606f54294Sopenharmony_ci        "abcdefghz",
33706f54294Sopenharmony_ci        &[(0, 0, 1), (2, 7, 9),]
33806f54294Sopenharmony_ci    ),
33906f54294Sopenharmony_ci    t!(leftfirst330, &["a", "abab"], "abab", &[(0, 0, 1), (0, 2, 3)]),
34006f54294Sopenharmony_ci    t!(leftfirst400, &["amwix", "samwise", "sam"], "Zsamwix", &[(2, 1, 4)]),
34106f54294Sopenharmony_ci];
34206f54294Sopenharmony_ci
34306f54294Sopenharmony_ci/// Like LEFTMOST_FIRST, but for anchored searches.
34406f54294Sopenharmony_ciconst ANCHORED_LEFTMOST_FIRST: &'static [SearchTest] = &[
34506f54294Sopenharmony_ci    t!(aleftfirst000, &["ab", "abcd"], "abcd", &[(0, 0, 2)]),
34606f54294Sopenharmony_ci    t!(aleftfirst010, &["", "a"], "a", &[(0, 0, 0)]),
34706f54294Sopenharmony_ci    t!(aleftfirst011, &["", "a", ""], "a", &[(0, 0, 0)]),
34806f54294Sopenharmony_ci    t!(aleftfirst012, &["a", "", ""], "a", &[(0, 0, 1)]),
34906f54294Sopenharmony_ci    t!(aleftfirst013, &["", "", "a"], "a", &[(0, 0, 0)]),
35006f54294Sopenharmony_ci    t!(aleftfirst020, &["abcd", "ab"], "abcd", &[(0, 0, 4)]),
35106f54294Sopenharmony_ci    t!(aleftfirst030, &["ab", "ab"], "abcd", &[(0, 0, 2)]),
35206f54294Sopenharmony_ci    t!(aleftfirst040, &["a", "ab"], "xayabbbz", &[]),
35306f54294Sopenharmony_ci    t!(aleftfirst100, &["abcdefg", "bcde", "bcdef"], "abcdef", &[]),
35406f54294Sopenharmony_ci    t!(aleftfirst110, &["abcdefg", "bcdef", "bcde"], "abcdef", &[]),
35506f54294Sopenharmony_ci    t!(aleftfirst300, &["abcd", "b", "bce"], "abce", &[]),
35606f54294Sopenharmony_ci    t!(aleftfirst310, &["abcd", "b", "bce", "ce"], "abce", &[]),
35706f54294Sopenharmony_ci    t!(
35806f54294Sopenharmony_ci        aleftfirst320,
35906f54294Sopenharmony_ci        &["a", "abcdefghi", "hz", "abcdefgh"],
36006f54294Sopenharmony_ci        "abcdefghz",
36106f54294Sopenharmony_ci        &[(0, 0, 1)]
36206f54294Sopenharmony_ci    ),
36306f54294Sopenharmony_ci    t!(aleftfirst330, &["a", "abab"], "abab", &[(0, 0, 1)]),
36406f54294Sopenharmony_ci    t!(aleftfirst400, &["wise", "samwise", "sam"], "samwix", &[(2, 0, 3)]),
36506f54294Sopenharmony_ci];
36606f54294Sopenharmony_ci
36706f54294Sopenharmony_ci/// Tests for non-overlapping leftmost-longest match semantics. These tests
36806f54294Sopenharmony_ci/// should generally be specific to leftmost-longest, which means they should
36906f54294Sopenharmony_ci/// generally fail under leftmost-first semantics.
37006f54294Sopenharmony_ciconst LEFTMOST_LONGEST: &'static [SearchTest] = &[
37106f54294Sopenharmony_ci    t!(leftlong000, &["ab", "abcd"], "abcd", &[(1, 0, 4)]),
37206f54294Sopenharmony_ci    t!(leftlong010, &["abcd", "bcd", "cd", "b"], "abcd", &[(0, 0, 4),]),
37306f54294Sopenharmony_ci    t!(leftlong020, &["", "a"], "a", &[(1, 0, 1), (0, 1, 1),]),
37406f54294Sopenharmony_ci    t!(leftlong021, &["", "a", ""], "a", &[(1, 0, 1), (0, 1, 1),]),
37506f54294Sopenharmony_ci    t!(leftlong022, &["a", "", ""], "a", &[(0, 0, 1), (1, 1, 1),]),
37606f54294Sopenharmony_ci    t!(leftlong023, &["", "", "a"], "a", &[(2, 0, 1), (0, 1, 1),]),
37706f54294Sopenharmony_ci    t!(leftlong030, &["", "a"], "aa", &[(1, 0, 1), (1, 1, 2), (0, 2, 2),]),
37806f54294Sopenharmony_ci    t!(leftlong040, &["a", "ab"], "a", &[(0, 0, 1)]),
37906f54294Sopenharmony_ci    t!(leftlong050, &["a", "ab"], "ab", &[(1, 0, 2)]),
38006f54294Sopenharmony_ci    t!(leftlong060, &["ab", "a"], "a", &[(1, 0, 1)]),
38106f54294Sopenharmony_ci    t!(leftlong070, &["ab", "a"], "ab", &[(0, 0, 2)]),
38206f54294Sopenharmony_ci    t!(leftlong100, &["abcdefg", "bcde", "bcdef"], "abcdef", &[(2, 1, 6)]),
38306f54294Sopenharmony_ci    t!(leftlong110, &["abcdefg", "bcdef", "bcde"], "abcdef", &[(1, 1, 6)]),
38406f54294Sopenharmony_ci    t!(leftlong300, &["abcd", "b", "bce"], "abce", &[(2, 1, 4)]),
38506f54294Sopenharmony_ci    t!(
38606f54294Sopenharmony_ci        leftlong310,
38706f54294Sopenharmony_ci        &["a", "abcdefghi", "hz", "abcdefgh"],
38806f54294Sopenharmony_ci        "abcdefghz",
38906f54294Sopenharmony_ci        &[(3, 0, 8),]
39006f54294Sopenharmony_ci    ),
39106f54294Sopenharmony_ci    t!(leftlong320, &["a", "abab"], "abab", &[(1, 0, 4)]),
39206f54294Sopenharmony_ci    t!(leftlong330, &["abcd", "b", "ce"], "abce", &[(1, 1, 2), (2, 2, 4),]),
39306f54294Sopenharmony_ci    t!(leftlong340, &["a", "ab"], "xayabbbz", &[(0, 1, 2), (1, 3, 5)]),
39406f54294Sopenharmony_ci];
39506f54294Sopenharmony_ci
39606f54294Sopenharmony_ci/// Like LEFTMOST_LONGEST, but for anchored searches.
39706f54294Sopenharmony_ciconst ANCHORED_LEFTMOST_LONGEST: &'static [SearchTest] = &[
39806f54294Sopenharmony_ci    t!(aleftlong000, &["ab", "abcd"], "abcd", &[(1, 0, 4)]),
39906f54294Sopenharmony_ci    t!(aleftlong010, &["abcd", "bcd", "cd", "b"], "abcd", &[(0, 0, 4),]),
40006f54294Sopenharmony_ci    t!(aleftlong020, &["", "a"], "a", &[(1, 0, 1)]),
40106f54294Sopenharmony_ci    t!(aleftlong021, &["", "a", ""], "a", &[(1, 0, 1)]),
40206f54294Sopenharmony_ci    t!(aleftlong022, &["a", "", ""], "a", &[(0, 0, 1)]),
40306f54294Sopenharmony_ci    t!(aleftlong023, &["", "", "a"], "a", &[(2, 0, 1)]),
40406f54294Sopenharmony_ci    t!(aleftlong030, &["", "a"], "aa", &[(1, 0, 1)]),
40506f54294Sopenharmony_ci    t!(aleftlong040, &["a", "ab"], "a", &[(0, 0, 1)]),
40606f54294Sopenharmony_ci    t!(aleftlong050, &["a", "ab"], "ab", &[(1, 0, 2)]),
40706f54294Sopenharmony_ci    t!(aleftlong060, &["ab", "a"], "a", &[(1, 0, 1)]),
40806f54294Sopenharmony_ci    t!(aleftlong070, &["ab", "a"], "ab", &[(0, 0, 2)]),
40906f54294Sopenharmony_ci    t!(aleftlong100, &["abcdefg", "bcde", "bcdef"], "abcdef", &[]),
41006f54294Sopenharmony_ci    t!(aleftlong110, &["abcdefg", "bcdef", "bcde"], "abcdef", &[]),
41106f54294Sopenharmony_ci    t!(aleftlong300, &["abcd", "b", "bce"], "abce", &[]),
41206f54294Sopenharmony_ci    t!(
41306f54294Sopenharmony_ci        aleftlong310,
41406f54294Sopenharmony_ci        &["a", "abcdefghi", "hz", "abcdefgh"],
41506f54294Sopenharmony_ci        "abcdefghz",
41606f54294Sopenharmony_ci        &[(3, 0, 8),]
41706f54294Sopenharmony_ci    ),
41806f54294Sopenharmony_ci    t!(aleftlong320, &["a", "abab"], "abab", &[(1, 0, 4)]),
41906f54294Sopenharmony_ci    t!(aleftlong330, &["abcd", "b", "ce"], "abce", &[]),
42006f54294Sopenharmony_ci    t!(aleftlong340, &["a", "ab"], "xayabbbz", &[]),
42106f54294Sopenharmony_ci];
42206f54294Sopenharmony_ci
42306f54294Sopenharmony_ci/// Tests for non-overlapping match semantics.
42406f54294Sopenharmony_ci///
42506f54294Sopenharmony_ci/// Generally these tests shouldn't pass when using overlapping semantics.
42606f54294Sopenharmony_ci/// These should pass for both standard and leftmost match semantics.
42706f54294Sopenharmony_ciconst NON_OVERLAPPING: &'static [SearchTest] = &[
42806f54294Sopenharmony_ci    t!(nover010, &["abcd", "bcd", "cd"], "abcd", &[(0, 0, 4),]),
42906f54294Sopenharmony_ci    t!(nover020, &["bcd", "cd", "abcd"], "abcd", &[(2, 0, 4),]),
43006f54294Sopenharmony_ci    t!(nover030, &["abc", "bc"], "zazabcz", &[(0, 3, 6),]),
43106f54294Sopenharmony_ci    t!(
43206f54294Sopenharmony_ci        nover100,
43306f54294Sopenharmony_ci        &["ab", "ba"],
43406f54294Sopenharmony_ci        "abababa",
43506f54294Sopenharmony_ci        &[(0, 0, 2), (0, 2, 4), (0, 4, 6),]
43606f54294Sopenharmony_ci    ),
43706f54294Sopenharmony_ci    t!(nover200, &["foo", "foo"], "foobarfoo", &[(0, 0, 3), (0, 6, 9),]),
43806f54294Sopenharmony_ci    t!(nover300, &["", ""], "", &[(0, 0, 0),]),
43906f54294Sopenharmony_ci    t!(nover310, &["", ""], "a", &[(0, 0, 0), (0, 1, 1),]),
44006f54294Sopenharmony_ci];
44106f54294Sopenharmony_ci
44206f54294Sopenharmony_ci/// Like NON_OVERLAPPING, but for anchored searches.
44306f54294Sopenharmony_ciconst ANCHORED_NON_OVERLAPPING: &'static [SearchTest] = &[
44406f54294Sopenharmony_ci    t!(anover010, &["abcd", "bcd", "cd"], "abcd", &[(0, 0, 4),]),
44506f54294Sopenharmony_ci    t!(anover020, &["bcd", "cd", "abcd"], "abcd", &[(2, 0, 4),]),
44606f54294Sopenharmony_ci    t!(anover030, &["abc", "bc"], "zazabcz", &[]),
44706f54294Sopenharmony_ci    t!(anover100, &["ab", "ba"], "abababa", &[(0, 0, 2)]),
44806f54294Sopenharmony_ci    t!(anover200, &["foo", "foo"], "foobarfoo", &[(0, 0, 3)]),
44906f54294Sopenharmony_ci    t!(anover300, &["", ""], "", &[(0, 0, 0),]),
45006f54294Sopenharmony_ci    t!(anover310, &["", ""], "a", &[(0, 0, 0)]),
45106f54294Sopenharmony_ci];
45206f54294Sopenharmony_ci
45306f54294Sopenharmony_ci/// Tests for overlapping match semantics.
45406f54294Sopenharmony_ci///
45506f54294Sopenharmony_ci/// This only supports standard match semantics, since leftmost-{first,longest}
45606f54294Sopenharmony_ci/// do not support overlapping matches.
45706f54294Sopenharmony_ciconst OVERLAPPING: &'static [SearchTest] = &[
45806f54294Sopenharmony_ci    t!(
45906f54294Sopenharmony_ci        over000,
46006f54294Sopenharmony_ci        &["abcd", "bcd", "cd", "b"],
46106f54294Sopenharmony_ci        "abcd",
46206f54294Sopenharmony_ci        &[(3, 1, 2), (0, 0, 4), (1, 1, 4), (2, 2, 4),]
46306f54294Sopenharmony_ci    ),
46406f54294Sopenharmony_ci    t!(
46506f54294Sopenharmony_ci        over010,
46606f54294Sopenharmony_ci        &["bcd", "cd", "b", "abcd"],
46706f54294Sopenharmony_ci        "abcd",
46806f54294Sopenharmony_ci        &[(2, 1, 2), (3, 0, 4), (0, 1, 4), (1, 2, 4),]
46906f54294Sopenharmony_ci    ),
47006f54294Sopenharmony_ci    t!(
47106f54294Sopenharmony_ci        over020,
47206f54294Sopenharmony_ci        &["abcd", "bcd", "cd"],
47306f54294Sopenharmony_ci        "abcd",
47406f54294Sopenharmony_ci        &[(0, 0, 4), (1, 1, 4), (2, 2, 4),]
47506f54294Sopenharmony_ci    ),
47606f54294Sopenharmony_ci    t!(
47706f54294Sopenharmony_ci        over030,
47806f54294Sopenharmony_ci        &["bcd", "abcd", "cd"],
47906f54294Sopenharmony_ci        "abcd",
48006f54294Sopenharmony_ci        &[(1, 0, 4), (0, 1, 4), (2, 2, 4),]
48106f54294Sopenharmony_ci    ),
48206f54294Sopenharmony_ci    t!(
48306f54294Sopenharmony_ci        over040,
48406f54294Sopenharmony_ci        &["bcd", "cd", "abcd"],
48506f54294Sopenharmony_ci        "abcd",
48606f54294Sopenharmony_ci        &[(2, 0, 4), (0, 1, 4), (1, 2, 4),]
48706f54294Sopenharmony_ci    ),
48806f54294Sopenharmony_ci    t!(over050, &["abc", "bc"], "zazabcz", &[(0, 3, 6), (1, 4, 6),]),
48906f54294Sopenharmony_ci    t!(
49006f54294Sopenharmony_ci        over100,
49106f54294Sopenharmony_ci        &["ab", "ba"],
49206f54294Sopenharmony_ci        "abababa",
49306f54294Sopenharmony_ci        &[(0, 0, 2), (1, 1, 3), (0, 2, 4), (1, 3, 5), (0, 4, 6), (1, 5, 7),]
49406f54294Sopenharmony_ci    ),
49506f54294Sopenharmony_ci    t!(
49606f54294Sopenharmony_ci        over200,
49706f54294Sopenharmony_ci        &["foo", "foo"],
49806f54294Sopenharmony_ci        "foobarfoo",
49906f54294Sopenharmony_ci        &[(0, 0, 3), (1, 0, 3), (0, 6, 9), (1, 6, 9),]
50006f54294Sopenharmony_ci    ),
50106f54294Sopenharmony_ci    t!(over300, &["", ""], "", &[(0, 0, 0), (1, 0, 0),]),
50206f54294Sopenharmony_ci    t!(
50306f54294Sopenharmony_ci        over310,
50406f54294Sopenharmony_ci        &["", ""],
50506f54294Sopenharmony_ci        "a",
50606f54294Sopenharmony_ci        &[(0, 0, 0), (1, 0, 0), (0, 1, 1), (1, 1, 1),]
50706f54294Sopenharmony_ci    ),
50806f54294Sopenharmony_ci    t!(over320, &["", "a"], "a", &[(0, 0, 0), (1, 0, 1), (0, 1, 1),]),
50906f54294Sopenharmony_ci    t!(
51006f54294Sopenharmony_ci        over330,
51106f54294Sopenharmony_ci        &["", "a", ""],
51206f54294Sopenharmony_ci        "a",
51306f54294Sopenharmony_ci        &[(0, 0, 0), (2, 0, 0), (1, 0, 1), (0, 1, 1), (2, 1, 1),]
51406f54294Sopenharmony_ci    ),
51506f54294Sopenharmony_ci    t!(
51606f54294Sopenharmony_ci        over340,
51706f54294Sopenharmony_ci        &["a", "", ""],
51806f54294Sopenharmony_ci        "a",
51906f54294Sopenharmony_ci        &[(1, 0, 0), (2, 0, 0), (0, 0, 1), (1, 1, 1), (2, 1, 1),]
52006f54294Sopenharmony_ci    ),
52106f54294Sopenharmony_ci    t!(
52206f54294Sopenharmony_ci        over350,
52306f54294Sopenharmony_ci        &["", "", "a"],
52406f54294Sopenharmony_ci        "a",
52506f54294Sopenharmony_ci        &[(0, 0, 0), (1, 0, 0), (2, 0, 1), (0, 1, 1), (1, 1, 1),]
52606f54294Sopenharmony_ci    ),
52706f54294Sopenharmony_ci    t!(
52806f54294Sopenharmony_ci        over360,
52906f54294Sopenharmony_ci        &["foo", "foofoo"],
53006f54294Sopenharmony_ci        "foofoo",
53106f54294Sopenharmony_ci        &[(0, 0, 3), (1, 0, 6), (0, 3, 6)]
53206f54294Sopenharmony_ci    ),
53306f54294Sopenharmony_ci];
53406f54294Sopenharmony_ci
53506f54294Sopenharmony_ci/// Like OVERLAPPING, but for anchored searches.
53606f54294Sopenharmony_ciconst ANCHORED_OVERLAPPING: &'static [SearchTest] = &[
53706f54294Sopenharmony_ci    t!(aover000, &["abcd", "bcd", "cd", "b"], "abcd", &[(0, 0, 4)]),
53806f54294Sopenharmony_ci    t!(aover010, &["bcd", "cd", "b", "abcd"], "abcd", &[(3, 0, 4)]),
53906f54294Sopenharmony_ci    t!(aover020, &["abcd", "bcd", "cd"], "abcd", &[(0, 0, 4)]),
54006f54294Sopenharmony_ci    t!(aover030, &["bcd", "abcd", "cd"], "abcd", &[(1, 0, 4)]),
54106f54294Sopenharmony_ci    t!(aover040, &["bcd", "cd", "abcd"], "abcd", &[(2, 0, 4)]),
54206f54294Sopenharmony_ci    t!(aover050, &["abc", "bc"], "zazabcz", &[]),
54306f54294Sopenharmony_ci    t!(aover100, &["ab", "ba"], "abababa", &[(0, 0, 2)]),
54406f54294Sopenharmony_ci    t!(aover200, &["foo", "foo"], "foobarfoo", &[(0, 0, 3), (1, 0, 3)]),
54506f54294Sopenharmony_ci    t!(aover300, &["", ""], "", &[(0, 0, 0), (1, 0, 0),]),
54606f54294Sopenharmony_ci    t!(aover310, &["", ""], "a", &[(0, 0, 0), (1, 0, 0)]),
54706f54294Sopenharmony_ci    t!(aover320, &["", "a"], "a", &[(0, 0, 0), (1, 0, 1)]),
54806f54294Sopenharmony_ci    t!(aover330, &["", "a", ""], "a", &[(0, 0, 0), (2, 0, 0), (1, 0, 1)]),
54906f54294Sopenharmony_ci    t!(aover340, &["a", "", ""], "a", &[(1, 0, 0), (2, 0, 0), (0, 0, 1)]),
55006f54294Sopenharmony_ci    t!(aover350, &["", "", "a"], "a", &[(0, 0, 0), (1, 0, 0), (2, 0, 1)]),
55106f54294Sopenharmony_ci    t!(aover360, &["foo", "foofoo"], "foofoo", &[(0, 0, 3), (1, 0, 6)]),
55206f54294Sopenharmony_ci];
55306f54294Sopenharmony_ci
55406f54294Sopenharmony_ci/// Tests for ASCII case insensitivity.
55506f54294Sopenharmony_ci///
55606f54294Sopenharmony_ci/// These tests should all have the same behavior regardless of match semantics
55706f54294Sopenharmony_ci/// or whether the search is overlapping.
55806f54294Sopenharmony_ciconst ASCII_CASE_INSENSITIVE: &'static [SearchTest] = &[
55906f54294Sopenharmony_ci    t!(acasei000, &["a"], "A", &[(0, 0, 1)]),
56006f54294Sopenharmony_ci    t!(acasei010, &["Samwise"], "SAMWISE", &[(0, 0, 7)]),
56106f54294Sopenharmony_ci    t!(acasei011, &["Samwise"], "SAMWISE.abcd", &[(0, 0, 7)]),
56206f54294Sopenharmony_ci    t!(acasei020, &["fOoBaR"], "quux foobar baz", &[(0, 5, 11)]),
56306f54294Sopenharmony_ci];
56406f54294Sopenharmony_ci
56506f54294Sopenharmony_ci/// Like ASCII_CASE_INSENSITIVE, but specifically for non-overlapping tests.
56606f54294Sopenharmony_ciconst ASCII_CASE_INSENSITIVE_NON_OVERLAPPING: &'static [SearchTest] = &[
56706f54294Sopenharmony_ci    t!(acasei000, &["foo", "FOO"], "fOo", &[(0, 0, 3)]),
56806f54294Sopenharmony_ci    t!(acasei000, &["FOO", "foo"], "fOo", &[(0, 0, 3)]),
56906f54294Sopenharmony_ci    t!(acasei010, &["abc", "def"], "abcdef", &[(0, 0, 3), (1, 3, 6)]),
57006f54294Sopenharmony_ci];
57106f54294Sopenharmony_ci
57206f54294Sopenharmony_ci/// Like ASCII_CASE_INSENSITIVE, but specifically for overlapping tests.
57306f54294Sopenharmony_ciconst ASCII_CASE_INSENSITIVE_OVERLAPPING: &'static [SearchTest] = &[
57406f54294Sopenharmony_ci    t!(acasei000, &["foo", "FOO"], "fOo", &[(0, 0, 3), (1, 0, 3)]),
57506f54294Sopenharmony_ci    t!(acasei001, &["FOO", "foo"], "fOo", &[(0, 0, 3), (1, 0, 3)]),
57606f54294Sopenharmony_ci    // This is a regression test from:
57706f54294Sopenharmony_ci    // https://github.com/BurntSushi/aho-corasick/issues/68
57806f54294Sopenharmony_ci    // Previously, it was reporting a duplicate (1, 3, 6) match.
57906f54294Sopenharmony_ci    t!(
58006f54294Sopenharmony_ci        acasei010,
58106f54294Sopenharmony_ci        &["abc", "def", "abcdef"],
58206f54294Sopenharmony_ci        "abcdef",
58306f54294Sopenharmony_ci        &[(0, 0, 3), (2, 0, 6), (1, 3, 6)]
58406f54294Sopenharmony_ci    ),
58506f54294Sopenharmony_ci];
58606f54294Sopenharmony_ci
58706f54294Sopenharmony_ci/// Regression tests that are applied to all Aho-Corasick combinations.
58806f54294Sopenharmony_ci///
58906f54294Sopenharmony_ci/// If regression tests are needed for specific match semantics, then add them
59006f54294Sopenharmony_ci/// to the appropriate group above.
59106f54294Sopenharmony_ciconst REGRESSION: &'static [SearchTest] = &[
59206f54294Sopenharmony_ci    t!(regression010, &["inf", "ind"], "infind", &[(0, 0, 3), (1, 3, 6),]),
59306f54294Sopenharmony_ci    t!(regression020, &["ind", "inf"], "infind", &[(1, 0, 3), (0, 3, 6),]),
59406f54294Sopenharmony_ci    t!(
59506f54294Sopenharmony_ci        regression030,
59606f54294Sopenharmony_ci        &["libcore/", "libstd/"],
59706f54294Sopenharmony_ci        "libcore/char/methods.rs",
59806f54294Sopenharmony_ci        &[(0, 0, 8),]
59906f54294Sopenharmony_ci    ),
60006f54294Sopenharmony_ci    t!(
60106f54294Sopenharmony_ci        regression040,
60206f54294Sopenharmony_ci        &["libstd/", "libcore/"],
60306f54294Sopenharmony_ci        "libcore/char/methods.rs",
60406f54294Sopenharmony_ci        &[(1, 0, 8),]
60506f54294Sopenharmony_ci    ),
60606f54294Sopenharmony_ci    t!(
60706f54294Sopenharmony_ci        regression050,
60806f54294Sopenharmony_ci        &["\x00\x00\x01", "\x00\x00\x00"],
60906f54294Sopenharmony_ci        "\x00\x00\x00",
61006f54294Sopenharmony_ci        &[(1, 0, 3),]
61106f54294Sopenharmony_ci    ),
61206f54294Sopenharmony_ci    t!(
61306f54294Sopenharmony_ci        regression060,
61406f54294Sopenharmony_ci        &["\x00\x00\x00", "\x00\x00\x01"],
61506f54294Sopenharmony_ci        "\x00\x00\x00",
61606f54294Sopenharmony_ci        &[(0, 0, 3),]
61706f54294Sopenharmony_ci    ),
61806f54294Sopenharmony_ci];
61906f54294Sopenharmony_ci
62006f54294Sopenharmony_ci// Now define a test for each combination of things above that we want to run.
62106f54294Sopenharmony_ci// Since there are a few different combinations for each collection of tests,
62206f54294Sopenharmony_ci// we define a couple of macros to avoid repetition drudgery. The testconfig
62306f54294Sopenharmony_ci// macro constructs the automaton from a given match kind, and runs the search
62406f54294Sopenharmony_ci// tests one-by-one over the given collection. The `with` parameter allows one
62506f54294Sopenharmony_ci// to configure the builder with additional parameters. The testcombo macro
62606f54294Sopenharmony_ci// invokes testconfig in precisely this way: it sets up several tests where
62706f54294Sopenharmony_ci// each one turns a different knob on AhoCorasickBuilder.
62806f54294Sopenharmony_ci
62906f54294Sopenharmony_cimacro_rules! testconfig {
63006f54294Sopenharmony_ci    (overlapping, $name:ident, $collection:expr, $kind:ident, $with:expr) => {
63106f54294Sopenharmony_ci        #[test]
63206f54294Sopenharmony_ci        fn $name() {
63306f54294Sopenharmony_ci            run_search_tests($collection, |test| {
63406f54294Sopenharmony_ci                let mut builder = AhoCorasickBuilder::new();
63506f54294Sopenharmony_ci                $with(&mut builder);
63606f54294Sopenharmony_ci                builder
63706f54294Sopenharmony_ci                    .match_kind(MatchKind::$kind)
63806f54294Sopenharmony_ci                    .build(test.patterns)
63906f54294Sopenharmony_ci                    .find_overlapping_iter(test.haystack)
64006f54294Sopenharmony_ci                    .collect()
64106f54294Sopenharmony_ci            });
64206f54294Sopenharmony_ci        }
64306f54294Sopenharmony_ci    };
64406f54294Sopenharmony_ci    (stream, $name:ident, $collection:expr, $kind:ident, $with:expr) => {
64506f54294Sopenharmony_ci        #[test]
64606f54294Sopenharmony_ci        fn $name() {
64706f54294Sopenharmony_ci            run_search_tests($collection, |test| {
64806f54294Sopenharmony_ci                let buf =
64906f54294Sopenharmony_ci                    io::BufReader::with_capacity(1, test.haystack.as_bytes());
65006f54294Sopenharmony_ci                let mut builder = AhoCorasickBuilder::new();
65106f54294Sopenharmony_ci                $with(&mut builder);
65206f54294Sopenharmony_ci                builder
65306f54294Sopenharmony_ci                    .match_kind(MatchKind::$kind)
65406f54294Sopenharmony_ci                    .build(test.patterns)
65506f54294Sopenharmony_ci                    .stream_find_iter(buf)
65606f54294Sopenharmony_ci                    .map(|result| result.unwrap())
65706f54294Sopenharmony_ci                    .collect()
65806f54294Sopenharmony_ci            });
65906f54294Sopenharmony_ci        }
66006f54294Sopenharmony_ci    };
66106f54294Sopenharmony_ci    ($name:ident, $collection:expr, $kind:ident, $with:expr) => {
66206f54294Sopenharmony_ci        #[test]
66306f54294Sopenharmony_ci        fn $name() {
66406f54294Sopenharmony_ci            run_search_tests($collection, |test| {
66506f54294Sopenharmony_ci                let mut builder = AhoCorasickBuilder::new();
66606f54294Sopenharmony_ci                $with(&mut builder);
66706f54294Sopenharmony_ci                builder
66806f54294Sopenharmony_ci                    .match_kind(MatchKind::$kind)
66906f54294Sopenharmony_ci                    .build(test.patterns)
67006f54294Sopenharmony_ci                    .find_iter(test.haystack)
67106f54294Sopenharmony_ci                    .collect()
67206f54294Sopenharmony_ci            });
67306f54294Sopenharmony_ci        }
67406f54294Sopenharmony_ci    };
67506f54294Sopenharmony_ci}
67606f54294Sopenharmony_ci
67706f54294Sopenharmony_cimacro_rules! testcombo {
67806f54294Sopenharmony_ci    ($name:ident, $collection:expr, $kind:ident) => {
67906f54294Sopenharmony_ci        mod $name {
68006f54294Sopenharmony_ci            use super::*;
68106f54294Sopenharmony_ci
68206f54294Sopenharmony_ci            testconfig!(nfa_default, $collection, $kind, |_| ());
68306f54294Sopenharmony_ci            testconfig!(
68406f54294Sopenharmony_ci                nfa_no_prefilter,
68506f54294Sopenharmony_ci                $collection,
68606f54294Sopenharmony_ci                $kind,
68706f54294Sopenharmony_ci                |b: &mut AhoCorasickBuilder| {
68806f54294Sopenharmony_ci                    b.prefilter(false);
68906f54294Sopenharmony_ci                }
69006f54294Sopenharmony_ci            );
69106f54294Sopenharmony_ci            testconfig!(
69206f54294Sopenharmony_ci                nfa_all_sparse,
69306f54294Sopenharmony_ci                $collection,
69406f54294Sopenharmony_ci                $kind,
69506f54294Sopenharmony_ci                |b: &mut AhoCorasickBuilder| {
69606f54294Sopenharmony_ci                    b.dense_depth(0);
69706f54294Sopenharmony_ci                }
69806f54294Sopenharmony_ci            );
69906f54294Sopenharmony_ci            testconfig!(
70006f54294Sopenharmony_ci                nfa_all_dense,
70106f54294Sopenharmony_ci                $collection,
70206f54294Sopenharmony_ci                $kind,
70306f54294Sopenharmony_ci                |b: &mut AhoCorasickBuilder| {
70406f54294Sopenharmony_ci                    b.dense_depth(usize::MAX);
70506f54294Sopenharmony_ci                }
70606f54294Sopenharmony_ci            );
70706f54294Sopenharmony_ci            testconfig!(
70806f54294Sopenharmony_ci                dfa_default,
70906f54294Sopenharmony_ci                $collection,
71006f54294Sopenharmony_ci                $kind,
71106f54294Sopenharmony_ci                |b: &mut AhoCorasickBuilder| {
71206f54294Sopenharmony_ci                    b.dfa(true);
71306f54294Sopenharmony_ci                }
71406f54294Sopenharmony_ci            );
71506f54294Sopenharmony_ci            testconfig!(
71606f54294Sopenharmony_ci                dfa_no_prefilter,
71706f54294Sopenharmony_ci                $collection,
71806f54294Sopenharmony_ci                $kind,
71906f54294Sopenharmony_ci                |b: &mut AhoCorasickBuilder| {
72006f54294Sopenharmony_ci                    b.dfa(true).prefilter(false);
72106f54294Sopenharmony_ci                }
72206f54294Sopenharmony_ci            );
72306f54294Sopenharmony_ci            testconfig!(
72406f54294Sopenharmony_ci                dfa_all_sparse,
72506f54294Sopenharmony_ci                $collection,
72606f54294Sopenharmony_ci                $kind,
72706f54294Sopenharmony_ci                |b: &mut AhoCorasickBuilder| {
72806f54294Sopenharmony_ci                    b.dfa(true).dense_depth(0);
72906f54294Sopenharmony_ci                }
73006f54294Sopenharmony_ci            );
73106f54294Sopenharmony_ci            testconfig!(
73206f54294Sopenharmony_ci                dfa_all_dense,
73306f54294Sopenharmony_ci                $collection,
73406f54294Sopenharmony_ci                $kind,
73506f54294Sopenharmony_ci                |b: &mut AhoCorasickBuilder| {
73606f54294Sopenharmony_ci                    b.dfa(true).dense_depth(usize::MAX);
73706f54294Sopenharmony_ci                }
73806f54294Sopenharmony_ci            );
73906f54294Sopenharmony_ci            testconfig!(
74006f54294Sopenharmony_ci                dfa_no_byte_class,
74106f54294Sopenharmony_ci                $collection,
74206f54294Sopenharmony_ci                $kind,
74306f54294Sopenharmony_ci                |b: &mut AhoCorasickBuilder| {
74406f54294Sopenharmony_ci                    // TODO: remove tests when option is removed.
74506f54294Sopenharmony_ci                    #[allow(deprecated)]
74606f54294Sopenharmony_ci                    b.dfa(true).byte_classes(false);
74706f54294Sopenharmony_ci                }
74806f54294Sopenharmony_ci            );
74906f54294Sopenharmony_ci            testconfig!(
75006f54294Sopenharmony_ci                dfa_no_premultiply,
75106f54294Sopenharmony_ci                $collection,
75206f54294Sopenharmony_ci                $kind,
75306f54294Sopenharmony_ci                |b: &mut AhoCorasickBuilder| {
75406f54294Sopenharmony_ci                    // TODO: remove tests when option is removed.
75506f54294Sopenharmony_ci                    #[allow(deprecated)]
75606f54294Sopenharmony_ci                    b.dfa(true).premultiply(false);
75706f54294Sopenharmony_ci                }
75806f54294Sopenharmony_ci            );
75906f54294Sopenharmony_ci            testconfig!(
76006f54294Sopenharmony_ci                dfa_no_byte_class_no_premultiply,
76106f54294Sopenharmony_ci                $collection,
76206f54294Sopenharmony_ci                $kind,
76306f54294Sopenharmony_ci                |b: &mut AhoCorasickBuilder| {
76406f54294Sopenharmony_ci                    // TODO: remove tests when options are removed.
76506f54294Sopenharmony_ci                    #[allow(deprecated)]
76606f54294Sopenharmony_ci                    b.dfa(true).byte_classes(false).premultiply(false);
76706f54294Sopenharmony_ci                }
76806f54294Sopenharmony_ci            );
76906f54294Sopenharmony_ci        }
77006f54294Sopenharmony_ci    };
77106f54294Sopenharmony_ci}
77206f54294Sopenharmony_ci
77306f54294Sopenharmony_ci// Write out the combinations.
77406f54294Sopenharmony_citestcombo!(search_leftmost_longest, AC_LEFTMOST_LONGEST, LeftmostLongest);
77506f54294Sopenharmony_citestcombo!(search_leftmost_first, AC_LEFTMOST_FIRST, LeftmostFirst);
77606f54294Sopenharmony_citestcombo!(
77706f54294Sopenharmony_ci    search_standard_nonoverlapping,
77806f54294Sopenharmony_ci    AC_STANDARD_NON_OVERLAPPING,
77906f54294Sopenharmony_ci    Standard
78006f54294Sopenharmony_ci);
78106f54294Sopenharmony_ci
78206f54294Sopenharmony_ci// Write out the overlapping combo by hand since there is only one of them.
78306f54294Sopenharmony_citestconfig!(
78406f54294Sopenharmony_ci    overlapping,
78506f54294Sopenharmony_ci    search_standard_overlapping_nfa_default,
78606f54294Sopenharmony_ci    AC_STANDARD_OVERLAPPING,
78706f54294Sopenharmony_ci    Standard,
78806f54294Sopenharmony_ci    |_| ()
78906f54294Sopenharmony_ci);
79006f54294Sopenharmony_citestconfig!(
79106f54294Sopenharmony_ci    overlapping,
79206f54294Sopenharmony_ci    search_standard_overlapping_nfa_all_sparse,
79306f54294Sopenharmony_ci    AC_STANDARD_OVERLAPPING,
79406f54294Sopenharmony_ci    Standard,
79506f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
79606f54294Sopenharmony_ci        b.dense_depth(0);
79706f54294Sopenharmony_ci    }
79806f54294Sopenharmony_ci);
79906f54294Sopenharmony_citestconfig!(
80006f54294Sopenharmony_ci    overlapping,
80106f54294Sopenharmony_ci    search_standard_overlapping_nfa_all_dense,
80206f54294Sopenharmony_ci    AC_STANDARD_OVERLAPPING,
80306f54294Sopenharmony_ci    Standard,
80406f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
80506f54294Sopenharmony_ci        b.dense_depth(usize::MAX);
80606f54294Sopenharmony_ci    }
80706f54294Sopenharmony_ci);
80806f54294Sopenharmony_citestconfig!(
80906f54294Sopenharmony_ci    overlapping,
81006f54294Sopenharmony_ci    search_standard_overlapping_dfa_default,
81106f54294Sopenharmony_ci    AC_STANDARD_OVERLAPPING,
81206f54294Sopenharmony_ci    Standard,
81306f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
81406f54294Sopenharmony_ci        b.dfa(true);
81506f54294Sopenharmony_ci    }
81606f54294Sopenharmony_ci);
81706f54294Sopenharmony_citestconfig!(
81806f54294Sopenharmony_ci    overlapping,
81906f54294Sopenharmony_ci    search_standard_overlapping_dfa_all_sparse,
82006f54294Sopenharmony_ci    AC_STANDARD_OVERLAPPING,
82106f54294Sopenharmony_ci    Standard,
82206f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
82306f54294Sopenharmony_ci        b.dfa(true).dense_depth(0);
82406f54294Sopenharmony_ci    }
82506f54294Sopenharmony_ci);
82606f54294Sopenharmony_citestconfig!(
82706f54294Sopenharmony_ci    overlapping,
82806f54294Sopenharmony_ci    search_standard_overlapping_dfa_all_dense,
82906f54294Sopenharmony_ci    AC_STANDARD_OVERLAPPING,
83006f54294Sopenharmony_ci    Standard,
83106f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
83206f54294Sopenharmony_ci        b.dfa(true).dense_depth(usize::MAX);
83306f54294Sopenharmony_ci    }
83406f54294Sopenharmony_ci);
83506f54294Sopenharmony_citestconfig!(
83606f54294Sopenharmony_ci    overlapping,
83706f54294Sopenharmony_ci    search_standard_overlapping_dfa_no_byte_class,
83806f54294Sopenharmony_ci    AC_STANDARD_OVERLAPPING,
83906f54294Sopenharmony_ci    Standard,
84006f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
84106f54294Sopenharmony_ci        // TODO: remove tests when option is removed.
84206f54294Sopenharmony_ci        #[allow(deprecated)]
84306f54294Sopenharmony_ci        b.dfa(true).byte_classes(false);
84406f54294Sopenharmony_ci    }
84506f54294Sopenharmony_ci);
84606f54294Sopenharmony_citestconfig!(
84706f54294Sopenharmony_ci    overlapping,
84806f54294Sopenharmony_ci    search_standard_overlapping_dfa_no_premultiply,
84906f54294Sopenharmony_ci    AC_STANDARD_OVERLAPPING,
85006f54294Sopenharmony_ci    Standard,
85106f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
85206f54294Sopenharmony_ci        // TODO: remove tests when option is removed.
85306f54294Sopenharmony_ci        #[allow(deprecated)]
85406f54294Sopenharmony_ci        b.dfa(true).premultiply(false);
85506f54294Sopenharmony_ci    }
85606f54294Sopenharmony_ci);
85706f54294Sopenharmony_citestconfig!(
85806f54294Sopenharmony_ci    overlapping,
85906f54294Sopenharmony_ci    search_standard_overlapping_dfa_no_byte_class_no_premultiply,
86006f54294Sopenharmony_ci    AC_STANDARD_OVERLAPPING,
86106f54294Sopenharmony_ci    Standard,
86206f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
86306f54294Sopenharmony_ci        // TODO: remove tests when options are removed.
86406f54294Sopenharmony_ci        #[allow(deprecated)]
86506f54294Sopenharmony_ci        b.dfa(true).byte_classes(false).premultiply(false);
86606f54294Sopenharmony_ci    }
86706f54294Sopenharmony_ci);
86806f54294Sopenharmony_ci
86906f54294Sopenharmony_ci// Also write out tests manually for streams, since we only test the standard
87006f54294Sopenharmony_ci// match semantics. We also don't bother testing different automaton
87106f54294Sopenharmony_ci// configurations, since those are well covered by tests above.
87206f54294Sopenharmony_citestconfig!(
87306f54294Sopenharmony_ci    stream,
87406f54294Sopenharmony_ci    search_standard_stream_nfa_default,
87506f54294Sopenharmony_ci    AC_STANDARD_NON_OVERLAPPING,
87606f54294Sopenharmony_ci    Standard,
87706f54294Sopenharmony_ci    |_| ()
87806f54294Sopenharmony_ci);
87906f54294Sopenharmony_citestconfig!(
88006f54294Sopenharmony_ci    stream,
88106f54294Sopenharmony_ci    search_standard_stream_dfa_default,
88206f54294Sopenharmony_ci    AC_STANDARD_NON_OVERLAPPING,
88306f54294Sopenharmony_ci    Standard,
88406f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
88506f54294Sopenharmony_ci        b.dfa(true);
88606f54294Sopenharmony_ci    }
88706f54294Sopenharmony_ci);
88806f54294Sopenharmony_ci
88906f54294Sopenharmony_ci// Same thing for anchored searches. Write them out manually.
89006f54294Sopenharmony_citestconfig!(
89106f54294Sopenharmony_ci    search_standard_anchored_nfa_default,
89206f54294Sopenharmony_ci    AC_STANDARD_ANCHORED_NON_OVERLAPPING,
89306f54294Sopenharmony_ci    Standard,
89406f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
89506f54294Sopenharmony_ci        b.anchored(true);
89606f54294Sopenharmony_ci    }
89706f54294Sopenharmony_ci);
89806f54294Sopenharmony_citestconfig!(
89906f54294Sopenharmony_ci    search_standard_anchored_dfa_default,
90006f54294Sopenharmony_ci    AC_STANDARD_ANCHORED_NON_OVERLAPPING,
90106f54294Sopenharmony_ci    Standard,
90206f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
90306f54294Sopenharmony_ci        b.anchored(true).dfa(true);
90406f54294Sopenharmony_ci    }
90506f54294Sopenharmony_ci);
90606f54294Sopenharmony_citestconfig!(
90706f54294Sopenharmony_ci    overlapping,
90806f54294Sopenharmony_ci    search_standard_anchored_overlapping_nfa_default,
90906f54294Sopenharmony_ci    AC_STANDARD_ANCHORED_OVERLAPPING,
91006f54294Sopenharmony_ci    Standard,
91106f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
91206f54294Sopenharmony_ci        b.anchored(true);
91306f54294Sopenharmony_ci    }
91406f54294Sopenharmony_ci);
91506f54294Sopenharmony_citestconfig!(
91606f54294Sopenharmony_ci    overlapping,
91706f54294Sopenharmony_ci    search_standard_anchored_overlapping_dfa_default,
91806f54294Sopenharmony_ci    AC_STANDARD_ANCHORED_OVERLAPPING,
91906f54294Sopenharmony_ci    Standard,
92006f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
92106f54294Sopenharmony_ci        b.anchored(true).dfa(true);
92206f54294Sopenharmony_ci    }
92306f54294Sopenharmony_ci);
92406f54294Sopenharmony_citestconfig!(
92506f54294Sopenharmony_ci    search_leftmost_first_anchored_nfa_default,
92606f54294Sopenharmony_ci    AC_LEFTMOST_FIRST_ANCHORED,
92706f54294Sopenharmony_ci    LeftmostFirst,
92806f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
92906f54294Sopenharmony_ci        b.anchored(true);
93006f54294Sopenharmony_ci    }
93106f54294Sopenharmony_ci);
93206f54294Sopenharmony_citestconfig!(
93306f54294Sopenharmony_ci    search_leftmost_first_anchored_dfa_default,
93406f54294Sopenharmony_ci    AC_LEFTMOST_FIRST_ANCHORED,
93506f54294Sopenharmony_ci    LeftmostFirst,
93606f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
93706f54294Sopenharmony_ci        b.anchored(true).dfa(true);
93806f54294Sopenharmony_ci    }
93906f54294Sopenharmony_ci);
94006f54294Sopenharmony_citestconfig!(
94106f54294Sopenharmony_ci    search_leftmost_longest_anchored_nfa_default,
94206f54294Sopenharmony_ci    AC_LEFTMOST_LONGEST_ANCHORED,
94306f54294Sopenharmony_ci    LeftmostLongest,
94406f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
94506f54294Sopenharmony_ci        b.anchored(true);
94606f54294Sopenharmony_ci    }
94706f54294Sopenharmony_ci);
94806f54294Sopenharmony_citestconfig!(
94906f54294Sopenharmony_ci    search_leftmost_longest_anchored_dfa_default,
95006f54294Sopenharmony_ci    AC_LEFTMOST_LONGEST_ANCHORED,
95106f54294Sopenharmony_ci    LeftmostLongest,
95206f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
95306f54294Sopenharmony_ci        b.anchored(true).dfa(true);
95406f54294Sopenharmony_ci    }
95506f54294Sopenharmony_ci);
95606f54294Sopenharmony_ci
95706f54294Sopenharmony_ci// And also write out the test combinations for ASCII case insensitivity.
95806f54294Sopenharmony_citestconfig!(
95906f54294Sopenharmony_ci    acasei_standard_nfa_default,
96006f54294Sopenharmony_ci    &[ASCII_CASE_INSENSITIVE],
96106f54294Sopenharmony_ci    Standard,
96206f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
96306f54294Sopenharmony_ci        b.prefilter(false).ascii_case_insensitive(true);
96406f54294Sopenharmony_ci    }
96506f54294Sopenharmony_ci);
96606f54294Sopenharmony_citestconfig!(
96706f54294Sopenharmony_ci    acasei_standard_dfa_default,
96806f54294Sopenharmony_ci    &[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_NON_OVERLAPPING],
96906f54294Sopenharmony_ci    Standard,
97006f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
97106f54294Sopenharmony_ci        b.ascii_case_insensitive(true).dfa(true);
97206f54294Sopenharmony_ci    }
97306f54294Sopenharmony_ci);
97406f54294Sopenharmony_citestconfig!(
97506f54294Sopenharmony_ci    overlapping,
97606f54294Sopenharmony_ci    acasei_standard_overlapping_nfa_default,
97706f54294Sopenharmony_ci    &[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_OVERLAPPING],
97806f54294Sopenharmony_ci    Standard,
97906f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
98006f54294Sopenharmony_ci        b.ascii_case_insensitive(true);
98106f54294Sopenharmony_ci    }
98206f54294Sopenharmony_ci);
98306f54294Sopenharmony_citestconfig!(
98406f54294Sopenharmony_ci    overlapping,
98506f54294Sopenharmony_ci    acasei_standard_overlapping_dfa_default,
98606f54294Sopenharmony_ci    &[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_OVERLAPPING],
98706f54294Sopenharmony_ci    Standard,
98806f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
98906f54294Sopenharmony_ci        b.ascii_case_insensitive(true).dfa(true);
99006f54294Sopenharmony_ci    }
99106f54294Sopenharmony_ci);
99206f54294Sopenharmony_citestconfig!(
99306f54294Sopenharmony_ci    acasei_leftmost_first_nfa_default,
99406f54294Sopenharmony_ci    &[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_NON_OVERLAPPING],
99506f54294Sopenharmony_ci    LeftmostFirst,
99606f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
99706f54294Sopenharmony_ci        b.ascii_case_insensitive(true);
99806f54294Sopenharmony_ci    }
99906f54294Sopenharmony_ci);
100006f54294Sopenharmony_citestconfig!(
100106f54294Sopenharmony_ci    acasei_leftmost_first_dfa_default,
100206f54294Sopenharmony_ci    &[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_NON_OVERLAPPING],
100306f54294Sopenharmony_ci    LeftmostFirst,
100406f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
100506f54294Sopenharmony_ci        b.ascii_case_insensitive(true).dfa(true);
100606f54294Sopenharmony_ci    }
100706f54294Sopenharmony_ci);
100806f54294Sopenharmony_citestconfig!(
100906f54294Sopenharmony_ci    acasei_leftmost_longest_nfa_default,
101006f54294Sopenharmony_ci    &[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_NON_OVERLAPPING],
101106f54294Sopenharmony_ci    LeftmostLongest,
101206f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
101306f54294Sopenharmony_ci        b.ascii_case_insensitive(true);
101406f54294Sopenharmony_ci    }
101506f54294Sopenharmony_ci);
101606f54294Sopenharmony_citestconfig!(
101706f54294Sopenharmony_ci    acasei_leftmost_longest_dfa_default,
101806f54294Sopenharmony_ci    &[ASCII_CASE_INSENSITIVE, ASCII_CASE_INSENSITIVE_NON_OVERLAPPING],
101906f54294Sopenharmony_ci    LeftmostLongest,
102006f54294Sopenharmony_ci    |b: &mut AhoCorasickBuilder| {
102106f54294Sopenharmony_ci        b.ascii_case_insensitive(true).dfa(true);
102206f54294Sopenharmony_ci    }
102306f54294Sopenharmony_ci);
102406f54294Sopenharmony_ci
102506f54294Sopenharmony_cifn run_search_tests<F: FnMut(&SearchTest) -> Vec<Match>>(
102606f54294Sopenharmony_ci    which: TestCollection,
102706f54294Sopenharmony_ci    mut f: F,
102806f54294Sopenharmony_ci) {
102906f54294Sopenharmony_ci    let get_match_triples =
103006f54294Sopenharmony_ci        |matches: Vec<Match>| -> Vec<(usize, usize, usize)> {
103106f54294Sopenharmony_ci            matches
103206f54294Sopenharmony_ci                .into_iter()
103306f54294Sopenharmony_ci                .map(|m| (m.pattern(), m.start(), m.end()))
103406f54294Sopenharmony_ci                .collect()
103506f54294Sopenharmony_ci        };
103606f54294Sopenharmony_ci    for &tests in which {
103706f54294Sopenharmony_ci        for test in tests {
103806f54294Sopenharmony_ci            assert_eq!(
103906f54294Sopenharmony_ci                test.matches,
104006f54294Sopenharmony_ci                get_match_triples(f(&test)).as_slice(),
104106f54294Sopenharmony_ci                "test: {}, patterns: {:?}, haystack: {:?}",
104206f54294Sopenharmony_ci                test.name,
104306f54294Sopenharmony_ci                test.patterns,
104406f54294Sopenharmony_ci                test.haystack
104506f54294Sopenharmony_ci            );
104606f54294Sopenharmony_ci        }
104706f54294Sopenharmony_ci    }
104806f54294Sopenharmony_ci}
104906f54294Sopenharmony_ci
105006f54294Sopenharmony_ci#[test]
105106f54294Sopenharmony_cifn search_tests_have_unique_names() {
105206f54294Sopenharmony_ci    let assert = |constname, tests: &[SearchTest]| {
105306f54294Sopenharmony_ci        let mut seen = HashMap::new(); // map from test name to position
105406f54294Sopenharmony_ci        for (i, test) in tests.iter().enumerate() {
105506f54294Sopenharmony_ci            if !seen.contains_key(test.name) {
105606f54294Sopenharmony_ci                seen.insert(test.name, i);
105706f54294Sopenharmony_ci            } else {
105806f54294Sopenharmony_ci                let last = seen[test.name];
105906f54294Sopenharmony_ci                panic!(
106006f54294Sopenharmony_ci                    "{} tests have duplicate names at positions {} and {}",
106106f54294Sopenharmony_ci                    constname, last, i
106206f54294Sopenharmony_ci                );
106306f54294Sopenharmony_ci            }
106406f54294Sopenharmony_ci        }
106506f54294Sopenharmony_ci    };
106606f54294Sopenharmony_ci    assert("BASICS", BASICS);
106706f54294Sopenharmony_ci    assert("STANDARD", STANDARD);
106806f54294Sopenharmony_ci    assert("LEFTMOST", LEFTMOST);
106906f54294Sopenharmony_ci    assert("LEFTMOST_FIRST", LEFTMOST_FIRST);
107006f54294Sopenharmony_ci    assert("LEFTMOST_LONGEST", LEFTMOST_LONGEST);
107106f54294Sopenharmony_ci    assert("NON_OVERLAPPING", NON_OVERLAPPING);
107206f54294Sopenharmony_ci    assert("OVERLAPPING", OVERLAPPING);
107306f54294Sopenharmony_ci    assert("REGRESSION", REGRESSION);
107406f54294Sopenharmony_ci}
107506f54294Sopenharmony_ci
107606f54294Sopenharmony_ci#[test]
107706f54294Sopenharmony_ci#[should_panic]
107806f54294Sopenharmony_cifn stream_not_allowed_leftmost_first() {
107906f54294Sopenharmony_ci    let fsm = AhoCorasickBuilder::new()
108006f54294Sopenharmony_ci        .match_kind(MatchKind::LeftmostFirst)
108106f54294Sopenharmony_ci        .build(None::<String>);
108206f54294Sopenharmony_ci    assert_eq!(fsm.stream_find_iter(&b""[..]).count(), 0);
108306f54294Sopenharmony_ci}
108406f54294Sopenharmony_ci
108506f54294Sopenharmony_ci#[test]
108606f54294Sopenharmony_ci#[should_panic]
108706f54294Sopenharmony_cifn stream_not_allowed_leftmost_longest() {
108806f54294Sopenharmony_ci    let fsm = AhoCorasickBuilder::new()
108906f54294Sopenharmony_ci        .match_kind(MatchKind::LeftmostLongest)
109006f54294Sopenharmony_ci        .build(None::<String>);
109106f54294Sopenharmony_ci    assert_eq!(fsm.stream_find_iter(&b""[..]).count(), 0);
109206f54294Sopenharmony_ci}
109306f54294Sopenharmony_ci
109406f54294Sopenharmony_ci#[test]
109506f54294Sopenharmony_ci#[should_panic]
109606f54294Sopenharmony_cifn overlapping_not_allowed_leftmost_first() {
109706f54294Sopenharmony_ci    let fsm = AhoCorasickBuilder::new()
109806f54294Sopenharmony_ci        .match_kind(MatchKind::LeftmostFirst)
109906f54294Sopenharmony_ci        .build(None::<String>);
110006f54294Sopenharmony_ci    assert_eq!(fsm.find_overlapping_iter("").count(), 0);
110106f54294Sopenharmony_ci}
110206f54294Sopenharmony_ci
110306f54294Sopenharmony_ci#[test]
110406f54294Sopenharmony_ci#[should_panic]
110506f54294Sopenharmony_cifn overlapping_not_allowed_leftmost_longest() {
110606f54294Sopenharmony_ci    let fsm = AhoCorasickBuilder::new()
110706f54294Sopenharmony_ci        .match_kind(MatchKind::LeftmostLongest)
110806f54294Sopenharmony_ci        .build(None::<String>);
110906f54294Sopenharmony_ci    assert_eq!(fsm.find_overlapping_iter("").count(), 0);
111006f54294Sopenharmony_ci}
111106f54294Sopenharmony_ci
111206f54294Sopenharmony_ci#[test]
111306f54294Sopenharmony_cifn state_id_too_small() {
111406f54294Sopenharmony_ci    let mut patterns = vec![];
111506f54294Sopenharmony_ci    for c1 in (b'a'..b'z').map(|b| b as char) {
111606f54294Sopenharmony_ci        for c2 in (b'a'..b'z').map(|b| b as char) {
111706f54294Sopenharmony_ci            for c3 in (b'a'..b'z').map(|b| b as char) {
111806f54294Sopenharmony_ci                patterns.push(format!("{}{}{}", c1, c2, c3));
111906f54294Sopenharmony_ci            }
112006f54294Sopenharmony_ci        }
112106f54294Sopenharmony_ci    }
112206f54294Sopenharmony_ci    let result =
112306f54294Sopenharmony_ci        AhoCorasickBuilder::new().build_with_size::<u8, _, _>(&patterns);
112406f54294Sopenharmony_ci    assert!(result.is_err());
112506f54294Sopenharmony_ci}
112606f54294Sopenharmony_ci
112706f54294Sopenharmony_ci// See: https://github.com/BurntSushi/aho-corasick/issues/44
112806f54294Sopenharmony_ci//
112906f54294Sopenharmony_ci// In short, this test ensures that enabling ASCII case insensitivity does not
113006f54294Sopenharmony_ci// visit an exponential number of states when filling in failure transitions.
113106f54294Sopenharmony_ci#[test]
113206f54294Sopenharmony_cifn regression_ascii_case_insensitive_no_exponential() {
113306f54294Sopenharmony_ci    let ac = AhoCorasickBuilder::new()
113406f54294Sopenharmony_ci        .ascii_case_insensitive(true)
113506f54294Sopenharmony_ci        .build(&["Tsubaki House-Triple Shot Vol01校花三姐妹"]);
113606f54294Sopenharmony_ci    assert!(ac.find("").is_none());
113706f54294Sopenharmony_ci}
113806f54294Sopenharmony_ci
113906f54294Sopenharmony_ci// See: https://github.com/BurntSushi/aho-corasick/issues/53
114006f54294Sopenharmony_ci//
114106f54294Sopenharmony_ci// This test ensures that the rare byte prefilter works in a particular corner
114206f54294Sopenharmony_ci// case. In particular, the shift offset detected for '/' in the patterns below
114306f54294Sopenharmony_ci// was incorrect, leading to a false negative.
114406f54294Sopenharmony_ci#[test]
114506f54294Sopenharmony_cifn regression_rare_byte_prefilter() {
114606f54294Sopenharmony_ci    use crate::AhoCorasick;
114706f54294Sopenharmony_ci
114806f54294Sopenharmony_ci    let ac = AhoCorasick::new_auto_configured(&["ab/j/", "x/"]);
114906f54294Sopenharmony_ci    assert!(ac.is_match("ab/j/"));
115006f54294Sopenharmony_ci}
115106f54294Sopenharmony_ci
115206f54294Sopenharmony_ci#[test]
115306f54294Sopenharmony_cifn regression_case_insensitive_prefilter() {
115406f54294Sopenharmony_ci    use crate::AhoCorasickBuilder;
115506f54294Sopenharmony_ci
115606f54294Sopenharmony_ci    for c in b'a'..b'z' {
115706f54294Sopenharmony_ci        for c2 in b'a'..b'z' {
115806f54294Sopenharmony_ci            let c = c as char;
115906f54294Sopenharmony_ci            let c2 = c2 as char;
116006f54294Sopenharmony_ci            let needle = format!("{}{}", c, c2).to_lowercase();
116106f54294Sopenharmony_ci            let haystack = needle.to_uppercase();
116206f54294Sopenharmony_ci            let ac = AhoCorasickBuilder::new()
116306f54294Sopenharmony_ci                .ascii_case_insensitive(true)
116406f54294Sopenharmony_ci                .prefilter(true)
116506f54294Sopenharmony_ci                .build(&[&needle]);
116606f54294Sopenharmony_ci            assert_eq!(
116706f54294Sopenharmony_ci                1,
116806f54294Sopenharmony_ci                ac.find_iter(&haystack).count(),
116906f54294Sopenharmony_ci                "failed to find {:?} in {:?}\n\nautomaton:\n{:?}",
117006f54294Sopenharmony_ci                needle,
117106f54294Sopenharmony_ci                haystack,
117206f54294Sopenharmony_ci                ac,
117306f54294Sopenharmony_ci            );
117406f54294Sopenharmony_ci        }
117506f54294Sopenharmony_ci    }
117606f54294Sopenharmony_ci}
117706f54294Sopenharmony_ci
117806f54294Sopenharmony_ci// See: https://github.com/BurntSushi/aho-corasick/issues/64
117906f54294Sopenharmony_ci//
118006f54294Sopenharmony_ci// This occurs when the rare byte prefilter is active.
118106f54294Sopenharmony_ci#[test]
118206f54294Sopenharmony_cifn regression_stream_rare_byte_prefilter() {
118306f54294Sopenharmony_ci    use std::io::Read;
118406f54294Sopenharmony_ci
118506f54294Sopenharmony_ci    // NOTE: The test only fails if this ends with j.
118606f54294Sopenharmony_ci    const MAGIC: [u8; 5] = *b"1234j";
118706f54294Sopenharmony_ci
118806f54294Sopenharmony_ci    // NOTE: The test fails for value in 8188..=8191 These value put the string
118906f54294Sopenharmony_ci    // to search accross two call to read because the buffer size is 8192 by
119006f54294Sopenharmony_ci    // default.
119106f54294Sopenharmony_ci    const BEGIN: usize = 8191;
119206f54294Sopenharmony_ci
119306f54294Sopenharmony_ci    /// This is just a structure that implements Reader. The reader
119406f54294Sopenharmony_ci    /// implementation will simulate a file filled with 0, except for the MAGIC
119506f54294Sopenharmony_ci    /// string at offset BEGIN.
119606f54294Sopenharmony_ci    #[derive(Default)]
119706f54294Sopenharmony_ci    struct R {
119806f54294Sopenharmony_ci        read: usize,
119906f54294Sopenharmony_ci    }
120006f54294Sopenharmony_ci
120106f54294Sopenharmony_ci    impl Read for R {
120206f54294Sopenharmony_ci        fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
120306f54294Sopenharmony_ci            //dbg!(buf.len());
120406f54294Sopenharmony_ci            if self.read > 100000 {
120506f54294Sopenharmony_ci                return Ok(0);
120606f54294Sopenharmony_ci            }
120706f54294Sopenharmony_ci            let mut from = 0;
120806f54294Sopenharmony_ci            if self.read < BEGIN {
120906f54294Sopenharmony_ci                from = buf.len().min(BEGIN - self.read);
121006f54294Sopenharmony_ci                for x in 0..from {
121106f54294Sopenharmony_ci                    buf[x] = 0;
121206f54294Sopenharmony_ci                }
121306f54294Sopenharmony_ci                self.read += from;
121406f54294Sopenharmony_ci            }
121506f54294Sopenharmony_ci            if self.read >= BEGIN && self.read <= BEGIN + MAGIC.len() {
121606f54294Sopenharmony_ci                let to = buf.len().min(BEGIN + MAGIC.len() - self.read + from);
121706f54294Sopenharmony_ci                if to > from {
121806f54294Sopenharmony_ci                    buf[from..to].copy_from_slice(
121906f54294Sopenharmony_ci                        &MAGIC
122006f54294Sopenharmony_ci                            [self.read - BEGIN..self.read - BEGIN + to - from],
122106f54294Sopenharmony_ci                    );
122206f54294Sopenharmony_ci                    self.read += to - from;
122306f54294Sopenharmony_ci                    from = to;
122406f54294Sopenharmony_ci                }
122506f54294Sopenharmony_ci            }
122606f54294Sopenharmony_ci            for x in from..buf.len() {
122706f54294Sopenharmony_ci                buf[x] = 0;
122806f54294Sopenharmony_ci                self.read += 1;
122906f54294Sopenharmony_ci            }
123006f54294Sopenharmony_ci            Ok(buf.len())
123106f54294Sopenharmony_ci        }
123206f54294Sopenharmony_ci    }
123306f54294Sopenharmony_ci
123406f54294Sopenharmony_ci    fn run() -> ::std::io::Result<()> {
123506f54294Sopenharmony_ci        let aut = AhoCorasickBuilder::new().build(&[&MAGIC]);
123606f54294Sopenharmony_ci
123706f54294Sopenharmony_ci        // While reading from a vector, it works:
123806f54294Sopenharmony_ci        let mut buf = vec![];
123906f54294Sopenharmony_ci        R::default().read_to_end(&mut buf)?;
124006f54294Sopenharmony_ci        let from_whole = aut.find_iter(&buf).next().unwrap().start();
124106f54294Sopenharmony_ci
124206f54294Sopenharmony_ci        //But using stream_find_iter fails!
124306f54294Sopenharmony_ci        let mut file = R::default();
124406f54294Sopenharmony_ci        let begin = aut
124506f54294Sopenharmony_ci            .stream_find_iter(&mut file)
124606f54294Sopenharmony_ci            .next()
124706f54294Sopenharmony_ci            .expect("NOT FOUND!!!!")? // Panic here
124806f54294Sopenharmony_ci            .start();
124906f54294Sopenharmony_ci        assert_eq!(from_whole, begin);
125006f54294Sopenharmony_ci        Ok(())
125106f54294Sopenharmony_ci    }
125206f54294Sopenharmony_ci
125306f54294Sopenharmony_ci    run().unwrap()
125406f54294Sopenharmony_ci}
1255