1#![warn(missing_docs)]
2#![warn(rustdoc::missing_doc_code_examples)]
3#![warn(missing_debug_implementations)]
4#![warn(rust_2018_idioms)]
5
6use std::fmt::Debug;
9use std::sync::{Arc, Mutex};
10
11pub 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#[derive(Debug)]
26pub struct Caller<T> {
27 calls: Arc<Mutex<Option<Vec<T>>>>,
28}
29
30impl<T> Caller<T> {
31 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#[derive(Debug)]
44pub struct Verifier<T> {
45 calls: Arc<Mutex<Option<Vec<T>>>>,
46}
47
48impl<T> Verifier<T> {
49 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 struct NotDebug;
70
71 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 let (verifier, caller) = pair();
80 let handle = std::thread::spawn(move || {
81 caller.call(1);
82 });
83
84 handle.join().unwrap();
86 let calls = verifier.calls();
87
88 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 let (verifier, caller) = pair();
97 let _calls = verifier.calls();
98
99 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 struct NotDebug;
114
115 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 let (verifier, _caller) = pair::<()>();
124
125 let calls = verifier.calls();
127
128 assert_eq!(calls.len(), 0);
130 }
131
132 #[test]
133 fn receives_calls_from_caller() {
134 let (verifier, caller) = pair();
136 caller.call(1);
137 caller.call(2);
138 caller.call(3);
139
140 let calls = verifier.calls();
142
143 assert_eq!(calls, &[1, 2, 3]);
145 }
146 }
147}