1#[cfg(test)]
7mod tests {
8 use crate::domain::coordinator::{DomainCoordinator, Operation};
9
10 fn create_operation(id: &str, name: &str, priority: u32, dependencies: Vec<&str>) -> Operation {
11 Operation {
12 id: id.to_string(),
13 name: name.to_string(),
14 priority,
15 dependencies: dependencies.iter().map(|d| d.to_string()).collect(),
16 }
17 }
18
19 #[test]
30 fn property_operation_sequencing_by_priority() {
31 let coordinator = DomainCoordinator::new();
32
33 let operations = vec![
35 create_operation("deploy", "Deploy Application", 3, vec![]),
36 create_operation("setup", "Setup Infrastructure", 1, vec![]),
37 create_operation("migrate", "Database Migration", 2, vec!["setup"]),
38 ];
39
40 for _ in 0..5 {
42 let sequenced = coordinator.sequence_operations(operations.clone()).unwrap();
43
44 assert_eq!(sequenced[0].priority, 1, "First operation should have priority 1");
46 assert_eq!(sequenced[1].priority, 2, "Second operation should have priority 2");
47 assert_eq!(sequenced[2].priority, 3, "Third operation should have priority 3");
48
49 assert_eq!(sequenced[0].id, "setup", "Setup should be first");
51
52 assert_eq!(sequenced[1].id, "migrate", "Migration should be second");
54
55 assert_eq!(sequenced[2].id, "deploy", "Deploy should be last");
57 }
58 }
59
60 #[test]
64 fn property_operation_sequencing_deterministic() {
65 let coordinator = DomainCoordinator::new();
66
67 let operations = vec![
68 create_operation("op1", "Operation 1", 5, vec![]),
69 create_operation("op2", "Operation 2", 2, vec![]),
70 create_operation("op3", "Operation 3", 8, vec![]),
71 create_operation("op4", "Operation 4", 1, vec![]),
72 create_operation("op5", "Operation 5", 3, vec![]),
73 ];
74
75 let mut results = Vec::new();
77 for _ in 0..5 {
78 let sequenced = coordinator.sequence_operations(operations.clone()).unwrap();
79 results.push(sequenced);
80 }
81
82 let first = &results[0];
84 for result in &results[1..] {
85 assert_eq!(result.len(), first.len(), "All sequences should have same length");
86
87 for (i, op) in result.iter().enumerate() {
88 assert_eq!(op.id, first[i].id, "Operation {} ID should be consistent", i);
89 assert_eq!(op.priority, first[i].priority, "Operation {} priority should be consistent", i);
90 }
91 }
92 }
93
94 #[test]
98 fn property_operation_sequencing_respects_dependencies() {
99 let coordinator = DomainCoordinator::new();
100
101 let operations = vec![
103 create_operation("app-deploy", "Deploy Application", 3, vec!["db-migrate"]),
104 create_operation("db-migrate", "Database Migration", 2, vec!["infra-setup"]),
105 create_operation("infra-setup", "Setup Infrastructure", 1, vec![]),
106 ];
107
108 for _ in 0..5 {
109 let sequenced = coordinator.sequence_operations(operations.clone()).unwrap();
110
111 assert_eq!(sequenced[0].id, "infra-setup", "Infrastructure setup should be first");
113
114 assert_eq!(sequenced[1].id, "db-migrate", "Database migration should be second");
116
117 assert_eq!(sequenced[2].id, "app-deploy", "Application deployment should be last");
119
120 let mut seen_ids = std::collections::HashSet::new();
122 for op in &sequenced {
123 for dep in &op.dependencies {
124 assert!(
125 seen_ids.contains(dep),
126 "Dependency {} should be executed before {}",
127 dep,
128 op.id
129 );
130 }
131 seen_ids.insert(op.id.clone());
132 }
133 }
134 }
135
136 #[test]
139 fn property_operation_sequencing_empty_input() {
140 let coordinator = DomainCoordinator::new();
141
142 for _ in 0..5 {
143 let sequenced = coordinator.sequence_operations(vec![]).unwrap();
144
145 assert!(sequenced.is_empty(), "Empty input should produce empty output");
147 }
148 }
149
150 #[test]
153 fn property_operation_sequencing_single_operation() {
154 let coordinator = DomainCoordinator::new();
155
156 let operation = create_operation("single", "Single Operation", 5, vec![]);
157
158 for _ in 0..5 {
159 let sequenced = coordinator.sequence_operations(vec![operation.clone()]).unwrap();
160
161 assert_eq!(sequenced.len(), 1, "Should have one operation");
163 assert_eq!(sequenced[0].id, "single", "Operation ID should be preserved");
164 assert_eq!(sequenced[0].priority, 5, "Operation priority should be preserved");
165 }
166 }
167
168 #[test]
171 fn property_operation_sequencing_stable_sort() {
172 let coordinator = DomainCoordinator::new();
173
174 let operations = vec![
176 create_operation("op1", "Operation 1", 1, vec![]),
177 create_operation("op2", "Operation 2", 1, vec![]),
178 create_operation("op3", "Operation 3", 1, vec![]),
179 ];
180
181 for _ in 0..5 {
182 let sequenced = coordinator.sequence_operations(operations.clone()).unwrap();
183
184 for op in &sequenced {
186 assert_eq!(op.priority, 1, "All operations should have priority 1");
187 }
188
189 assert_eq!(sequenced[0].id, "op1", "First operation should be op1");
191 assert_eq!(sequenced[1].id, "op2", "Second operation should be op2");
192 assert_eq!(sequenced[2].id, "op3", "Third operation should be op3");
193 }
194 }
195
196 #[test]
199 fn property_operation_sequencing_complex_dependencies() {
200 let coordinator = DomainCoordinator::new();
201
202 let operations = vec![
204 create_operation("app", "Deploy App", 5, vec!["db", "cache"]),
205 create_operation("db", "Setup Database", 2, vec!["infra"]),
206 create_operation("cache", "Setup Cache", 3, vec!["infra"]),
207 create_operation("infra", "Setup Infrastructure", 1, vec![]),
208 create_operation("monitor", "Setup Monitoring", 4, vec!["infra"]),
209 ];
210
211 for _ in 0..3 {
212 let sequenced = coordinator.sequence_operations(operations.clone()).unwrap();
213
214 assert_eq!(sequenced[0].id, "infra", "Infrastructure should be first");
216
217 let mut seen_ids = std::collections::HashSet::new();
219 for op in &sequenced {
220 for dep in &op.dependencies {
221 assert!(
222 seen_ids.contains(dep),
223 "Dependency {} should be executed before {}",
224 dep,
225 op.id
226 );
227 }
228 seen_ids.insert(op.id.clone());
229 }
230
231 assert_eq!(sequenced[sequenced.len() - 1].id, "app", "App deployment should be last");
233 }
234 }
235
236 #[test]
239 fn property_operation_sequencing_priority_ordering() {
240 let coordinator = DomainCoordinator::new();
241
242 let operations = vec![
244 create_operation("op10", "Operation 10", 10, vec![]),
245 create_operation("op5", "Operation 5", 5, vec![]),
246 create_operation("op1", "Operation 1", 1, vec![]),
247 create_operation("op7", "Operation 7", 7, vec![]),
248 create_operation("op3", "Operation 3", 3, vec![]),
249 ];
250
251 for _ in 0..5 {
252 let sequenced = coordinator.sequence_operations(operations.clone()).unwrap();
253
254 for i in 0..sequenced.len() - 1 {
256 assert!(
257 sequenced[i].priority <= sequenced[i + 1].priority,
258 "Priority should be non-decreasing"
259 );
260 }
261
262 assert_eq!(sequenced[0].priority, 1);
264 assert_eq!(sequenced[1].priority, 3);
265 assert_eq!(sequenced[2].priority, 5);
266 assert_eq!(sequenced[3].priority, 7);
267 assert_eq!(sequenced[4].priority, 10);
268 }
269 }
270
271 #[test]
274 fn property_operation_sequencing_data_preservation() {
275 let coordinator = DomainCoordinator::new();
276
277 let operations = vec![
278 create_operation("op1", "Operation 1", 3, vec!["dep1", "dep2"]),
279 create_operation("op2", "Operation 2", 1, vec![]),
280 create_operation("op3", "Operation 3", 2, vec!["dep3"]),
281 ];
282
283 for _ in 0..5 {
284 let sequenced = coordinator.sequence_operations(operations.clone()).unwrap();
285
286 assert_eq!(sequenced.len(), 3, "All operations should be present");
288
289 let op1 = sequenced.iter().find(|op| op.id == "op1").unwrap();
291 assert_eq!(op1.name, "Operation 1");
292 assert_eq!(op1.priority, 3);
293 assert_eq!(op1.dependencies.len(), 2);
294 assert!(op1.dependencies.contains(&"dep1".to_string()));
295 assert!(op1.dependencies.contains(&"dep2".to_string()));
296
297 let op2 = sequenced.iter().find(|op| op.id == "op2").unwrap();
298 assert_eq!(op2.name, "Operation 2");
299 assert_eq!(op2.priority, 1);
300 assert!(op2.dependencies.is_empty());
301
302 let op3 = sequenced.iter().find(|op| op.id == "op3").unwrap();
303 assert_eq!(op3.name, "Operation 3");
304 assert_eq!(op3.priority, 2);
305 assert_eq!(op3.dependencies.len(), 1);
306 assert!(op3.dependencies.contains(&"dep3".to_string()));
307 }
308 }
309
310 #[test]
314 fn property_operation_sequencing_large_number() {
315 let coordinator = DomainCoordinator::new();
316
317 let mut operations = Vec::new();
319 for i in 0..100 {
320 let priority = (i * 7) % 100; operations.push(create_operation(
322 &format!("op{}", i),
323 &format!("Operation {}", i),
324 priority as u32,
325 vec![],
326 ));
327 }
328
329 for _ in 0..3 {
330 let sequenced = coordinator.sequence_operations(operations.clone()).unwrap();
331
332 assert_eq!(sequenced.len(), 100, "All 100 operations should be present");
334
335 for i in 0..sequenced.len() - 1 {
337 assert!(
338 sequenced[i].priority <= sequenced[i + 1].priority,
339 "Operations should be sorted by priority"
340 );
341 }
342 }
343 }
344}