use agent_core::{Checkpoint, CheckpointManager, FileDiff, SessionHistory, SessionStats}; use std::fs; use std::path::PathBuf; use tempfile::TempDir; #[test] fn test_checkpoint_save_and_load() { let temp_dir = TempDir::new().unwrap(); let checkpoint_dir = temp_dir.path().to_path_buf(); let stats = SessionStats::new(); let mut history = SessionHistory::new(); history.add_user_message("Hello".to_string()); history.add_assistant_message("Hi there!".to_string()); let file_diffs = vec![FileDiff::new( PathBuf::from("test.txt"), "before".to_string(), "after".to_string(), )]; let checkpoint = Checkpoint::new( "test-checkpoint".to_string(), stats.clone(), &history, file_diffs, ); // Save checkpoint checkpoint.save(&checkpoint_dir).unwrap(); // Load checkpoint let loaded = Checkpoint::load(&checkpoint_dir, "test-checkpoint").unwrap(); assert_eq!(loaded.id, "test-checkpoint"); assert_eq!(loaded.user_prompts, vec!["Hello"]); assert_eq!(loaded.assistant_responses, vec!["Hi there!"]); assert_eq!(loaded.file_diffs.len(), 1); assert_eq!(loaded.file_diffs[0].path, PathBuf::from("test.txt")); assert_eq!(loaded.file_diffs[0].before, "before"); assert_eq!(loaded.file_diffs[0].after, "after"); } #[test] fn test_checkpoint_list() { let temp_dir = TempDir::new().unwrap(); let checkpoint_dir = temp_dir.path().to_path_buf(); // Create a few checkpoints for i in 1..=3 { let checkpoint = Checkpoint::new( format!("checkpoint-{}", i), SessionStats::new(), &SessionHistory::new(), vec![], ); checkpoint.save(&checkpoint_dir).unwrap(); } let checkpoints = Checkpoint::list(&checkpoint_dir).unwrap(); assert_eq!(checkpoints.len(), 3); assert!(checkpoints.contains(&"checkpoint-1".to_string())); assert!(checkpoints.contains(&"checkpoint-2".to_string())); assert!(checkpoints.contains(&"checkpoint-3".to_string())); } #[test] fn test_checkpoint_manager_snapshot_and_diff() { let temp_dir = TempDir::new().unwrap(); let checkpoint_dir = temp_dir.path().join("checkpoints"); let test_file = temp_dir.path().join("test.txt"); // Create initial file content fs::write(&test_file, "initial content").unwrap(); let mut manager = CheckpointManager::new(checkpoint_dir.clone()); // Snapshot the file manager.snapshot_file(&test_file).unwrap(); // Modify the file fs::write(&test_file, "modified content").unwrap(); // Create a diff let diff = manager.create_diff(&test_file).unwrap(); assert!(diff.is_some()); let diff = diff.unwrap(); assert_eq!(diff.path, test_file); assert_eq!(diff.before, "initial content"); assert_eq!(diff.after, "modified content"); } #[test] fn test_checkpoint_manager_save_and_restore() { let temp_dir = TempDir::new().unwrap(); let checkpoint_dir = temp_dir.path().join("checkpoints"); let test_file = temp_dir.path().join("test.txt"); // Create initial file content fs::write(&test_file, "initial content").unwrap(); let mut manager = CheckpointManager::new(checkpoint_dir.clone()); // Snapshot the file manager.snapshot_file(&test_file).unwrap(); // Modify the file fs::write(&test_file, "modified content").unwrap(); // Save checkpoint let mut history = SessionHistory::new(); history.add_user_message("test".to_string()); let checkpoint = manager .save_checkpoint("test-checkpoint".to_string(), SessionStats::new(), &history) .unwrap(); assert_eq!(checkpoint.file_diffs.len(), 1); assert_eq!(checkpoint.file_diffs[0].before, "initial content"); assert_eq!(checkpoint.file_diffs[0].after, "modified content"); // Modify file again fs::write(&test_file, "final content").unwrap(); assert_eq!(fs::read_to_string(&test_file).unwrap(), "final content"); // Rewind to checkpoint let restored_files = manager.rewind_to("test-checkpoint").unwrap(); assert_eq!(restored_files.len(), 1); assert_eq!(restored_files[0], test_file); // File should be reverted to initial content (before the checkpoint) assert_eq!(fs::read_to_string(&test_file).unwrap(), "initial content"); } #[test] fn test_checkpoint_manager_multiple_files() { let temp_dir = TempDir::new().unwrap(); let checkpoint_dir = temp_dir.path().join("checkpoints"); let test_file1 = temp_dir.path().join("file1.txt"); let test_file2 = temp_dir.path().join("file2.txt"); // Create initial files fs::write(&test_file1, "file1 initial").unwrap(); fs::write(&test_file2, "file2 initial").unwrap(); let mut manager = CheckpointManager::new(checkpoint_dir.clone()); // Snapshot both files manager.snapshot_file(&test_file1).unwrap(); manager.snapshot_file(&test_file2).unwrap(); // Modify both files fs::write(&test_file1, "file1 modified").unwrap(); fs::write(&test_file2, "file2 modified").unwrap(); // Save checkpoint let checkpoint = manager .save_checkpoint( "multi-file-checkpoint".to_string(), SessionStats::new(), &SessionHistory::new(), ) .unwrap(); assert_eq!(checkpoint.file_diffs.len(), 2); // Modify files again fs::write(&test_file1, "file1 final").unwrap(); fs::write(&test_file2, "file2 final").unwrap(); // Rewind let restored_files = manager.rewind_to("multi-file-checkpoint").unwrap(); assert_eq!(restored_files.len(), 2); // Both files should be reverted assert_eq!(fs::read_to_string(&test_file1).unwrap(), "file1 initial"); assert_eq!(fs::read_to_string(&test_file2).unwrap(), "file2 initial"); } #[test] fn test_checkpoint_no_changes() { let temp_dir = TempDir::new().unwrap(); let checkpoint_dir = temp_dir.path().join("checkpoints"); let test_file = temp_dir.path().join("test.txt"); // Create file fs::write(&test_file, "content").unwrap(); let mut manager = CheckpointManager::new(checkpoint_dir.clone()); // Snapshot the file manager.snapshot_file(&test_file).unwrap(); // Don't modify the file // Create diff - should be None because nothing changed let diff = manager.create_diff(&test_file).unwrap(); assert!(diff.is_none()); // Save checkpoint - should have no diffs let checkpoint = manager .save_checkpoint( "no-change-checkpoint".to_string(), SessionStats::new(), &SessionHistory::new(), ) .unwrap(); assert_eq!(checkpoint.file_diffs.len(), 0); }