toasty_driver_integration_suite/
exec_log.rs

1use crate::logging_driver::DriverOp;
2use std::{
3    fmt,
4    sync::{Arc, Mutex},
5};
6use toasty_core::driver::{Operation, Response};
7
8/// A wrapper around the operations log that provides a clean API for tests
9pub struct ExecLog {
10    ops: Arc<Mutex<Vec<DriverOp>>>,
11}
12
13impl ExecLog {
14    pub(crate) fn new(ops: Arc<Mutex<Vec<DriverOp>>>) -> Self {
15        Self { ops }
16    }
17
18    /// Get the number of logged operations
19    pub fn len(&self) -> usize {
20        self.ops.lock().unwrap().len()
21    }
22
23    /// Check if the log is empty
24    pub fn is_empty(&self) -> bool {
25        self.ops.lock().unwrap().is_empty()
26    }
27
28    /// Clear the log
29    pub fn clear(&mut self) {
30        self.ops.lock().unwrap().clear();
31    }
32
33    /// Remove and return the first operation from the log
34    /// Returns None if the log is empty
35    #[track_caller]
36    pub fn pop(&mut self) -> (Operation, Response) {
37        let mut ops = self.ops.lock().unwrap();
38        if ops.is_empty() {
39            panic!("no operations in log");
40        } else {
41            let driver_op = ops.remove(0);
42            (driver_op.operation, driver_op.response)
43        }
44    }
45
46    #[track_caller]
47    pub fn pop_op(&mut self) -> Operation {
48        self.pop().0
49    }
50}
51
52impl fmt::Debug for ExecLog {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        let ops = self.ops.lock().unwrap();
55        f.debug_struct("ExecLog").field("ops", &*ops).finish()
56    }
57}