1macro_rules! searcher {
2    ($name:ident, $re:expr, $haystack:expr) => (
3        searcher!($name, $re, $haystack, vec vec![]);
4    );
5    ($name:ident, $re:expr, $haystack:expr, $($steps:expr,)*) => (
6        searcher!($name, $re, $haystack, vec vec![$($steps),*]);
7    );
8    ($name:ident, $re:expr, $haystack:expr, $($steps:expr),*) => (
9        searcher!($name, $re, $haystack, vec vec![$($steps),*]);
10    );
11    ($name:ident, $re:expr, $haystack:expr, vec $expect_steps:expr) => (
12        #[test]
13        #[allow(unused_imports)]
14        fn $name() {
15            searcher_expr! {{
16                use std::str::pattern::{Pattern, Searcher};
17                use std::str::pattern::SearchStep::{Match, Reject, Done};
18                let re = regex!($re);
19                let mut se = re.into_searcher($haystack);
20                let mut got_steps = vec![];
21                loop {
22                    match se.next() {
23                        Done => break,
24                        step => { got_steps.push(step); }
25                    }
26                }
27                assert_eq!(got_steps, $expect_steps);
28            }}
29        }
30    );
31}
32
33searcher!(searcher_empty_regex_empty_haystack, r"", "", Match(0, 0));
34searcher!(
35    searcher_empty_regex,
36    r"",
37    "ab",
38    Match(0, 0),
39    Reject(0, 1),
40    Match(1, 1),
41    Reject(1, 2),
42    Match(2, 2)
43);
44searcher!(searcher_empty_haystack, r"\d", "");
45searcher!(searcher_one_match, r"\d", "5", Match(0, 1));
46searcher!(searcher_no_match, r"\d", "a", Reject(0, 1));
47searcher!(
48    searcher_two_adjacent_matches,
49    r"\d",
50    "56",
51    Match(0, 1),
52    Match(1, 2)
53);
54searcher!(
55    searcher_two_non_adjacent_matches,
56    r"\d",
57    "5a6",
58    Match(0, 1),
59    Reject(1, 2),
60    Match(2, 3)
61);
62searcher!(searcher_reject_first, r"\d", "a6", Reject(0, 1), Match(1, 2));
63searcher!(
64    searcher_one_zero_length_matches,
65    r"\d*",
66    "a1b2",
67    Match(0, 0),  // ^
68    Reject(0, 1), // a
69    Match(1, 2),  // a1
70    Reject(2, 3), // a1b
71    Match(3, 4),  // a1b2
72);
73searcher!(
74    searcher_many_zero_length_matches,
75    r"\d*",
76    "a1bbb2",
77    Match(0, 0),  // ^
78    Reject(0, 1), // a
79    Match(1, 2),  // a1
80    Reject(2, 3), // a1b
81    Match(3, 3),  // a1bb
82    Reject(3, 4), // a1bb
83    Match(4, 4),  // a1bbb
84    Reject(4, 5), // a1bbb
85    Match(5, 6),  // a1bbba
86);
87searcher!(
88    searcher_unicode,
89    r".+?",
90    "Ⅰ1Ⅱ2",
91    Match(0, 3),
92    Match(3, 4),
93    Match(4, 7),
94    Match(7, 8)
95);
96