1use std::fmt::Debug;
2
3pub mod highlighter;
4
5pub trait Token {
7 type Rule;
8
9 fn start(&self) -> usize;
10 fn end(&self) -> usize;
11 fn rule(&self) -> Self::Rule;
12}
13
14pub struct TestToken<R> {
15 pub start: usize,
16 pub end: usize,
17 pub rule: R,
18}
19
20impl<R: Copy> Token for TestToken<R> {
21 type Rule = R;
22
23 fn start(&self) -> usize {
24 self.start
25 }
26 fn end(&self) -> usize {
27 self.end
28 }
29 fn rule(&self) -> Self::Rule {
30 self.rule
31 }
32}
33
34pub fn test<O, E, R>(output: O, expected: E, spans: &str) -> bool
35 where O: IntoIterator,
36 <O as IntoIterator>::Item: Token<Rule = R>,
37 E: IntoIterator<Item = R>,
38 R: Eq + Sized + Debug,
39{
40 let mut expected_spans = highlighter::Highlighter::new(spans);
41 let mut expected = expected.into_iter();
42 for actual_output in output {
43 let expected_span = expected_spans.next().expect("Not enough spans defined");
44 let expected_output = expected.next().expect("More output than expected");
45 if actual_output.rule() != expected_output {
46 panic!("Expected rule: {:?} got: {:?} at pos:{}",
47 expected_output,
48 actual_output.rule(),
49 actual_output.start()
50 );
51 }
52 if actual_output.start() != expected_span.0 || actual_output.end() != expected_span.1 {
53 panic!("Spans do not match on rule: {:?}: [{}, {}] vs [{}, {}]",
54 actual_output.rule(),
55 actual_output.start(),
56 actual_output.end(),
57 expected_span.0,
58 expected_span.1
59 );
60 }
61 }
62 assert!(expected.next().is_none(), "Expected more output");
63 assert!(expected_spans.next().is_none(), "Defined more spans than expected rules");
64
65 true
66}