1use std::sync::Arc;
2use std::sync::Mutex;
3
4pub fn verify<I: PartialEq>(validator: Validator<I>) -> bool {
5 validator.called()
6}
7
8pub struct Validator<I> {
9 calls: Arc<Mutex<Vec<I>>>,
10 result: Option<bool>,
11 input: I,
12}
13
14impl<I> Validator<I> {
15 pub fn new(calls: Arc<Mutex<Vec<I>>>, input: I) -> Validator<I> {
16 Validator {
17 calls,
18 result: None,
19 input,
20 }
21 }
22}
23
24impl<I: PartialEq> Validator<I> {
25 pub fn result(&mut self) -> bool {
26 match self.result {
27 Some(val) => val,
28 None => {
29 let calls = self.calls.lock().unwrap();
30 let was_called = calls.iter().any(|value| value == &self.input);
31 self.result = Some(was_called);
32 was_called
33 }
34 }
35 }
36 pub fn times(mut self, times: usize) -> Validator<I> {
37 let times_called = {
38 let calls = self.calls.lock().unwrap();
39 calls.iter().filter(|value| *value == &self.input).count()
40 };
41
42 if times_called != times {
43 self.result = Some(false)
44 }
45
46 self
47 }
48 pub fn called(self) -> bool {
49 let mut this = self;
50 this.result()
51 }
52}
53
54#[cfg(test)]
55mod test {
56 use super::*;
57 use table_test::table_test;
58
59 #[test]
60 fn times() {
61 let table = vec![
62 ((vec![1, 1, 3], true, 1, 1), false),
63 ((vec![1, 1, 3], true, 1, 2), true),
64 ((vec![1, 1, 3], true, 3, 1), true),
65 ((vec![1, 1, 3], false, 3, 1), false),
66 ((vec![1, 1, 3], false, 3, 1), false),
67 ((vec![1, 1, 3], false, 3, 1), false),
68 ];
69
70 for (test_case, (calls, initial_result, input, times), expected) in table_test!(table) {
71 let mut validator = Validator::new(Arc::new(Mutex::new(calls.clone())), input);
72 validator.result = Some(initial_result);
73
74 let actual = verify(validator.times(times));
75
76 test_case
77 .given(&format!(
78 "Validator: calls {:?}, initial_result {:?}, input {:?}",
79 calls, initial_result, input
80 ))
81 .given(&format!("times {:?}", times))
82 .when("verify validator")
83 .then(&format!("{:?}", expected))
84 .assert_eq(expected, actual);
85 }
86 }
87}