verify_call/
lib.rs

1#![warn(missing_docs)]
2#![warn(rustdoc::missing_doc_code_examples)]
3#![warn(missing_debug_implementations)]
4#![warn(rust_2018_idioms)]
5
6//! ...
7
8use std::fmt::Debug;
9use std::sync::{Arc, Mutex};
10
11/// ...
12pub fn pair<T>() -> (Verifier<T>, Caller<T>) {
13    let calls = Arc::new(Mutex::new(Some(Vec::new())));
14
15    let matcher = Verifier {
16        calls: calls.clone(),
17    };
18
19    let spy = Caller { calls };
20
21    (matcher, spy)
22}
23
24/// ...
25#[derive(Debug)]
26pub struct Caller<T> {
27    calls: Arc<Mutex<Option<Vec<T>>>>,
28}
29
30impl<T> Caller<T> {
31    /// ...
32    pub fn call(&self, value: T) {
33        let mut guard = self.calls.lock().unwrap();
34
35        match guard.as_mut() {
36            Some(calls) => calls.push(value),
37            None => panic!("verify_call received a call after the verifier was consumed"),
38        }
39    }
40}
41
42/// ...
43#[derive(Debug)]
44pub struct Verifier<T> {
45    calls: Arc<Mutex<Option<Vec<T>>>>,
46}
47
48impl<T> Verifier<T> {
49    /// ...
50    pub fn calls(self) -> Vec<T> {
51        let mut guard = self.calls.lock().unwrap();
52        guard.take().unwrap()
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    mod caller {
61        use super::*;
62
63        #[test]
64        fn implements_traits() {
65            use impls::impls;
66            use std::fmt::Debug;
67
68            // Given
69            struct NotDebug;
70
71            // Then
72            assert!(impls!(Caller<i32>: Debug & Send & Sync & !Clone));
73            assert!(impls!(Caller<NotDebug>: !Debug & Send & Sync & !Clone));
74        }
75
76        #[test]
77        fn is_thread_safe() {
78            // Given
79            let (verifier, caller) = pair();
80            let handle = std::thread::spawn(move || {
81                caller.call(1);
82            });
83
84            // When
85            handle.join().unwrap();
86            let calls = verifier.calls();
87
88            // Then
89            assert_eq!(calls, &[1]);
90        }
91
92        #[test]
93        #[should_panic(expected = "verify_call received a call after the verifier was consumed")]
94        fn panics_when_called_after_verification() {
95            // Given
96            let (verifier, caller) = pair();
97            let _calls = verifier.calls();
98
99            // When
100            caller.call(3);
101        }
102    }
103
104    mod verifier {
105        use super::*;
106
107        #[test]
108        fn implements_traits() {
109            use impls::impls;
110            use std::fmt::Debug;
111
112            // Given
113            struct NotDebug;
114
115            // Then
116            assert!(impls!(Verifier<i32>: Debug & Send & Sync & !Clone));
117            assert!(impls!(Verifier<NotDebug>: !Debug & Send & Sync & !Clone));
118        }
119
120        #[test]
121        fn initially_has_no_calls() {
122            // Given
123            let (verifier, _caller) = pair::<()>();
124
125            // When
126            let calls = verifier.calls();
127
128            // Then
129            assert_eq!(calls.len(), 0);
130        }
131
132        #[test]
133        fn receives_calls_from_caller() {
134            // Given
135            let (verifier, caller) = pair();
136            caller.call(1);
137            caller.call(2);
138            caller.call(3);
139
140            // When
141            let calls = verifier.calls();
142
143            // Then
144            assert_eq!(calls, &[1, 2, 3]);
145        }
146    }
147}