hotshot_testing/
script.rs1use std::{sync::Arc, time::Duration};
8
9use hotshot_task_impls::events::HotShotEvent;
10use hotshot_types::traits::node_implementation::NodeType;
11
12use crate::predicates::{Predicate, PredicateResult};
13
14pub enum InputOrder<TYPES: NodeType> {
15 Random(Vec<HotShotEvent<TYPES>>),
16 Serial(Vec<HotShotEvent<TYPES>>),
17}
18
19#[macro_export]
20macro_rules! random {
21 ($($x:expr),* $(,)?) => {
22 {
23 let inputs = vec![$($x),*];
24 InputOrder::Random(inputs)
25 }
26 };
27}
28
29#[macro_export]
30macro_rules! serial {
31 ($($x:expr),* $(,)?) => {
32 {
33 let inputs = vec![$($x),*];
34 InputOrder::Serial(inputs)
35 }
36 };
37}
38
39pub struct TaskScript<TYPES: NodeType, S> {
40 pub timeout: Duration,
42 pub state: S,
43 pub expectations: Vec<Expectations<TYPES, S>>,
44}
45
46pub struct Expectations<TYPES: NodeType, S> {
47 pub output_asserts: Vec<Box<dyn Predicate<Arc<HotShotEvent<TYPES>>>>>,
48 pub task_state_asserts: Vec<Box<dyn Predicate<S>>>,
49}
50
51impl<TYPES: NodeType, S> Expectations<TYPES, S> {
52 pub fn from_outputs(output_asserts: Vec<Box<dyn Predicate<Arc<HotShotEvent<TYPES>>>>>) -> Self {
53 Self {
54 output_asserts,
55 task_state_asserts: vec![],
56 }
57 }
58 pub fn from_outputs_and_task_states(
59 output_asserts: Vec<Box<dyn Predicate<Arc<HotShotEvent<TYPES>>>>>,
60 task_state_asserts: Vec<Box<dyn Predicate<S>>>,
61 ) -> Self {
62 Self {
63 output_asserts,
64 task_state_asserts,
65 }
66 }
67}
68
69pub fn panic_extra_output_in_script<S>(stage_number: usize, script_name: String, output: &S)
70where
71 S: std::fmt::Debug,
72{
73 let extra_output_error = format!(
74 "Stage {stage_number} | Received unexpected additional output in \
75 {script_name}:\n\n{output:?}"
76 );
77
78 panic!("{}", extra_output_error);
79}
80
81pub fn panic_missing_output_in_script<S>(stage_number: usize, script_name: String, predicate: &S)
82where
83 S: std::fmt::Debug,
84{
85 let output_missing_error = format!(
86 "Stage {stage_number} | Failed to receive output for predicate in {script_name}: \
87 {predicate:?}"
88 );
89
90 panic!("{}", output_missing_error);
91}
92
93pub async fn validate_task_state_or_panic_in_script<S>(
94 stage_number: usize,
95 script_name: String,
96 state: &S,
97 assert: &dyn Predicate<S>,
98) {
99 assert!(
100 assert.evaluate(state).await == PredicateResult::Pass,
101 "Stage {stage_number} | Task state in {script_name} failed to satisfy: {assert:?}"
102 );
103}
104
105pub async fn validate_output_or_panic_in_script<S: std::fmt::Debug>(
106 stage_number: usize,
107 script_name: String,
108 output: &S,
109 assert: &dyn Predicate<S>,
110) -> PredicateResult {
111 let result = assert.evaluate(output).await;
112
113 match result {
114 PredicateResult::Pass => result,
115 PredicateResult::Incomplete => result,
116 PredicateResult::Fail => {
117 panic!(
118 "Stage {stage_number} | Output in {script_name} failed to satisfy: \
119 {assert:?}.\n\nReceived:\n\n{output:?}"
120 )
121 },
122 }
123}