1pub mod aggregators;
20pub mod engine;
21pub mod model;
22pub mod query;
23
24pub use engine::WorldStateEngine;
25pub use model::{StateEdge, StateLayer, StateNode, WorldStateSnapshot};
26pub use query::WorldStateQuery;
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31 use model::{NodeType, StateEdge, StateLayer, StateNode, WorldStateSnapshot};
32 use query::WorldStateQuery;
33 use std::collections::HashSet;
34
35 #[test]
36 fn test_module_exports() {
37 let _snapshot: WorldStateSnapshot;
39 let _node: StateNode;
40 let _edge: StateEdge;
41 let _layer: StateLayer;
42 let _engine: WorldStateEngine;
43 let _query: WorldStateQuery;
44 }
45
46 #[test]
47 fn test_create_world_state_snapshot() {
48 let snapshot = WorldStateSnapshot::new();
49 assert!(!snapshot.id.is_empty());
50 assert!(snapshot.nodes.is_empty());
51 assert!(snapshot.edges.is_empty());
52 }
53
54 #[test]
55 fn test_create_state_node() {
56 let node = StateNode::new(
57 "test-id".to_string(),
58 "Test Label".to_string(),
59 NodeType::Persona,
60 StateLayer::Personas,
61 );
62
63 assert_eq!(node.id, "test-id");
64 assert_eq!(node.label, "Test Label");
65 assert_eq!(node.node_type, NodeType::Persona);
66 assert_eq!(node.layer, StateLayer::Personas);
67 }
68
69 #[test]
70 fn test_create_state_edge() {
71 let edge = StateEdge::new(
72 "from-node".to_string(),
73 "to-node".to_string(),
74 "relationship".to_string(),
75 );
76
77 assert_eq!(edge.from, "from-node");
78 assert_eq!(edge.to, "to-node");
79 assert_eq!(edge.relationship_type, "relationship");
80 }
81
82 #[test]
83 fn test_state_layer_all() {
84 let layers = StateLayer::all();
85 assert!(!layers.is_empty());
86 assert!(layers.contains(&StateLayer::Personas));
87 assert!(layers.contains(&StateLayer::Lifecycle));
88 }
89
90 #[test]
91 fn test_world_state_query_builder() {
92 let mut node_types = HashSet::new();
93 node_types.insert(NodeType::Persona);
94
95 let query = WorldStateQuery::new().with_node_types(node_types.clone());
96
97 assert_eq!(query.node_types, Some(node_types));
98 }
99
100 #[test]
101 fn test_world_state_engine_creation() {
102 let engine = WorldStateEngine::new();
103 let layers = engine.get_layers();
104 assert!(layers.is_empty());
105 }
106
107 #[test]
108 fn test_integration_snapshot_with_nodes_and_edges() {
109 let mut snapshot = WorldStateSnapshot::new();
110
111 let node1 = StateNode::new(
113 "user-1".to_string(),
114 "User 1".to_string(),
115 NodeType::Entity,
116 StateLayer::Lifecycle,
117 );
118
119 let node2 = StateNode::new(
120 "order-1".to_string(),
121 "Order 1".to_string(),
122 NodeType::Entity,
123 StateLayer::Lifecycle,
124 );
125
126 let edge = StateEdge::new("user-1".to_string(), "order-1".to_string(), "owns".to_string());
128
129 snapshot.nodes.push(node1);
130 snapshot.nodes.push(node2);
131 snapshot.edges.push(edge);
132
133 assert_eq!(snapshot.nodes.len(), 2);
135 assert_eq!(snapshot.edges.len(), 1);
136
137 let user_node = snapshot.get_node("user-1");
138 assert!(user_node.is_some());
139 assert_eq!(user_node.unwrap().label, "User 1");
140
141 let user_edges = snapshot.edges_for_node("user-1");
142 assert_eq!(user_edges.len(), 1);
143 assert_eq!(user_edges[0].to, "order-1");
144 }
145
146 #[test]
147 fn test_integration_query_workflow() {
148 let mut snapshot = WorldStateSnapshot::new();
149
150 let persona = StateNode::new(
152 "persona-1".to_string(),
153 "John Doe".to_string(),
154 NodeType::Persona,
155 StateLayer::Personas,
156 );
157
158 let entity = StateNode::new(
159 "entity-1".to_string(),
160 "Payment".to_string(),
161 NodeType::Entity,
162 StateLayer::Lifecycle,
163 );
164
165 let session = StateNode::new(
166 "session-1".to_string(),
167 "Session 123".to_string(),
168 NodeType::Session,
169 StateLayer::Protocols,
170 );
171
172 snapshot.nodes.push(persona.clone());
173 snapshot.nodes.push(entity.clone());
174 snapshot.nodes.push(session.clone());
175
176 let persona_layer_nodes = snapshot.nodes_in_layer(&StateLayer::Personas);
178 assert_eq!(persona_layer_nodes.len(), 1);
179 assert_eq!(persona_layer_nodes[0].id, "persona-1");
180
181 let lifecycle_layer_nodes = snapshot.nodes_in_layer(&StateLayer::Lifecycle);
182 assert_eq!(lifecycle_layer_nodes.len(), 1);
183 assert_eq!(lifecycle_layer_nodes[0].id, "entity-1");
184 }
185
186 #[test]
187 fn test_integration_state_node_properties() {
188 let mut node = StateNode::new(
189 "test".to_string(),
190 "Test".to_string(),
191 NodeType::Entity,
192 StateLayer::System,
193 );
194
195 node.set_property("status".to_string(), serde_json::json!("active"));
197 node.set_property("count".to_string(), serde_json::json!(42));
198 node.set_property("metadata".to_string(), serde_json::json!({"key": "value"}));
199
200 assert_eq!(node.get_property("status"), Some(&serde_json::json!("active")));
202 assert_eq!(node.get_property("count"), Some(&serde_json::json!(42)));
203 assert!(node.get_property("metadata").is_some());
204 assert!(node.get_property("nonexistent").is_none());
205
206 node.set_state("running".to_string());
208 assert_eq!(node.state, Some("running".to_string()));
209 }
210
211 #[test]
212 fn test_integration_state_edge_properties() {
213 let mut edge = StateEdge::new("a".to_string(), "b".to_string(), "connects".to_string());
214
215 edge.set_property("weight".to_string(), serde_json::json!(0.75));
216 edge.set_property("bidirectional".to_string(), serde_json::json!(true));
217
218 assert_eq!(edge.properties.get("weight"), Some(&serde_json::json!(0.75)));
219 assert_eq!(edge.properties.get("bidirectional"), Some(&serde_json::json!(true)));
220 }
221
222 #[test]
223 fn test_integration_snapshot_metadata() {
224 let mut snapshot = WorldStateSnapshot::new();
225
226 snapshot.metadata.insert("version".to_string(), serde_json::json!("1.0.0"));
227 snapshot.metadata.insert("environment".to_string(), serde_json::json!("test"));
228
229 assert_eq!(snapshot.metadata.get("version"), Some(&serde_json::json!("1.0.0")));
230 assert_eq!(snapshot.metadata.get("environment"), Some(&serde_json::json!("test")));
231 }
232
233 #[test]
234 fn test_integration_layer_management() {
235 let mut snapshot = WorldStateSnapshot::new();
236
237 snapshot.layers.insert(StateLayer::Personas, true);
239 snapshot.layers.insert(StateLayer::Lifecycle, true);
240 snapshot.layers.insert(StateLayer::Reality, false);
241
242 assert_eq!(snapshot.layers.get(&StateLayer::Personas), Some(&true));
243 assert_eq!(snapshot.layers.get(&StateLayer::Lifecycle), Some(&true));
244 assert_eq!(snapshot.layers.get(&StateLayer::Reality), Some(&false));
245 assert_eq!(snapshot.layers.get(&StateLayer::Time), None);
246 }
247
248 #[test]
249 fn test_all_node_types_coverage() {
250 let types = vec![
252 NodeType::Persona,
253 NodeType::Entity,
254 NodeType::Session,
255 NodeType::Protocol,
256 NodeType::Behavior,
257 NodeType::Schema,
258 NodeType::Recorded,
259 NodeType::AiModifier,
260 NodeType::System,
261 ];
262
263 for (i, node_type) in types.iter().enumerate() {
264 let node = StateNode::new(
265 format!("node-{}", i),
266 format!("Node {}", i),
267 *node_type,
268 StateLayer::System,
269 );
270 assert_eq!(node.node_type, *node_type);
271 }
272 }
273
274 #[test]
275 fn test_all_state_layers_coverage() {
276 let all_layers = StateLayer::all();
278
279 for layer in &all_layers {
280 let name = layer.name();
281 assert!(!name.is_empty());
282
283 let node =
284 StateNode::new("test".to_string(), "Test".to_string(), NodeType::System, *layer);
285 assert_eq!(node.layer, *layer);
286 }
287
288 assert_eq!(all_layers.len(), 10);
290 }
291
292 #[test]
293 fn test_serialization_roundtrip_snapshot() {
294 let mut snapshot = WorldStateSnapshot::new();
295
296 let node = StateNode::new(
297 "node-1".to_string(),
298 "Node 1".to_string(),
299 NodeType::Persona,
300 StateLayer::Personas,
301 );
302 snapshot.nodes.push(node);
303
304 let edge =
305 StateEdge::new("node-1".to_string(), "node-2".to_string(), "relates".to_string());
306 snapshot.edges.push(edge);
307
308 let json = serde_json::to_string(&snapshot).unwrap();
310 assert!(!json.is_empty());
311
312 let deserialized: WorldStateSnapshot = serde_json::from_str(&json).unwrap();
314 assert_eq!(snapshot.id, deserialized.id);
315 assert_eq!(snapshot.nodes.len(), deserialized.nodes.len());
316 assert_eq!(snapshot.edges.len(), deserialized.edges.len());
317 }
318
319 #[test]
320 fn test_serialization_roundtrip_query() {
321 let mut node_types = HashSet::new();
322 node_types.insert(NodeType::Persona);
323 node_types.insert(NodeType::Entity);
324
325 let query = WorldStateQuery::new()
326 .with_node_types(node_types)
327 .include_edges(false)
328 .with_max_depth(5);
329
330 let json = serde_json::to_string(&query).unwrap();
332
333 let deserialized: WorldStateQuery = serde_json::from_str(&json).unwrap();
335 assert_eq!(query.include_edges, deserialized.include_edges);
336 assert_eq!(query.max_depth, deserialized.max_depth);
337 }
338
339 #[test]
340 fn test_complex_graph_structure() {
341 let mut snapshot = WorldStateSnapshot::new();
342
343 let node_a = StateNode::new(
346 "a".to_string(),
347 "Node A".to_string(),
348 NodeType::Entity,
349 StateLayer::Lifecycle,
350 );
351 let node_b = StateNode::new(
352 "b".to_string(),
353 "Node B".to_string(),
354 NodeType::Entity,
355 StateLayer::Lifecycle,
356 );
357 let node_c = StateNode::new(
358 "c".to_string(),
359 "Node C".to_string(),
360 NodeType::Entity,
361 StateLayer::Lifecycle,
362 );
363 let node_d = StateNode::new(
364 "d".to_string(),
365 "Node D".to_string(),
366 NodeType::Entity,
367 StateLayer::Lifecycle,
368 );
369
370 snapshot.nodes.push(node_a);
371 snapshot.nodes.push(node_b);
372 snapshot.nodes.push(node_c);
373 snapshot.nodes.push(node_d);
374
375 snapshot
376 .edges
377 .push(StateEdge::new("a".to_string(), "b".to_string(), "owns".to_string()));
378 snapshot
379 .edges
380 .push(StateEdge::new("b".to_string(), "c".to_string(), "owns".to_string()));
381 snapshot.edges.push(StateEdge::new(
382 "a".to_string(),
383 "d".to_string(),
384 "references".to_string(),
385 ));
386
387 let edges_from_a = snapshot.edges_for_node("a");
389 assert_eq!(edges_from_a.len(), 2);
390
391 let edges_from_b = snapshot.edges_for_node("b");
392 assert_eq!(edges_from_b.len(), 2); let edges_from_c = snapshot.edges_for_node("c");
395 assert_eq!(edges_from_c.len(), 1); let edges_from_d = snapshot.edges_for_node("d");
398 assert_eq!(edges_from_d.len(), 1); }
400
401 #[tokio::test]
402 async fn test_full_integration_workflow() {
403 use aggregators::StateAggregator;
404 use std::sync::Arc;
405
406 struct TestAggregator;
408
409 #[async_trait::async_trait]
410 impl StateAggregator for TestAggregator {
411 async fn aggregate(&self) -> anyhow::Result<(Vec<StateNode>, Vec<StateEdge>)> {
412 let node1 = StateNode::new(
413 "test-1".to_string(),
414 "Test 1".to_string(),
415 NodeType::Persona,
416 StateLayer::Personas,
417 );
418 let node2 = StateNode::new(
419 "test-2".to_string(),
420 "Test 2".to_string(),
421 NodeType::Entity,
422 StateLayer::Lifecycle,
423 );
424 let edge =
425 StateEdge::new("test-1".to_string(), "test-2".to_string(), "owns".to_string());
426
427 Ok((vec![node1, node2], vec![edge]))
428 }
429
430 fn layer(&self) -> StateLayer {
431 StateLayer::Personas
432 }
433 }
434
435 let mut engine = WorldStateEngine::new();
437 engine.register_aggregator(Arc::new(TestAggregator));
438
439 let snapshot = engine.create_snapshot().await.unwrap();
441 assert_eq!(snapshot.nodes.len(), 2);
442 assert_eq!(snapshot.edges.len(), 1);
443
444 let mut node_types = HashSet::new();
446 node_types.insert(NodeType::Persona);
447
448 let query = WorldStateQuery::new().with_node_types(node_types);
449 let filtered = engine.query(&query).await.unwrap();
450
451 assert_eq!(filtered.nodes.len(), 1);
452 assert_eq!(filtered.nodes[0].id, "test-1");
453
454 let all_snapshots = engine.get_all_snapshots().await;
456 assert_eq!(all_snapshots.len(), 2); }
458
459 #[test]
460 fn test_node_equality() {
461 let node1 = StateNode::new(
462 "same-id".to_string(),
463 "Label 1".to_string(),
464 NodeType::Persona,
465 StateLayer::Personas,
466 );
467
468 let node2 = StateNode::new(
469 "same-id".to_string(),
470 "Label 1".to_string(),
471 NodeType::Persona,
472 StateLayer::Personas,
473 );
474
475 assert_eq!(node1.id, node2.id);
478 assert_eq!(node1.label, node2.label);
479 assert_eq!(node1.node_type, node2.node_type);
480 assert_eq!(node1.layer, node2.layer);
481 }
482
483 #[test]
484 fn test_edge_equality() {
485 let edge1 = StateEdge::new("a".to_string(), "b".to_string(), "owns".to_string());
486
487 let edge2 = StateEdge::new("a".to_string(), "b".to_string(), "owns".to_string());
488
489 assert_eq!(edge1.from, edge2.from);
490 assert_eq!(edge1.to, edge2.to);
491 assert_eq!(edge1.relationship_type, edge2.relationship_type);
492 }
493
494 #[test]
495 fn test_snapshot_cloning() {
496 let mut snapshot = WorldStateSnapshot::new();
497 let node = StateNode::new(
498 "test".to_string(),
499 "Test".to_string(),
500 NodeType::Entity,
501 StateLayer::System,
502 );
503 snapshot.nodes.push(node);
504
505 let cloned = snapshot.clone();
506 assert_eq!(snapshot.id, cloned.id);
507 assert_eq!(snapshot.nodes.len(), cloned.nodes.len());
508 assert_eq!(snapshot.nodes[0].id, cloned.nodes[0].id);
509 }
510
511 #[test]
512 fn test_query_matches_complex_scenarios() {
513 let mut node_types = HashSet::new();
514 node_types.insert(NodeType::Persona);
515 node_types.insert(NodeType::Entity);
516
517 let mut layers = HashSet::new();
518 layers.insert(StateLayer::Personas);
519
520 let mut ids = HashSet::new();
521 ids.insert("specific-id".to_string());
522
523 let query = WorldStateQuery::new()
525 .with_node_types(node_types.clone())
526 .with_layers(layers.clone())
527 .with_node_ids(ids.clone());
528
529 let matching = StateNode::new(
531 "specific-id".to_string(),
532 "Match".to_string(),
533 NodeType::Persona,
534 StateLayer::Personas,
535 );
536 assert!(query.matches_node(&matching));
537
538 let wrong_id = StateNode::new(
540 "other-id".to_string(),
541 "Wrong".to_string(),
542 NodeType::Persona,
543 StateLayer::Personas,
544 );
545 assert!(!query.matches_node(&wrong_id));
546
547 let wrong_type = StateNode::new(
548 "specific-id".to_string(),
549 "Wrong".to_string(),
550 NodeType::System,
551 StateLayer::Personas,
552 );
553 assert!(!query.matches_node(&wrong_type));
554
555 let wrong_layer = StateNode::new(
556 "specific-id".to_string(),
557 "Wrong".to_string(),
558 NodeType::Persona,
559 StateLayer::Lifecycle,
560 );
561 assert!(!query.matches_node(&wrong_layer));
562 }
563}