143 lines
5.4 KiB
Rust
143 lines
5.4 KiB
Rust
mod common;
|
|
use common::TestVault;
|
|
use std::process::Command;
|
|
use assert_cmd::cargo::CommandCargoExt;
|
|
|
|
const BACKUP_PASS: &str = "strong-backup-pass-test-2026";
|
|
|
|
#[test]
|
|
fn export_then_restore_round_trip() {
|
|
let v = TestVault::init();
|
|
|
|
v.run(&["add", "login", "--title", "GitHub", "--username", "alice", "--password", "p"]);
|
|
v.run(&["add", "login", "--title", "Email", "--username", "bob", "--password", "q"]);
|
|
|
|
let backup_path = v.path().join("vault.relbak");
|
|
let out = v.run_with_backup_pass(
|
|
&["backup", "export", backup_path.to_str().unwrap()],
|
|
BACKUP_PASS,
|
|
);
|
|
assert!(out.status.success(), "export failed: {:?}", String::from_utf8_lossy(&out.stderr));
|
|
assert!(backup_path.exists());
|
|
assert!(v.path().join(".relicario/last_backup").exists());
|
|
|
|
// Restore into a fresh dir.
|
|
let restore_dir = tempfile::TempDir::new().unwrap();
|
|
let out = Command::cargo_bin("relicario")
|
|
.unwrap()
|
|
.current_dir(restore_dir.path())
|
|
.env("RELICARIO_TEST_BACKUP_PASSPHRASE", BACKUP_PASS)
|
|
.args(["backup", "restore", backup_path.to_str().unwrap(), "."])
|
|
.output()
|
|
.unwrap();
|
|
assert!(out.status.success(), "restore failed: {:?}", String::from_utf8_lossy(&out.stderr));
|
|
|
|
// Vault should be unlockable in the restore dir using the same passphrase + image.
|
|
// Since the original vault didn't include the image, we copy it in manually
|
|
// (the standard restore-without-image flow expects the user to keep their
|
|
// reference image separately).
|
|
std::fs::copy(&v.reference_image, restore_dir.path().join("reference.jpg")).unwrap();
|
|
|
|
let out = Command::cargo_bin("relicario")
|
|
.unwrap()
|
|
.current_dir(restore_dir.path())
|
|
.env("RELICARIO_TEST_PASSPHRASE", &v.passphrase)
|
|
.env("RELICARIO_IMAGE", restore_dir.path().join("reference.jpg"))
|
|
.args(["list"])
|
|
.output()
|
|
.unwrap();
|
|
let stdout = String::from_utf8(out.stdout).unwrap();
|
|
assert!(stdout.contains("GitHub"));
|
|
assert!(stdout.contains("Email"));
|
|
}
|
|
|
|
#[test]
|
|
fn restore_refuses_non_empty_target() {
|
|
let v = TestVault::init();
|
|
let backup_path = v.path().join("vault.relbak");
|
|
v.run_with_backup_pass(&["backup", "export", backup_path.to_str().unwrap()], BACKUP_PASS);
|
|
|
|
let out = Command::cargo_bin("relicario")
|
|
.unwrap()
|
|
.current_dir(v.path()) // already has a .relicario/
|
|
.env("RELICARIO_TEST_BACKUP_PASSPHRASE", BACKUP_PASS)
|
|
.args(["backup", "restore", backup_path.to_str().unwrap(), "."])
|
|
.output()
|
|
.unwrap();
|
|
assert!(!out.status.success());
|
|
let err = String::from_utf8(out.stderr).unwrap();
|
|
assert!(err.contains("already contains a relicario vault"), "stderr: {err}");
|
|
}
|
|
|
|
#[test]
|
|
fn export_with_include_image_round_trips_the_image() {
|
|
let v = TestVault::init();
|
|
let backup_path = v.path().join("vault.relbak");
|
|
v.run_with_backup_pass(
|
|
&["backup", "export", backup_path.to_str().unwrap(), "--include-image"],
|
|
BACKUP_PASS,
|
|
);
|
|
|
|
let restore_dir = tempfile::TempDir::new().unwrap();
|
|
let out = Command::cargo_bin("relicario")
|
|
.unwrap()
|
|
.current_dir(restore_dir.path())
|
|
.env("RELICARIO_TEST_BACKUP_PASSPHRASE", BACKUP_PASS)
|
|
.args(["backup", "restore", backup_path.to_str().unwrap(), "."])
|
|
.output()
|
|
.unwrap();
|
|
assert!(out.status.success(), "{:?}", String::from_utf8_lossy(&out.stderr));
|
|
assert!(restore_dir.path().join("reference.jpg").exists(),
|
|
"image should be restored when --include-image was used");
|
|
}
|
|
|
|
#[test]
|
|
fn export_with_no_history_skips_git_dir() {
|
|
let v = TestVault::init();
|
|
let backup_path = v.path().join("vault.relbak");
|
|
v.run_with_backup_pass(
|
|
&["backup", "export", backup_path.to_str().unwrap(), "--no-history"],
|
|
BACKUP_PASS,
|
|
);
|
|
|
|
let restore_dir = tempfile::TempDir::new().unwrap();
|
|
let out = Command::cargo_bin("relicario")
|
|
.unwrap()
|
|
.current_dir(restore_dir.path())
|
|
.env("RELICARIO_TEST_BACKUP_PASSPHRASE", BACKUP_PASS)
|
|
.args(["backup", "restore", backup_path.to_str().unwrap(), "."])
|
|
.output()
|
|
.unwrap();
|
|
assert!(out.status.success(), "{:?}", String::from_utf8_lossy(&out.stderr));
|
|
|
|
// .git/ should exist but contain only the "restore from backup ..." commit.
|
|
assert!(restore_dir.path().join(".git").is_dir());
|
|
let out = std::process::Command::new("git")
|
|
.current_dir(restore_dir.path())
|
|
.args(["log", "--oneline"])
|
|
.output()
|
|
.unwrap();
|
|
let log = String::from_utf8(out.stdout).unwrap();
|
|
assert_eq!(log.lines().count(), 1, "expected one commit, got: {log}");
|
|
assert!(log.contains("restore from backup"));
|
|
}
|
|
|
|
#[test]
|
|
fn wrong_backup_passphrase_fails() {
|
|
let v = TestVault::init();
|
|
let backup_path = v.path().join("vault.relbak");
|
|
v.run_with_backup_pass(&["backup", "export", backup_path.to_str().unwrap()], BACKUP_PASS);
|
|
|
|
let restore_dir = tempfile::TempDir::new().unwrap();
|
|
let out = Command::cargo_bin("relicario")
|
|
.unwrap()
|
|
.current_dir(restore_dir.path())
|
|
.env("RELICARIO_TEST_BACKUP_PASSPHRASE", "definitely-wrong")
|
|
.args(["backup", "restore", backup_path.to_str().unwrap(), "."])
|
|
.output()
|
|
.unwrap();
|
|
assert!(!out.status.success());
|
|
let err = String::from_utf8(out.stderr).unwrap();
|
|
assert!(err.contains("wrong backup passphrase"), "stderr: {err}");
|
|
}
|