use std::sync::Arc;
use swarm_engine_core::events::{InMemoryTraceSubscriber, NoOpTraceSubscriber, TraceSubscriber};
use swarm_engine_core::learn::{LearningPhase, SessionGroup, SessionGroupId, SessionGroupMetadata};
mod unit {
use super::*;
#[test]
fn test_learning_phase_serialization() {
let bootstrap = LearningPhase::Bootstrap;
let release = LearningPhase::Release;
let validate = LearningPhase::Validate;
assert_eq!(bootstrap.to_string(), "bootstrap");
assert_eq!(release.to_string(), "release");
assert_eq!(validate.to_string(), "validate");
assert_eq!(
"bootstrap".parse::<LearningPhase>().unwrap(),
LearningPhase::Bootstrap
);
assert_eq!(
"RELEASE".parse::<LearningPhase>().unwrap(),
LearningPhase::Release
);
let json = serde_json::to_string(&bootstrap).unwrap();
assert_eq!(json, "\"bootstrap\"");
let deserialized: LearningPhase = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, LearningPhase::Bootstrap);
}
#[test]
fn test_session_group_lifecycle() {
let mut group = SessionGroup::new(LearningPhase::Bootstrap, "test_scenario", 5);
assert_eq!(group.phase, LearningPhase::Bootstrap);
assert_eq!(group.metadata.scenario, "test_scenario");
assert_eq!(group.metadata.target_runs, 5);
assert_eq!(group.metadata.success_count, 0);
assert_eq!(group.metadata.failure_count, 0);
assert!(!group.is_target_reached());
group.add_session(swarm_engine_core::learn::SessionId("1".to_string()), true);
group.add_session(swarm_engine_core::learn::SessionId("2".to_string()), true);
group.add_session(swarm_engine_core::learn::SessionId("3".to_string()), false);
assert_eq!(group.metadata.success_count, 2);
assert_eq!(group.metadata.failure_count, 1);
assert_eq!(group.session_ids.len(), 3);
assert!(!group.is_target_reached());
group.add_session(swarm_engine_core::learn::SessionId("4".to_string()), true);
group.add_session(swarm_engine_core::learn::SessionId("5".to_string()), true);
assert!(group.is_target_reached());
assert_eq!(group.success_rate(), 0.8);
group.mark_completed();
assert!(group.metadata.completed_at.is_some());
}
#[test]
fn test_session_group_with_variant() {
let group =
SessionGroup::new(LearningPhase::Bootstrap, "test", 10).with_variant("with_graph");
assert_eq!(group.metadata.variant, Some("with_graph".to_string()));
}
#[test]
fn test_session_group_id_uniqueness() {
let id1 = SessionGroupId::new();
let id2 = SessionGroupId::new();
assert!(id1.0.starts_with('g'));
assert!(id2.0.starts_with('g'));
}
#[test]
fn test_session_group_metadata_success_rate() {
let mut meta = SessionGroupMetadata::new("test", 10);
assert_eq!(meta.success_rate(), 0.0);
assert_eq!(meta.completed_runs(), 0);
meta.record_success();
meta.record_success();
meta.record_failure();
assert_eq!(meta.success_rate(), 2.0 / 3.0);
assert_eq!(meta.completed_runs(), 3);
}
#[test]
fn test_noop_trace_subscriber() {
let subscriber = NoOpTraceSubscriber::new();
let event = make_test_action_event(1, "TestAction", true);
subscriber.on_event(&event);
subscriber.finish();
}
#[test]
fn test_in_memory_trace_subscriber() {
let subscriber = InMemoryTraceSubscriber::new();
assert!(subscriber.is_empty());
subscriber.on_event(&make_test_action_event(1, "Search", true));
subscriber.on_event(&make_test_action_event(2, "Read", true));
subscriber.on_event(&make_test_action_event(3, "Submit", false));
assert_eq!(subscriber.len(), 3);
let events = subscriber.events();
assert_eq!(events[0].tick, 1);
assert_eq!(events[0].action, "Search");
assert!(events[0].success);
assert_eq!(events[2].action, "Submit");
assert!(!events[2].success);
subscriber.clear();
assert!(subscriber.is_empty());
}
#[test]
fn test_in_memory_trace_subscriber_dump_to_file() {
let subscriber = InMemoryTraceSubscriber::new();
subscriber.on_event(&make_test_action_event(1, "Search", true));
subscriber.on_event(&make_test_action_event(2, "Read", true));
let temp_dir = std::env::temp_dir();
let path = temp_dir.join(format!("test_trace_dump_{}.jsonl", std::process::id()));
subscriber.dump_to_file(&path).unwrap();
let content = std::fs::read_to_string(&path).unwrap();
let lines: Vec<&str> = content.lines().collect();
assert_eq!(lines.len(), 2);
let first: swarm_engine_core::events::TraceEvent = serde_json::from_str(lines[0]).unwrap();
assert_eq!(first.tick, 1);
assert_eq!(first.action, "Search");
std::fs::remove_file(&path).ok();
}
#[test]
fn test_trace_subscriber_arc_wrapper() {
let subscriber = Arc::new(InMemoryTraceSubscriber::new());
let subscriber_trait: Arc<dyn TraceSubscriber> = subscriber.clone();
subscriber_trait.on_event(&make_test_action_event(1, "Test", true));
subscriber_trait.finish();
assert_eq!(subscriber.len(), 1);
}
fn make_test_action_event(
tick: u64,
action: &str,
success: bool,
) -> swarm_engine_core::events::ActionEvent {
use std::time::Duration;
use swarm_engine_core::events::{ActionEventBuilder, ActionEventResult};
use swarm_engine_core::types::WorkerId;
let result = if success {
ActionEventResult::success_with_output("ok")
} else {
ActionEventResult::failure("error")
};
ActionEventBuilder::new(tick, WorkerId(0), action)
.result(result)
.duration(Duration::from_millis(50))
.build()
}
}
#[cfg(feature = "llm-tests")]
mod integration {
#[test]
fn test_bootstrap_phase() {
}
#[test]
fn test_full_3step_workflow() {
}
}