mockforge_foundation/state_machine/
sub_scenario.rs1use super::rules::StateMachine;
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
16#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
17pub struct SubScenario {
18 pub id: String,
20
21 pub name: String,
23
24 pub state_machine: StateMachine,
26
27 #[serde(default)]
31 pub input_mapping: HashMap<String, String>,
32
33 #[serde(default)]
37 pub output_mapping: HashMap<String, String>,
38
39 pub description: Option<String>,
41}
42
43impl SubScenario {
44 pub fn new(
46 id: impl Into<String>,
47 name: impl Into<String>,
48 state_machine: StateMachine,
49 ) -> Self {
50 Self {
51 id: id.into(),
52 name: name.into(),
53 state_machine,
54 input_mapping: HashMap::new(),
55 output_mapping: HashMap::new(),
56 description: None,
57 }
58 }
59
60 pub fn with_description(mut self, description: impl Into<String>) -> Self {
62 self.description = Some(description.into());
63 self
64 }
65
66 pub fn with_input_mapping(
70 mut self,
71 parent_var: impl Into<String>,
72 sub_var: impl Into<String>,
73 ) -> Self {
74 self.input_mapping.insert(parent_var.into(), sub_var.into());
75 self
76 }
77
78 pub fn with_output_mapping(
82 mut self,
83 sub_var: impl Into<String>,
84 parent_var: impl Into<String>,
85 ) -> Self {
86 self.output_mapping.insert(sub_var.into(), parent_var.into());
87 self
88 }
89
90 pub fn state_machine(&self) -> &StateMachine {
92 &self.state_machine
93 }
94
95 pub fn state_machine_mut(&mut self) -> &mut StateMachine {
97 &mut self.state_machine
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use crate::state_machine::rules::{StateMachine, StateTransition};
105
106 #[test]
107 fn test_sub_scenario_creation() {
108 let nested_machine = StateMachine::new(
109 "sub_resource",
110 vec!["start".to_string(), "end".to_string()],
111 "start",
112 );
113
114 let sub_scenario = SubScenario::new("sub1", "Test Sub-Scenario", nested_machine)
115 .with_description("A test sub-scenario")
116 .with_input_mapping("parent.status", "sub.input.status")
117 .with_output_mapping("sub.output.result", "parent.result");
118
119 assert_eq!(sub_scenario.id, "sub1");
120 assert_eq!(sub_scenario.name, "Test Sub-Scenario");
121 assert_eq!(sub_scenario.input_mapping.len(), 1);
122 assert_eq!(sub_scenario.output_mapping.len(), 1);
123 assert_eq!(
124 sub_scenario.input_mapping.get("parent.status"),
125 Some(&"sub.input.status".to_string())
126 );
127 }
128
129 #[test]
130 fn test_sub_scenario_serialization() {
131 let nested_machine = StateMachine::new(
132 "sub_resource",
133 vec!["start".to_string(), "end".to_string()],
134 "start",
135 )
136 .add_transition(StateTransition::new("start", "end"));
137
138 let sub_scenario = SubScenario::new("sub1", "Test", nested_machine)
139 .with_input_mapping("parent.x", "sub.x");
140
141 let json = serde_json::to_string(&sub_scenario).unwrap();
142 let deserialized: SubScenario = serde_json::from_str(&json).unwrap();
143
144 assert_eq!(deserialized.id, "sub1");
145 assert_eq!(deserialized.input_mapping.len(), 1);
146 }
147}