use super::*;
use tempfile::TempDir;
#[test]
fn test_ROLLBACK_001_manager_creation() {
let temp_dir = TempDir::new().unwrap();
let manager = RollbackManager::new(temp_dir.path().join("backups")).unwrap();
assert!(manager.backup_dir().exists());
assert!(manager.is_auto_rollback());
assert_eq!(manager.step_count(), 0);
}
#[test]
fn test_ROLLBACK_002_register_step() {
let temp_dir = TempDir::new().unwrap();
let mut manager = RollbackManager::new(temp_dir.path().join("backups")).unwrap();
manager.register_step("step-1", "First Step");
manager.register_step("step-2", "Second Step");
assert_eq!(manager.step_count(), 2);
assert!(manager.get_step("step-1").is_some());
assert!(manager.get_step("step-2").is_some());
assert!(manager.get_step("step-3").is_none());
}
#[test]
fn test_ROLLBACK_003_add_rollback_action() {
let temp_dir = TempDir::new().unwrap();
let mut manager = RollbackManager::new(temp_dir.path().join("backups")).unwrap();
let step = manager.register_step("step-1", "Test Step");
step.add_action(RollbackAction::command("rm -f /tmp/test"));
step.add_action(RollbackAction::remove_file("/tmp/created"));
let step = manager.get_step("step-1").unwrap();
assert_eq!(step.actions.len(), 2);
}
#[test]
fn test_ROLLBACK_004_step_completion() {
let temp_dir = TempDir::new().unwrap();
let mut manager = RollbackManager::new(temp_dir.path().join("backups")).unwrap();
let step = manager.register_step("step-1", "Test Step");
step.add_action(RollbackAction::command("echo rollback"));
assert!(!step.completed);
assert!(step.needs_rollback());
step.mark_completed();
assert!(step.completed);
assert!(!step.needs_rollback()); }
#[test]
fn test_ROLLBACK_005_step_failure() {
let temp_dir = TempDir::new().unwrap();
let mut manager = RollbackManager::new(temp_dir.path().join("backups")).unwrap();
let step = manager.register_step("step-1", "Test Step");
step.add_action(RollbackAction::command("echo rollback"));
step.mark_failed("Command failed with exit code 1");
let step = manager.get_step("step-1").unwrap();
assert!(!step.completed);
assert!(step.needs_rollback());
assert_eq!(
step.error,
Some("Command failed with exit code 1".to_string())
);
}
#[test]
fn test_ROLLBACK_006_backup_file() {
let temp_dir = TempDir::new().unwrap();
let mut manager = RollbackManager::new(temp_dir.path().join("backups")).unwrap();
let test_file = temp_dir.path().join("test.txt");
std::fs::write(&test_file, "original content").unwrap();
manager.register_step("step-1", "Test Step");
let backup = manager.backup_file("step-1", &test_file).unwrap();
assert!(backup.existed);
assert!(backup.backup_path.exists());
assert_eq!(
std::fs::read_to_string(&backup.backup_path).unwrap(),
"original content"
);
let step = manager.get_step("step-1").unwrap();
assert_eq!(step.actions.len(), 1);
assert!(matches!(
&step.actions[0],
RollbackAction::RestoreFile { .. }
));
}
#[test]
fn test_ROLLBACK_007_backup_nonexistent_file() {
let temp_dir = TempDir::new().unwrap();
let mut manager = RollbackManager::new(temp_dir.path().join("backups")).unwrap();
let test_file = temp_dir.path().join("nonexistent.txt");
manager.register_step("step-1", "Test Step");
let backup = manager.backup_file("step-1", &test_file).unwrap();
assert!(!backup.existed);
assert_eq!(backup.content_hash, "nonexistent");
let step = manager.get_step("step-1").unwrap();
assert_eq!(step.actions.len(), 1);
assert!(matches!(&step.actions[0], RollbackAction::RemoveFile(_)));
}
#[test]
fn test_ROLLBACK_008_plan_rollback_from_step() {
let temp_dir = TempDir::new().unwrap();
let mut manager = RollbackManager::new(temp_dir.path().join("backups")).unwrap();
let step = manager.register_step("step-1", "First");
step.add_action(RollbackAction::command("echo 1"));
step.mark_completed();
let step = manager.register_step("step-2", "Second");
step.add_action(RollbackAction::command("echo 2"));
step.mark_completed();
let step = manager.register_step("step-3", "Third");
step.add_action(RollbackAction::command("echo 3"));
let plan = manager.plan_rollback_from("step-2").unwrap();
assert_eq!(plan.steps.len(), 2);
assert_eq!(plan.steps[0].step_id, "step-2");
assert_eq!(plan.steps[1].step_id, "step-1");
}
#[test]
fn test_ROLLBACK_009_plan_summary() {
let temp_dir = TempDir::new().unwrap();
let mut manager = RollbackManager::new(temp_dir.path().join("backups")).unwrap();
let step = manager.register_step("step-1", "Install Package");
step.add_action(RollbackAction::RestorePackages {
install: vec!["pkg-old".to_string()],
remove: vec!["pkg-new".to_string()],
});
step.mark_completed();
let plan = manager.plan_rollback_from("step-1").unwrap();
let summary = plan.summary();
assert!(summary.contains("Install Package"));
assert!(summary.contains("Reinstall: pkg-old"));
assert!(summary.contains("Remove: pkg-new"));
}
#[test]
fn test_ROLLBACK_010_action_descriptions() {
let actions = [
RollbackAction::Command("rm -f /tmp/test".to_string()),
RollbackAction::RestoreFile {
original_path: PathBuf::from("/etc/config"),
backup_path: PathBuf::from("/backup/config"),
},
RollbackAction::RemoveFile(PathBuf::from("/tmp/created")),
RollbackAction::RemoveDirectory(PathBuf::from("/opt/app")),
RollbackAction::RestoreService {
name: "nginx".to_string(),
was_enabled: true,
was_running: false,
},
RollbackAction::RestoreUserGroup {
user: "alice".to_string(),
group: "docker".to_string(),
was_member: false,
},
RollbackAction::None,
];
let descriptions: Vec<_> = actions.iter().map(|a| a.description()).collect();
assert!(descriptions[0].contains("Execute: rm -f"));
assert!(descriptions[1].contains("Restore /etc/config"));
assert!(descriptions[2].contains("Remove file: /tmp/created"));
assert!(descriptions[3].contains("Remove directory: /opt/app"));
assert!(descriptions[4].contains("Service nginx: enable, stop"));
assert!(descriptions[5].contains("Remove alice from group docker"));
assert!(descriptions[6].contains("No action required"));
}
#[test]
fn test_ROLLBACK_011_rollback_actions_reverse_order() {
let mut step = StepRollback::new("step-1", "Test");
step.add_action(RollbackAction::command("first"));
step.add_action(RollbackAction::command("second"));
step.add_action(RollbackAction::command("third"));
let actions: Vec<_> = step.rollback_actions().collect();
assert!(matches!(&actions[0], RollbackAction::Command(s) if s == "third"));
assert!(matches!(&actions[1], RollbackAction::Command(s) if s == "second"));
assert!(matches!(&actions[2], RollbackAction::Command(s) if s == "first"));
}
#[test]
fn test_ROLLBACK_012_counts() {
let temp_dir = TempDir::new().unwrap();
let mut manager = RollbackManager::new(temp_dir.path().join("backups")).unwrap();
let step = manager.register_step("step-1", "First");
step.mark_completed();
let step = manager.register_step("step-2", "Second");
step.mark_completed();
let step = manager.register_step("step-3", "Third");
step.mark_failed("Error");
assert_eq!(manager.step_count(), 3);
assert_eq!(manager.completed_count(), 2);
assert_eq!(manager.failed_count(), 1);
}