runmat_test/event/
replay.rs1use 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}