parameterized_macro/
tests.rs

1use indexmap::IndexMap;
2use std::fmt::Formatter;
3
4pub struct TestCases<'node> {
5    map: IndexMap<&'node syn::Ident, Vec<&'node syn::Expr>>,
6    amount_of_test_cases: Option<usize>,
7}
8
9impl std::fmt::Debug for TestCases<'_> {
10    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
11        let ids = self
12            .map
13            .iter()
14            .map(|(id, _)| format!("{}", id))
15            .collect::<Vec<String>>();
16        let joined = ids.join(", ");
17        f.write_str(&format!("TestCases {{  identifiers = {} }}", joined))
18    }
19}
20
21impl<'node> TestCases<'node> {
22    pub fn empty() -> Self {
23        Self {
24            map: IndexMap::new(),
25            amount_of_test_cases: None,
26        }
27    }
28
29    pub fn insert(&mut self, id: &'node syn::Ident, exprs: Vec<&'node syn::Expr>) {
30        let expressions = exprs.len();
31
32        //
33        match self.amount_of_test_cases {
34            Some(amount) if amount != expressions => panic!(
35                "parameterized-macro error: Each test-case parameter should have an equal amount of values passed to it.\n\
36                    Expected {} arguments for '{}', but got: {}", amount, id, expressions,
37            ),
38            Some(_) => {}
39            None => {
40                self.amount_of_test_cases = Some(expressions)
41            },
42        };
43
44        //
45        if expressions != self.unwrap_amount_of_test_cases() {
46            panic!(
47                "parameterized-macro: error: Each test-case parameter should have an equal amount of values passed to it.\n\
48                    Expected {} arguments for '{}', but got: {}", self.unwrap_amount_of_test_cases(), id, expressions,
49            );
50        }
51
52        // Only insert if the id does not yet exist
53        if self.map.get(id).is_none() {
54            self.map.insert(id, exprs);
55        } else {
56            panic!(
57                "parameterized-macro: error: found duplicate entry for '{}'",
58                id
59            );
60        }
61    }
62
63    pub fn get(&self, id: &syn::Ident, ith: usize) -> &syn::Expr {
64        if let Some(exprs) = self.map.get(id) {
65            exprs[ith]
66        } else {
67            panic!(
68                "parameterized-macro: error: Unable to find value for parameter '{}' (case #{})",
69                id, ith
70            );
71        }
72    }
73
74    pub fn amount_of_test_cases(&self) -> Option<usize> {
75        self.amount_of_test_cases
76    }
77
78    // NB: Panics if amount of test cases is unknown, i.e. if we haven't used the first parameter
79    //    to seed the amount of expressions required to be defined for each parameter.
80    //    This should never happen to 'parameterized' crate users, and must be guarded against in the
81    //    places where it's used.
82    fn unwrap_amount_of_test_cases(&self) -> usize {
83        if let Some(amount) = self.amount_of_test_cases {
84            amount
85        } else {
86            unreachable!()
87        }
88    }
89}