1use crate::aggregators::StateAggregator;
7use crate::model::{StateLayer, WorldStateSnapshot};
8use crate::query::WorldStateQuery;
9use anyhow::Result;
10use std::collections::HashMap;
11use std::sync::Arc;
12use tokio::sync::RwLock;
13use tracing::{debug, info, warn};
14
15pub struct WorldStateEngine {
20 aggregators: HashMap<StateLayer, Arc<dyn StateAggregator>>,
22 snapshots: Arc<RwLock<Vec<WorldStateSnapshot>>>,
24 max_snapshots: usize,
26}
27
28impl WorldStateEngine {
29 pub fn new() -> Self {
31 Self {
32 aggregators: HashMap::new(),
33 snapshots: Arc::new(RwLock::new(Vec::new())),
34 max_snapshots: 100,
35 }
36 }
37
38 pub fn register_aggregator(&mut self, aggregator: Arc<dyn StateAggregator>) {
40 let layer = aggregator.layer();
41 self.aggregators.insert(layer, aggregator);
42 info!("Registered aggregator for layer: {:?}", layer);
43 }
44
45 pub async fn create_snapshot(&self) -> Result<WorldStateSnapshot> {
47 debug!("Creating world state snapshot");
48
49 let mut snapshot = WorldStateSnapshot::new();
50 let mut all_nodes = Vec::new();
51 let mut all_edges = Vec::new();
52
53 for (layer, aggregator) in &self.aggregators {
55 match aggregator.aggregate().await {
56 Ok((nodes, edges)) => {
57 debug!(
58 "Aggregated {} nodes and {} edges from layer: {:?}",
59 nodes.len(),
60 edges.len(),
61 layer
62 );
63 all_nodes.extend(nodes);
64 all_edges.extend(edges);
65 snapshot.layers.insert(*layer, true);
66 }
67 Err(e) => {
68 warn!("Failed to aggregate state from layer {:?}: {}", layer, e);
69 snapshot.layers.insert(*layer, false);
70 }
71 }
72 }
73
74 snapshot.nodes = all_nodes;
75 snapshot.edges = all_edges;
76
77 let mut snapshots = self.snapshots.write().await;
79 snapshots.push(snapshot.clone());
80
81 if snapshots.len() > self.max_snapshots {
83 snapshots.remove(0);
84 }
85
86 info!(
87 "Created world state snapshot with {} nodes and {} edges",
88 snapshot.nodes.len(),
89 snapshot.edges.len()
90 );
91
92 Ok(snapshot)
93 }
94
95 pub async fn get_current_snapshot(&self) -> Result<WorldStateSnapshot> {
97 self.create_snapshot().await
98 }
99
100 pub async fn get_snapshot(&self, snapshot_id: &str) -> Option<WorldStateSnapshot> {
102 let snapshots = self.snapshots.read().await;
103 snapshots.iter().find(|s| s.id == snapshot_id).cloned()
104 }
105
106 pub async fn get_all_snapshots(&self) -> Vec<WorldStateSnapshot> {
108 let snapshots = self.snapshots.read().await;
109 snapshots.clone()
110 }
111
112 pub async fn query(&self, query: &WorldStateQuery) -> Result<WorldStateSnapshot> {
114 let snapshot = self.create_snapshot().await?;
115
116 let filtered_nodes: Vec<_> =
118 snapshot.nodes.iter().filter(|node| query.matches_node(node)).cloned().collect();
119
120 let filtered_edges: Vec<_> = if query.include_edges {
122 snapshot.edges.iter().filter(|edge| query.matches_edge(edge)).cloned().collect()
123 } else {
124 Vec::new()
125 };
126
127 let mut filtered_snapshot = snapshot;
129 filtered_snapshot.nodes = filtered_nodes;
130 filtered_snapshot.edges = filtered_edges;
131
132 Ok(filtered_snapshot)
133 }
134
135 pub fn get_layers(&self) -> Vec<StateLayer> {
137 self.aggregators.keys().copied().collect()
138 }
139
140 pub fn set_max_snapshots(&mut self, max: usize) {
142 self.max_snapshots = max;
143 }
144}
145
146impl Default for WorldStateEngine {
147 fn default() -> Self {
148 Self::new()
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155 use crate::model::{NodeType, StateNode};
156 use std::collections::HashSet;
157
158 struct MockAggregator {
160 layer: StateLayer,
161 nodes: Vec<StateNode>,
162 edges: Vec<crate::model::StateEdge>,
163 should_fail: bool,
164 }
165
166 impl MockAggregator {
167 fn new(layer: StateLayer) -> Self {
168 Self {
169 layer,
170 nodes: Vec::new(),
171 edges: Vec::new(),
172 should_fail: false,
173 }
174 }
175
176 fn with_nodes(mut self, nodes: Vec<StateNode>) -> Self {
177 self.nodes = nodes;
178 self
179 }
180
181 fn with_edges(mut self, edges: Vec<crate::model::StateEdge>) -> Self {
182 self.edges = edges;
183 self
184 }
185
186 fn with_failure(mut self) -> Self {
187 self.should_fail = true;
188 self
189 }
190 }
191
192 #[async_trait::async_trait]
193 impl StateAggregator for MockAggregator {
194 async fn aggregate(&self) -> Result<(Vec<StateNode>, Vec<crate::model::StateEdge>)> {
195 if self.should_fail {
196 anyhow::bail!("Mock aggregator failure");
197 }
198 Ok((self.nodes.clone(), self.edges.clone()))
199 }
200
201 fn layer(&self) -> StateLayer {
202 self.layer
203 }
204 }
205
206 #[test]
207 fn test_world_state_engine_new() {
208 let engine = WorldStateEngine::new();
209 assert_eq!(engine.aggregators.len(), 0);
210 assert_eq!(engine.max_snapshots, 100);
211 }
212
213 #[test]
214 fn test_world_state_engine_default() {
215 let engine = WorldStateEngine::default();
216 assert_eq!(engine.aggregators.len(), 0);
217 assert_eq!(engine.max_snapshots, 100);
218 }
219
220 #[test]
221 fn test_register_aggregator() {
222 let mut engine = WorldStateEngine::new();
223 let aggregator = Arc::new(MockAggregator::new(StateLayer::Personas));
224
225 engine.register_aggregator(aggregator);
226 assert_eq!(engine.aggregators.len(), 1);
227 assert!(engine.aggregators.contains_key(&StateLayer::Personas));
228 }
229
230 #[test]
231 fn test_register_multiple_aggregators() {
232 let mut engine = WorldStateEngine::new();
233
234 engine.register_aggregator(Arc::new(MockAggregator::new(StateLayer::Personas)));
235 engine.register_aggregator(Arc::new(MockAggregator::new(StateLayer::Lifecycle)));
236 engine.register_aggregator(Arc::new(MockAggregator::new(StateLayer::Reality)));
237
238 assert_eq!(engine.aggregators.len(), 3);
239 assert!(engine.aggregators.contains_key(&StateLayer::Personas));
240 assert!(engine.aggregators.contains_key(&StateLayer::Lifecycle));
241 assert!(engine.aggregators.contains_key(&StateLayer::Reality));
242 }
243
244 #[test]
245 fn test_register_aggregator_replacement() {
246 let mut engine = WorldStateEngine::new();
247
248 engine.register_aggregator(Arc::new(MockAggregator::new(StateLayer::Personas)));
250 assert_eq!(engine.aggregators.len(), 1);
251
252 engine.register_aggregator(Arc::new(MockAggregator::new(StateLayer::Personas)));
254 assert_eq!(engine.aggregators.len(), 1);
255 }
256
257 #[tokio::test]
258 async fn test_create_snapshot_empty() {
259 let engine = WorldStateEngine::new();
260 let snapshot = engine.create_snapshot().await.unwrap();
261
262 assert!(snapshot.nodes.is_empty());
263 assert!(snapshot.edges.is_empty());
264 assert!(snapshot.layers.is_empty());
265 }
266
267 #[tokio::test]
268 async fn test_create_snapshot_with_aggregator() {
269 let mut engine = WorldStateEngine::new();
270
271 let node = StateNode::new(
272 "test-node".to_string(),
273 "Test Node".to_string(),
274 NodeType::Persona,
275 StateLayer::Personas,
276 );
277
278 let aggregator =
279 Arc::new(MockAggregator::new(StateLayer::Personas).with_nodes(vec![node.clone()]));
280
281 engine.register_aggregator(aggregator);
282
283 let snapshot = engine.create_snapshot().await.unwrap();
284
285 assert_eq!(snapshot.nodes.len(), 1);
286 assert_eq!(snapshot.nodes[0].id, "test-node");
287 assert_eq!(snapshot.edges.len(), 0);
288 assert!(snapshot.layers.contains_key(&StateLayer::Personas));
289 assert_eq!(snapshot.layers[&StateLayer::Personas], true);
290 }
291
292 #[tokio::test]
293 async fn test_create_snapshot_with_edges() {
294 let mut engine = WorldStateEngine::new();
295
296 let node1 = StateNode::new(
297 "node1".to_string(),
298 "Node 1".to_string(),
299 NodeType::Persona,
300 StateLayer::Personas,
301 );
302 let node2 = StateNode::new(
303 "node2".to_string(),
304 "Node 2".to_string(),
305 NodeType::Persona,
306 StateLayer::Personas,
307 );
308 let edge = crate::model::StateEdge::new(
309 "node1".to_string(),
310 "node2".to_string(),
311 "relates_to".to_string(),
312 );
313
314 let aggregator = Arc::new(
315 MockAggregator::new(StateLayer::Personas)
316 .with_nodes(vec![node1, node2])
317 .with_edges(vec![edge]),
318 );
319
320 engine.register_aggregator(aggregator);
321
322 let snapshot = engine.create_snapshot().await.unwrap();
323
324 assert_eq!(snapshot.nodes.len(), 2);
325 assert_eq!(snapshot.edges.len(), 1);
326 assert_eq!(snapshot.edges[0].from, "node1");
327 assert_eq!(snapshot.edges[0].to, "node2");
328 }
329
330 #[tokio::test]
331 async fn test_create_snapshot_multiple_aggregators() {
332 let mut engine = WorldStateEngine::new();
333
334 let persona_node = StateNode::new(
335 "persona1".to_string(),
336 "Persona 1".to_string(),
337 NodeType::Persona,
338 StateLayer::Personas,
339 );
340 let lifecycle_node = StateNode::new(
341 "lifecycle1".to_string(),
342 "Lifecycle 1".to_string(),
343 NodeType::Entity,
344 StateLayer::Lifecycle,
345 );
346
347 engine.register_aggregator(Arc::new(
348 MockAggregator::new(StateLayer::Personas).with_nodes(vec![persona_node]),
349 ));
350 engine.register_aggregator(Arc::new(
351 MockAggregator::new(StateLayer::Lifecycle).with_nodes(vec![lifecycle_node]),
352 ));
353
354 let snapshot = engine.create_snapshot().await.unwrap();
355
356 assert_eq!(snapshot.nodes.len(), 2);
357 assert_eq!(snapshot.layers.len(), 2);
358 assert!(snapshot.layers.contains_key(&StateLayer::Personas));
359 assert!(snapshot.layers.contains_key(&StateLayer::Lifecycle));
360 }
361
362 #[tokio::test]
363 async fn test_create_snapshot_aggregator_failure() {
364 let mut engine = WorldStateEngine::new();
365
366 let success_node = StateNode::new(
367 "success".to_string(),
368 "Success Node".to_string(),
369 NodeType::Persona,
370 StateLayer::Personas,
371 );
372
373 engine.register_aggregator(Arc::new(
375 MockAggregator::new(StateLayer::Personas).with_nodes(vec![success_node]),
376 ));
377
378 engine.register_aggregator(Arc::new(
380 MockAggregator::new(StateLayer::Lifecycle).with_failure(),
381 ));
382
383 let snapshot = engine.create_snapshot().await.unwrap();
384
385 assert_eq!(snapshot.nodes.len(), 1);
387 assert_eq!(snapshot.layers[&StateLayer::Personas], true);
388 assert_eq!(snapshot.layers[&StateLayer::Lifecycle], false);
389 }
390
391 #[tokio::test]
392 async fn test_get_current_snapshot() {
393 let mut engine = WorldStateEngine::new();
394
395 let node = StateNode::new(
396 "test".to_string(),
397 "Test".to_string(),
398 NodeType::Entity,
399 StateLayer::System,
400 );
401
402 engine.register_aggregator(Arc::new(
403 MockAggregator::new(StateLayer::System).with_nodes(vec![node]),
404 ));
405
406 let snapshot = engine.get_current_snapshot().await.unwrap();
407
408 assert_eq!(snapshot.nodes.len(), 1);
409 assert_eq!(snapshot.nodes[0].id, "test");
410 }
411
412 #[tokio::test]
413 async fn test_snapshot_storage() {
414 let mut engine = WorldStateEngine::new();
415
416 let node = StateNode::new(
417 "test".to_string(),
418 "Test".to_string(),
419 NodeType::Entity,
420 StateLayer::System,
421 );
422
423 engine.register_aggregator(Arc::new(
424 MockAggregator::new(StateLayer::System).with_nodes(vec![node]),
425 ));
426
427 let snapshot1 = engine.create_snapshot().await.unwrap();
429 let snapshot1_id = snapshot1.id.clone();
430
431 let snapshots = engine.snapshots.read().await;
433 assert_eq!(snapshots.len(), 1);
434 assert_eq!(snapshots[0].id, snapshot1_id);
435 }
436
437 #[tokio::test]
438 async fn test_get_snapshot() {
439 let mut engine = WorldStateEngine::new();
440
441 let node = StateNode::new(
442 "test".to_string(),
443 "Test".to_string(),
444 NodeType::Entity,
445 StateLayer::System,
446 );
447
448 engine.register_aggregator(Arc::new(
449 MockAggregator::new(StateLayer::System).with_nodes(vec![node]),
450 ));
451
452 let snapshot = engine.create_snapshot().await.unwrap();
454 let snapshot_id = snapshot.id.clone();
455
456 let retrieved = engine.get_snapshot(&snapshot_id).await;
458 assert!(retrieved.is_some());
459 assert_eq!(retrieved.unwrap().id, snapshot_id);
460
461 let not_found = engine.get_snapshot("nonexistent").await;
463 assert!(not_found.is_none());
464 }
465
466 #[tokio::test]
467 async fn test_get_all_snapshots() {
468 let mut engine = WorldStateEngine::new();
469
470 let node = StateNode::new(
471 "test".to_string(),
472 "Test".to_string(),
473 NodeType::Entity,
474 StateLayer::System,
475 );
476
477 engine.register_aggregator(Arc::new(
478 MockAggregator::new(StateLayer::System).with_nodes(vec![node]),
479 ));
480
481 engine.create_snapshot().await.unwrap();
483 engine.create_snapshot().await.unwrap();
484 engine.create_snapshot().await.unwrap();
485
486 let all_snapshots = engine.get_all_snapshots().await;
487 assert_eq!(all_snapshots.len(), 3);
488 }
489
490 #[tokio::test]
491 async fn test_max_snapshots_limit() {
492 let mut engine = WorldStateEngine::new();
493 engine.set_max_snapshots(2);
494
495 let node = StateNode::new(
496 "test".to_string(),
497 "Test".to_string(),
498 NodeType::Entity,
499 StateLayer::System,
500 );
501
502 engine.register_aggregator(Arc::new(
503 MockAggregator::new(StateLayer::System).with_nodes(vec![node]),
504 ));
505
506 engine.create_snapshot().await.unwrap();
508 engine.create_snapshot().await.unwrap();
509 engine.create_snapshot().await.unwrap();
510
511 let snapshots = engine.get_all_snapshots().await;
512 assert_eq!(snapshots.len(), 2);
513 }
514
515 #[tokio::test]
516 async fn test_query_no_filters() {
517 let mut engine = WorldStateEngine::new();
518
519 let node1 = StateNode::new(
520 "node1".to_string(),
521 "Node 1".to_string(),
522 NodeType::Persona,
523 StateLayer::Personas,
524 );
525 let node2 = StateNode::new(
526 "node2".to_string(),
527 "Node 2".to_string(),
528 NodeType::Entity,
529 StateLayer::Lifecycle,
530 );
531
532 engine.register_aggregator(Arc::new(
533 MockAggregator::new(StateLayer::Personas).with_nodes(vec![node1]),
534 ));
535 engine.register_aggregator(Arc::new(
536 MockAggregator::new(StateLayer::Lifecycle).with_nodes(vec![node2]),
537 ));
538
539 let query = WorldStateQuery::new();
540 let result = engine.query(&query).await.unwrap();
541
542 assert_eq!(result.nodes.len(), 2);
543 }
544
545 #[tokio::test]
546 async fn test_query_filter_by_node_type() {
547 let mut engine = WorldStateEngine::new();
548
549 let persona_node = StateNode::new(
550 "persona".to_string(),
551 "Persona".to_string(),
552 NodeType::Persona,
553 StateLayer::Personas,
554 );
555 let entity_node = StateNode::new(
556 "entity".to_string(),
557 "Entity".to_string(),
558 NodeType::Entity,
559 StateLayer::Lifecycle,
560 );
561
562 engine.register_aggregator(Arc::new(
563 MockAggregator::new(StateLayer::Personas).with_nodes(vec![persona_node]),
564 ));
565 engine.register_aggregator(Arc::new(
566 MockAggregator::new(StateLayer::Lifecycle).with_nodes(vec![entity_node]),
567 ));
568
569 let mut node_types = HashSet::new();
570 node_types.insert(NodeType::Persona);
571
572 let query = WorldStateQuery::new().with_node_types(node_types);
573 let result = engine.query(&query).await.unwrap();
574
575 assert_eq!(result.nodes.len(), 1);
576 assert_eq!(result.nodes[0].node_type, NodeType::Persona);
577 }
578
579 #[tokio::test]
580 async fn test_query_filter_by_layer() {
581 let mut engine = WorldStateEngine::new();
582
583 let node1 = StateNode::new(
584 "node1".to_string(),
585 "Node 1".to_string(),
586 NodeType::Persona,
587 StateLayer::Personas,
588 );
589 let node2 = StateNode::new(
590 "node2".to_string(),
591 "Node 2".to_string(),
592 NodeType::Entity,
593 StateLayer::Lifecycle,
594 );
595
596 engine.register_aggregator(Arc::new(
597 MockAggregator::new(StateLayer::Personas).with_nodes(vec![node1]),
598 ));
599 engine.register_aggregator(Arc::new(
600 MockAggregator::new(StateLayer::Lifecycle).with_nodes(vec![node2]),
601 ));
602
603 let mut layers = HashSet::new();
604 layers.insert(StateLayer::Personas);
605
606 let query = WorldStateQuery::new().with_layers(layers);
607 let result = engine.query(&query).await.unwrap();
608
609 assert_eq!(result.nodes.len(), 1);
610 assert_eq!(result.nodes[0].layer, StateLayer::Personas);
611 }
612
613 #[tokio::test]
614 async fn test_query_include_edges_false() {
615 let mut engine = WorldStateEngine::new();
616
617 let node = StateNode::new(
618 "node".to_string(),
619 "Node".to_string(),
620 NodeType::Persona,
621 StateLayer::Personas,
622 );
623 let edge = crate::model::StateEdge::new(
624 "node".to_string(),
625 "node".to_string(),
626 "self".to_string(),
627 );
628
629 engine.register_aggregator(Arc::new(
630 MockAggregator::new(StateLayer::Personas)
631 .with_nodes(vec![node])
632 .with_edges(vec![edge]),
633 ));
634
635 let query = WorldStateQuery::new().include_edges(false);
636 let result = engine.query(&query).await.unwrap();
637
638 assert_eq!(result.nodes.len(), 1);
639 assert_eq!(result.edges.len(), 0);
640 }
641
642 #[tokio::test]
643 async fn test_query_filter_edges() {
644 let mut engine = WorldStateEngine::new();
645
646 let edge1 =
647 crate::model::StateEdge::new("a".to_string(), "b".to_string(), "owns".to_string());
648 let edge2 = crate::model::StateEdge::new(
649 "b".to_string(),
650 "c".to_string(),
651 "references".to_string(),
652 );
653
654 engine.register_aggregator(Arc::new(
655 MockAggregator::new(StateLayer::Personas).with_edges(vec![edge1, edge2]),
656 ));
657
658 let mut relationship_types = HashSet::new();
659 relationship_types.insert("owns".to_string());
660
661 let query = WorldStateQuery::new().with_relationship_types(relationship_types);
662 let result = engine.query(&query).await.unwrap();
663
664 assert_eq!(result.edges.len(), 1);
665 assert_eq!(result.edges[0].relationship_type, "owns");
666 }
667
668 #[test]
669 fn test_get_layers_empty() {
670 let engine = WorldStateEngine::new();
671 let layers = engine.get_layers();
672 assert!(layers.is_empty());
673 }
674
675 #[test]
676 fn test_get_layers() {
677 let mut engine = WorldStateEngine::new();
678
679 engine.register_aggregator(Arc::new(MockAggregator::new(StateLayer::Personas)));
680 engine.register_aggregator(Arc::new(MockAggregator::new(StateLayer::Lifecycle)));
681 engine.register_aggregator(Arc::new(MockAggregator::new(StateLayer::Reality)));
682
683 let layers = engine.get_layers();
684 assert_eq!(layers.len(), 3);
685 assert!(layers.contains(&StateLayer::Personas));
686 assert!(layers.contains(&StateLayer::Lifecycle));
687 assert!(layers.contains(&StateLayer::Reality));
688 }
689
690 #[test]
691 fn test_set_max_snapshots() {
692 let mut engine = WorldStateEngine::new();
693 assert_eq!(engine.max_snapshots, 100);
694
695 engine.set_max_snapshots(50);
696 assert_eq!(engine.max_snapshots, 50);
697
698 engine.set_max_snapshots(200);
699 assert_eq!(engine.max_snapshots, 200);
700 }
701
702 #[tokio::test]
703 async fn test_snapshot_pruning() {
704 let mut engine = WorldStateEngine::new();
705 engine.set_max_snapshots(3);
706
707 let node = StateNode::new(
708 "test".to_string(),
709 "Test".to_string(),
710 NodeType::Entity,
711 StateLayer::System,
712 );
713
714 engine.register_aggregator(Arc::new(
715 MockAggregator::new(StateLayer::System).with_nodes(vec![node]),
716 ));
717
718 let snapshot1 = engine.create_snapshot().await.unwrap();
720 let snapshot2 = engine.create_snapshot().await.unwrap();
721 let snapshot3 = engine.create_snapshot().await.unwrap();
722 let snapshot4 = engine.create_snapshot().await.unwrap();
723 let snapshot5 = engine.create_snapshot().await.unwrap();
724
725 let all_snapshots = engine.get_all_snapshots().await;
726 assert_eq!(all_snapshots.len(), 3);
727
728 assert!(engine.get_snapshot(&snapshot1.id).await.is_none());
730 assert!(engine.get_snapshot(&snapshot2.id).await.is_none());
731
732 assert!(engine.get_snapshot(&snapshot3.id).await.is_some());
734 assert!(engine.get_snapshot(&snapshot4.id).await.is_some());
735 assert!(engine.get_snapshot(&snapshot5.id).await.is_some());
736 }
737
738 #[tokio::test]
739 async fn test_concurrent_snapshot_access() {
740 let mut engine = WorldStateEngine::new();
741
742 let node = StateNode::new(
743 "test".to_string(),
744 "Test".to_string(),
745 NodeType::Entity,
746 StateLayer::System,
747 );
748
749 engine.register_aggregator(Arc::new(
750 MockAggregator::new(StateLayer::System).with_nodes(vec![node]),
751 ));
752
753 let engine = Arc::new(engine);
754
755 let engine_clone = Arc::clone(&engine);
757 let handle1 = tokio::spawn(async move { engine_clone.create_snapshot().await });
758
759 let engine_clone = Arc::clone(&engine);
761 let handle2 = tokio::spawn(async move { engine_clone.get_all_snapshots().await });
762
763 let snapshot = handle1.await.unwrap();
765 let snapshots = handle2.await.unwrap();
766
767 assert!(snapshot.is_ok());
768 assert!(!snapshots.is_empty());
769 }
770
771 #[tokio::test]
772 async fn test_query_with_multiple_filters() {
773 let mut engine = WorldStateEngine::new();
774
775 let node1 = StateNode::new(
776 "node1".to_string(),
777 "Node 1".to_string(),
778 NodeType::Persona,
779 StateLayer::Personas,
780 );
781 let node2 = StateNode::new(
782 "node2".to_string(),
783 "Node 2".to_string(),
784 NodeType::Entity,
785 StateLayer::Lifecycle,
786 );
787 let node3 = StateNode::new(
788 "node3".to_string(),
789 "Node 3".to_string(),
790 NodeType::Persona,
791 StateLayer::Lifecycle,
792 );
793
794 engine.register_aggregator(Arc::new(
795 MockAggregator::new(StateLayer::Personas).with_nodes(vec![node1]),
796 ));
797 engine.register_aggregator(Arc::new(
798 MockAggregator::new(StateLayer::Lifecycle).with_nodes(vec![node2, node3]),
799 ));
800
801 let mut node_types = HashSet::new();
802 node_types.insert(NodeType::Persona);
803
804 let mut layers = HashSet::new();
805 layers.insert(StateLayer::Personas);
806
807 let query = WorldStateQuery::new().with_node_types(node_types).with_layers(layers);
808
809 let result = engine.query(&query).await.unwrap();
810
811 assert_eq!(result.nodes.len(), 1);
813 assert_eq!(result.nodes[0].id, "node1");
814 }
815
816 #[tokio::test]
817 async fn test_empty_query_result() {
818 let mut engine = WorldStateEngine::new();
819
820 let node = StateNode::new(
821 "node".to_string(),
822 "Node".to_string(),
823 NodeType::Persona,
824 StateLayer::Personas,
825 );
826
827 engine.register_aggregator(Arc::new(
828 MockAggregator::new(StateLayer::Personas).with_nodes(vec![node]),
829 ));
830
831 let mut node_types = HashSet::new();
833 node_types.insert(NodeType::System);
834
835 let query = WorldStateQuery::new().with_node_types(node_types);
836 let result = engine.query(&query).await.unwrap();
837
838 assert_eq!(result.nodes.len(), 0);
839 assert_eq!(result.edges.len(), 0);
840 }
841
842 #[tokio::test]
843 async fn test_aggregator_metadata() {
844 struct MetadataAggregator {
845 layer: StateLayer,
846 }
847
848 #[async_trait::async_trait]
849 impl StateAggregator for MetadataAggregator {
850 async fn aggregate(&self) -> Result<(Vec<StateNode>, Vec<crate::model::StateEdge>)> {
851 Ok((Vec::new(), Vec::new()))
852 }
853
854 fn layer(&self) -> StateLayer {
855 self.layer
856 }
857
858 fn metadata(&self) -> HashMap<String, serde_json::Value> {
859 let mut map = HashMap::new();
860 map.insert("version".to_string(), serde_json::json!("1.0"));
861 map.insert("enabled".to_string(), serde_json::json!(true));
862 map
863 }
864 }
865
866 let aggregator = MetadataAggregator {
867 layer: StateLayer::Personas,
868 };
869
870 let metadata = aggregator.metadata();
871 assert_eq!(metadata.len(), 2);
872 assert_eq!(metadata.get("version"), Some(&serde_json::json!("1.0")));
873 assert_eq!(metadata.get("enabled"), Some(&serde_json::json!(true)));
874 }
875}