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