trellis_testing/
serialized.rs1use trellis_core::TransactionTrace;
2
3use crate::{Scenario, ScenarioError};
4
5pub const TRACE_FORMAT_VERSION: u32 = 1;
7
8#[derive(Clone, Debug, Eq, PartialEq)]
10#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
11#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
12pub struct DataTransactionScript<Operation> {
13 format_version: u32,
14 steps: Vec<DataScriptStep<Operation>>,
15}
16
17#[derive(Clone, Debug, Eq, PartialEq)]
19#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
20#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
21pub struct DataScriptStep<Operation> {
22 name: String,
23 operations: Vec<Operation>,
24}
25
26pub struct DataScriptStepBuilder<'script, Operation> {
28 script: &'script mut DataTransactionScript<Operation>,
29 name: String,
30 operations: Vec<Operation>,
31}
32
33#[derive(Clone, Debug, Eq, PartialEq)]
35#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
36#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
37pub struct SerializedScenario {
38 format_version: u32,
39 steps: Vec<SerializedScenarioStep>,
40}
41
42#[derive(Clone, Debug, Eq, PartialEq)]
44#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
45#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
46pub struct SerializedScenarioStep {
47 pub name: String,
49 pub trace: TransactionTrace,
51}
52
53impl<Operation> DataTransactionScript<Operation> {
54 pub fn new() -> Self {
56 Self {
57 format_version: TRACE_FORMAT_VERSION,
58 steps: Vec::new(),
59 }
60 }
61
62 pub fn step(&mut self, name: impl Into<String>) -> DataScriptStepBuilder<'_, Operation> {
64 DataScriptStepBuilder {
65 script: self,
66 name: name.into(),
67 operations: Vec::new(),
68 }
69 }
70
71 pub fn format_version(&self) -> u32 {
73 self.format_version
74 }
75
76 pub fn steps(&self) -> &[DataScriptStep<Operation>] {
78 &self.steps
79 }
80
81 pub fn validate_format_version(&self) -> Result<(), ScenarioError> {
83 validate_format_version(self.format_version)
84 }
85
86 #[cfg(feature = "serde")]
88 pub fn to_json(&self) -> Result<String, serde_json::Error>
89 where
90 Operation: serde::Serialize,
91 {
92 serde_json::to_string_pretty(self)
93 }
94
95 #[cfg(feature = "serde")]
97 pub fn from_json(json: &str) -> Result<Self, serde_json::Error>
98 where
99 Operation: serde::de::DeserializeOwned,
100 {
101 serde_json::from_str(json)
102 }
103}
104
105impl<Operation> Default for DataTransactionScript<Operation> {
106 fn default() -> Self {
107 Self::new()
108 }
109}
110
111impl<Operation> DataScriptStep<Operation> {
112 pub fn name(&self) -> &str {
114 &self.name
115 }
116
117 pub fn operations(&self) -> &[Operation] {
119 &self.operations
120 }
121}
122
123impl<Operation> DataScriptStepBuilder<'_, Operation> {
124 pub fn operation(mut self, operation: Operation) -> Self {
126 self.operations.push(operation);
127 self
128 }
129
130 pub fn commit(self) {
132 self.script.steps.push(DataScriptStep {
133 name: self.name,
134 operations: self.operations,
135 });
136 }
137}
138
139impl SerializedScenario {
140 pub fn from_scenario(scenario: &Scenario) -> Self {
142 Self {
143 format_version: TRACE_FORMAT_VERSION,
144 steps: scenario
145 .steps()
146 .iter()
147 .map(|step| SerializedScenarioStep {
148 name: step.name.clone(),
149 trace: step.trace.clone(),
150 })
151 .collect(),
152 }
153 }
154
155 pub fn format_version(&self) -> u32 {
157 self.format_version
158 }
159
160 pub fn steps(&self) -> &[SerializedScenarioStep] {
162 &self.steps
163 }
164
165 pub fn into_scenario(self) -> Result<Scenario, ScenarioError> {
167 validate_format_version(self.format_version)?;
168 let mut scenario = Scenario::new();
169 for step in self.steps {
170 scenario.record_trace(step.name, step.trace)?;
171 }
172 Ok(scenario)
173 }
174
175 pub fn assert_matches_scenario(&self, actual: &Scenario) -> Result<(), ScenarioError> {
177 self.clone().into_scenario()?.assert_replay_matches(actual)
178 }
179
180 #[cfg(feature = "serde")]
182 pub fn to_json(&self) -> Result<String, serde_json::Error> {
183 serde_json::to_string_pretty(self)
184 }
185
186 #[cfg(feature = "serde")]
188 pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
189 serde_json::from_str(json)
190 }
191}
192
193fn validate_format_version(actual: u32) -> Result<(), ScenarioError> {
194 if actual == TRACE_FORMAT_VERSION {
195 Ok(())
196 } else {
197 Err(ScenarioError::TraceFormatVersionMismatch {
198 expected: TRACE_FORMAT_VERSION,
199 actual,
200 })
201 }
202}