Skip to main content

runmat_test/event/
replay.rs

1use crate::error::TestDomainError;
2use crate::identity::RunId;
3use crate::result::{AttemptResult, RunResult};
4
5use super::{TestEvent, TestEventPayload};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
8pub struct ReplayedEvents {
9    pub run_id: RunId,
10    pub attempts: Vec<AttemptResult>,
11    pub result: RunResult,
12}
13
14pub fn replay(events: &[TestEvent]) -> Result<ReplayedEvents, TestDomainError> {
15    let first = events
16        .first()
17        .ok_or(TestDomainError::IncompleteEventStream)?;
18    if !matches!(first.payload, TestEventPayload::RunStarted)
19        || !matches!(
20            events.last().map(|event| &event.payload),
21            Some(TestEventPayload::RunFinished { .. })
22        )
23    {
24        return Err(TestDomainError::IncompleteEventStream);
25    }
26    let run_id = first.run_id.clone();
27    let mut attempts = Vec::new();
28    let mut result = None;
29    for (expected, event) in events.iter().enumerate() {
30        if event.sequence != expected as u64 {
31            return Err(TestDomainError::EventSequence {
32                expected: expected as u64,
33                actual: event.sequence,
34            });
35        }
36        if event.run_id != run_id {
37            return Err(TestDomainError::EventRunMismatch);
38        }
39        match &event.payload {
40            TestEventPayload::TestFinished { result } => attempts.push(result.clone()),
41            TestEventPayload::RunFinished { result: run_result } => {
42                if result.is_some() || event.sequence + 1 != events.len() as u64 {
43                    return Err(TestDomainError::IncompleteEventStream);
44                }
45                result = Some(run_result.clone());
46            }
47            _ => {}
48        }
49    }
50    let result = result.ok_or(TestDomainError::IncompleteEventStream)?;
51    Ok(ReplayedEvents {
52        run_id,
53        attempts,
54        result,
55    })
56}