//! Unit tests for g3-ensembles #[cfg(test)] mod tests { use crate::status::{FlockStatus, SegmentState, SegmentStatus}; use chrono::Utc; use std::path::PathBuf; #[test] fn test_segment_state_display() { assert_eq!(format!("{}", SegmentState::Pending), "⏳ Pending"); assert_eq!(format!("{}", SegmentState::Running), "🔄 Running"); assert_eq!(format!("{}", SegmentState::Completed), "✅ Completed"); assert_eq!(format!("{}", SegmentState::Failed), "❌ Failed"); assert_eq!(format!("{}", SegmentState::Cancelled), "⚠️ Cancelled"); } #[test] fn test_flock_status_creation() { let status = FlockStatus::new( "test-session".to_string(), PathBuf::from("/test/project"), PathBuf::from("/test/workspace"), 3, ); assert_eq!(status.session_id, "test-session"); assert_eq!(status.num_segments, 3); assert_eq!(status.segments.len(), 0); assert_eq!(status.total_tokens, 0); assert_eq!(status.total_tool_calls, 0); assert_eq!(status.total_errors, 0); assert!(status.completed_at.is_none()); } #[test] fn test_segment_status_update() { let mut status = FlockStatus::new( "test-session".to_string(), PathBuf::from("/test/project"), PathBuf::from("/test/workspace"), 2, ); let segment1 = SegmentStatus { segment_id: 1, workspace: PathBuf::from("/test/workspace/segment-1"), state: SegmentState::Completed, started_at: Utc::now(), completed_at: Some(Utc::now()), tokens_used: 1000, tool_calls: 50, errors: 2, current_turn: 5, max_turns: 10, last_message: Some("Done".to_string()), error_message: None, }; status.update_segment(1, segment1); assert_eq!(status.segments.len(), 1); assert_eq!(status.total_tokens, 1000); assert_eq!(status.total_tool_calls, 50); assert_eq!(status.total_errors, 2); } #[test] fn test_multiple_segment_updates() { let mut status = FlockStatus::new( "test-session".to_string(), PathBuf::from("/test/project"), PathBuf::from("/test/workspace"), 2, ); let segment1 = SegmentStatus { segment_id: 1, workspace: PathBuf::from("/test/workspace/segment-1"), state: SegmentState::Completed, started_at: Utc::now(), completed_at: Some(Utc::now()), tokens_used: 1000, tool_calls: 50, errors: 2, current_turn: 5, max_turns: 10, last_message: Some("Done".to_string()), error_message: None, }; let segment2 = SegmentStatus { segment_id: 2, workspace: PathBuf::from("/test/workspace/segment-2"), state: SegmentState::Failed, started_at: Utc::now(), completed_at: Some(Utc::now()), tokens_used: 500, tool_calls: 25, errors: 5, current_turn: 3, max_turns: 10, last_message: Some("Error".to_string()), error_message: Some("Test error".to_string()), }; status.update_segment(1, segment1); status.update_segment(2, segment2); assert_eq!(status.segments.len(), 2); assert_eq!(status.total_tokens, 1500); assert_eq!(status.total_tool_calls, 75); assert_eq!(status.total_errors, 7); } #[test] fn test_is_complete() { let mut status = FlockStatus::new( "test-session".to_string(), PathBuf::from("/test/project"), PathBuf::from("/test/workspace"), 2, ); // Not complete - no segments assert!(!status.is_complete()); // Add one completed segment let segment1 = SegmentStatus { segment_id: 1, workspace: PathBuf::from("/test/workspace/segment-1"), state: SegmentState::Completed, started_at: Utc::now(), completed_at: Some(Utc::now()), tokens_used: 1000, tool_calls: 50, errors: 0, current_turn: 5, max_turns: 10, last_message: None, error_message: None, }; status.update_segment(1, segment1); // Still not complete - only 1 of 2 segments assert!(!status.is_complete()); // Add second segment (running) let segment2 = SegmentStatus { segment_id: 2, workspace: PathBuf::from("/test/workspace/segment-2"), state: SegmentState::Running, started_at: Utc::now(), completed_at: None, tokens_used: 500, tool_calls: 25, errors: 0, current_turn: 3, max_turns: 10, last_message: None, error_message: None, }; status.update_segment(2, segment2); // Still not complete - segment 2 is running assert!(!status.is_complete()); // Update segment 2 to completed let segment2_done = SegmentStatus { segment_id: 2, workspace: PathBuf::from("/test/workspace/segment-2"), state: SegmentState::Completed, started_at: Utc::now(), completed_at: Some(Utc::now()), tokens_used: 500, tool_calls: 25, errors: 0, current_turn: 5, max_turns: 10, last_message: None, error_message: None, }; status.update_segment(2, segment2_done); // Now complete assert!(status.is_complete()); } #[test] fn test_count_by_state() { let mut status = FlockStatus::new( "test-session".to_string(), PathBuf::from("/test/project"), PathBuf::from("/test/workspace"), 3, ); let segment1 = SegmentStatus { segment_id: 1, workspace: PathBuf::from("/test/workspace/segment-1"), state: SegmentState::Completed, started_at: Utc::now(), completed_at: Some(Utc::now()), tokens_used: 1000, tool_calls: 50, errors: 0, current_turn: 5, max_turns: 10, last_message: None, error_message: None, }; let segment2 = SegmentStatus { segment_id: 2, workspace: PathBuf::from("/test/workspace/segment-2"), state: SegmentState::Failed, started_at: Utc::now(), completed_at: Some(Utc::now()), tokens_used: 500, tool_calls: 25, errors: 5, current_turn: 3, max_turns: 10, last_message: None, error_message: Some("Error".to_string()), }; let segment3 = SegmentStatus { segment_id: 3, workspace: PathBuf::from("/test/workspace/segment-3"), state: SegmentState::Completed, started_at: Utc::now(), completed_at: Some(Utc::now()), tokens_used: 800, tool_calls: 40, errors: 1, current_turn: 4, max_turns: 10, last_message: None, error_message: None, }; status.update_segment(1, segment1); status.update_segment(2, segment2); status.update_segment(3, segment3); assert_eq!(status.count_by_state(SegmentState::Completed), 2); assert_eq!(status.count_by_state(SegmentState::Failed), 1); assert_eq!(status.count_by_state(SegmentState::Running), 0); assert_eq!(status.count_by_state(SegmentState::Pending), 0); } #[test] fn test_status_serialization() { let mut status = FlockStatus::new( "test-session".to_string(), PathBuf::from("/test/project"), PathBuf::from("/test/workspace"), 1, ); let segment1 = SegmentStatus { segment_id: 1, workspace: PathBuf::from("/test/workspace/segment-1"), state: SegmentState::Completed, started_at: Utc::now(), completed_at: Some(Utc::now()), tokens_used: 1000, tool_calls: 50, errors: 2, current_turn: 5, max_turns: 10, last_message: Some("Done".to_string()), error_message: None, }; status.update_segment(1, segment1); // Serialize to JSON let json = serde_json::to_string(&status).expect("Failed to serialize"); assert!(json.contains("test-session")); assert!(json.contains("segment_id")); assert!(json.contains("Completed")); // Deserialize back let deserialized: FlockStatus = serde_json::from_str(&json).expect("Failed to deserialize"); assert_eq!(deserialized.session_id, "test-session"); assert_eq!(deserialized.segments.len(), 1); assert_eq!(deserialized.total_tokens, 1000); } #[test] fn test_report_generation() { let mut status = FlockStatus::new( "test-session".to_string(), PathBuf::from("/test/project"), PathBuf::from("/test/workspace"), 2, ); let segment1 = SegmentStatus { segment_id: 1, workspace: PathBuf::from("/test/workspace/segment-1"), state: SegmentState::Completed, started_at: Utc::now(), completed_at: Some(Utc::now()), tokens_used: 1000, tool_calls: 50, errors: 2, current_turn: 5, max_turns: 10, last_message: Some("Done".to_string()), error_message: None, }; status.update_segment(1, segment1); let report = status.generate_report(); // Check that report contains expected sections assert!(report.contains("FLOCK MODE SESSION REPORT")); assert!(report.contains("test-session")); assert!(report.contains("Segment Status:")); assert!(report.contains("Aggregate Metrics:")); assert!(report.contains("Segment Details:")); assert!(report.contains("Total Tokens: 1000")); assert!(report.contains("Total Tool Calls: 50")); assert!(report.contains("Total Errors: 2")); } }