Skip to main content

clankers_testing/
context.rs

1use std::path::PathBuf;
2
3use clankers_core::{LatencyStats, RobotResult};
4use clankers_data::{Replay, ReplayResult};
5
6/// Context for replay-based tests.
7pub struct ReplayContext {
8    pub mcap_path: PathBuf,
9    pub deterministic: bool,
10}
11
12#[derive(Debug, Clone)]
13pub struct ReplayTestResult {
14    pub replay: ReplayResult,
15    pub panics: u32,
16    pub topics_seen: Vec<String>,
17}
18
19impl ReplayContext {
20    pub fn new(mcap_path: impl Into<PathBuf>) -> Self {
21        Self {
22            mcap_path: mcap_path.into(),
23            deterministic: true,
24        }
25    }
26
27    pub async fn run_replay<F, Fut>(&self, mut handler: F) -> RobotResult<ReplayTestResult>
28    where
29        F: FnMut(clankers_data::McapRecord) -> Fut,
30        Fut: std::future::Future<Output = RobotResult<()>>,
31    {
32        let replay = Replay::from_mcap(&self.mcap_path)?;
33        let mut topics_seen = std::collections::HashSet::new();
34
35        let result = replay
36            .run(|msg| {
37                topics_seen.insert(msg.topic.clone());
38                handler(msg)
39            })
40            .await?;
41
42        let mut topics: Vec<_> = topics_seen.into_iter().collect();
43        topics.sort();
44
45        Ok(ReplayTestResult {
46            replay: result,
47            panics: 0,
48            topics_seen: topics,
49        })
50    }
51
52    pub fn latency(&self) -> &LatencyStats {
53        // convenience for assertions after run
54        unimplemented!("call result.replay.latency after run_replay")
55    }
56}