use super::super::super::*;
use super::super::fixtures::*;
use crate::test_support::temp_dir;
use canic_backup::persistence::BackupLayout;
use std::fs;
#[test]
fn live_create_refuses_before_creating_or_modifying_a_layout() {
let root = temp_dir("canic-cli-backup-create-unavailable");
let existing = root.join("existing");
fs::create_dir_all(&existing).expect("create retained output");
fs::write(existing.join("retained"), b"evidence").expect("retain evidence");
for out in [root.join("new"), existing.clone()] {
let options = BackupCreateOptions {
fleet: "unavailable-live-backup".to_string(),
subtree: None,
out: Some(out),
dry_run: false,
environment: "local".to_string(),
icp: root.join("nonexistent-icp").display().to_string(),
};
std::assert_matches!(
create::backup_create(&options),
Err(BackupCommandError::LiveCreateUnavailable)
);
}
assert!(!root.join("new").exists());
assert_eq!(fs::read_dir(&root).unwrap().count(), 1);
assert_eq!(fs::read_dir(&existing).unwrap().count(), 1);
assert_eq!(fs::read(existing.join("retained")).unwrap(), b"evidence");
fs::remove_dir_all(root).expect("remove test output");
}
#[test]
fn backup_create_persistence_rejects_incompatible_existing_layout() {
let root = temp_dir("canic-cli-backup-create-incompatible-resume");
let plan = valid_backup_plan();
persist_backup_create_dry_run(&root, &plan).expect("persist initial plan");
let mut requested = valid_backup_plan();
requested.environment = "ic".to_string();
let err = persist_backup_create_dry_run(&root, &requested)
.expect_err("incompatible existing layout rejects");
fs::remove_dir_all(root).expect("remove temp root");
std::assert_matches!(
err,
BackupCommandError::BackupLayoutMismatch {
field: "environment",
existing,
requested,
} if existing == "local" && requested == "ic"
);
}
#[test]
fn backup_create_persistence_rejects_dry_run_layout_for_execute_request() {
let root = temp_dir("canic-cli-backup-create-dry-run-execute-mismatch");
let plan = valid_backup_plan();
persist_backup_create_dry_run(&root, &plan).expect("persist dry-run plan");
let requested = valid_executable_backup_plan();
let err = persist_backup_create_dry_run(&root, &requested)
.expect_err("dry-run layout rejects execute request");
fs::remove_dir_all(root).expect("remove temp root");
std::assert_matches!(
err,
BackupCommandError::BackupLayoutMismatch {
field: "requires_root_controller",
existing,
requested,
} if existing == "true" && requested == "false"
);
}
#[test]
fn backup_create_persistence_rejects_plan_layout_missing_execution_journal() {
let root = temp_dir("canic-cli-backup-create-plan-missing-execution-journal");
let plan = valid_backup_plan();
BackupLayout::new(root.clone())
.write_backup_plan(&plan)
.expect("write backup plan");
let err = persist_backup_create_dry_run(&root, &plan)
.expect_err("plan layout missing execution journal rejects");
fs::remove_dir_all(root).expect("remove temp root");
std::assert_matches!(
err,
BackupCommandError::BackupLayoutIncomplete {
missing: "backup-execution-journal.json"
}
);
}
#[test]
fn backup_create_persistence_rejects_manifest_layout_missing_execution_journal() {
let root = temp_dir("canic-cli-backup-create-missing-execution-journal");
let plan = valid_backup_plan();
write_manifest_plan_without_execution_journal(&root);
let err = persist_backup_create_dry_run(&root, &plan)
.expect_err("manifest layout missing execution journal rejects");
fs::remove_dir_all(root).expect("remove temp root");
std::assert_matches!(
err,
BackupCommandError::BackupLayoutIncomplete {
missing: "backup-execution-journal.json"
}
);
}