sofie_values/fixture/
calls.rs1use std::sync::{Mutex, MutexGuard};
2
3use sofie_core::{Error, Result, unpoisoned};
4
5use super::{Fixture, Seed};
6
7#[derive(Default)]
8pub struct Calls {
9 state: Mutex<State>,
10}
11
12#[derive(Default)]
13struct State {
14 made: Vec<&'static str>,
15 failing: Vec<&'static str>,
16 seed: Seed,
17}
18
19impl Calls {
20 pub fn answer<T: Fixture>(&self, method: &'static str) -> Result<T> {
21 let mut state = self.state();
22 state.made.push(method);
23 if state.failing.contains(&method) {
24 return Err(Error::Unavailable(format!("the fake fails `{method}`")));
25 }
26 Ok(T::fixture(&mut state.seed))
27 }
28
29 pub fn value<T: Fixture>(&self, method: &'static str) -> T {
30 let mut state = self.state();
31 state.made.push(method);
32 T::fixture(&mut state.seed)
33 }
34
35 pub fn fail(&self, method: &'static str) {
36 self.state().failing.push(method);
37 }
38
39 #[must_use]
40 pub fn made(&self) -> Vec<&'static str> {
41 self.state().made.clone()
42 }
43
44 fn state(&self) -> MutexGuard<'_, State> {
45 unpoisoned::lock(&self.state)
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn records_each_call_and_fails_the_methods_it_is_told_to() {
55 let calls = Calls::default();
56
57 let answered: Result<i64> = calls.answer("find");
58 calls.fail("find");
59 let failed: Result<i64> = calls.answer("find");
60
61 assert!(answered.is_ok());
62 assert!(matches!(failed, Err(Error::Unavailable(_))));
63 assert_eq!(calls.made(), ["find", "find"]);
64 }
65}