test(core): backup error paths
Covers bad magic, unsupported version, wrong passphrase, truncation, and tampered ciphertext. The wrong-passphrase / tampered-tag pair both collapse to RelicarioError::Decrypt — same opaque-failure contract as the live vault.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
//! Backup container round-trip + error-path coverage.
|
||||
|
||||
use relicario_core::backup::{pack_backup, unpack_backup, BackupInput, BackupOutput};
|
||||
use relicario_core::backup::{pack_backup, unpack_backup, BackupInput};
|
||||
|
||||
fn empty_input() -> BackupInput<'static> {
|
||||
BackupInput {
|
||||
@@ -131,3 +131,58 @@ fn no_history_produces_strict_subset() {
|
||||
with.len(), without.len()
|
||||
);
|
||||
}
|
||||
|
||||
use relicario_core::RelicarioError;
|
||||
|
||||
#[test]
|
||||
fn bad_magic_rejected() {
|
||||
let mut bytes = pack_backup(empty_input(), "p").unwrap();
|
||||
bytes[0] = b'X';
|
||||
match unpack_backup(&bytes, "p") {
|
||||
Err(RelicarioError::BackupBadMagic) => {}
|
||||
other => panic!("expected BackupBadMagic, got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsupported_version_rejected() {
|
||||
let mut bytes = pack_backup(empty_input(), "p").unwrap();
|
||||
bytes[4] = 0xFF;
|
||||
match unpack_backup(&bytes, "p") {
|
||||
Err(RelicarioError::BackupUnsupportedVersion { found, expected }) => {
|
||||
assert_eq!(found, 0xFF);
|
||||
assert_eq!(expected, 0x01);
|
||||
}
|
||||
other => panic!("expected BackupUnsupportedVersion, got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_passphrase_rejected_as_decrypt_error() {
|
||||
let bytes = pack_backup(empty_input(), "right-passphrase").unwrap();
|
||||
match unpack_backup(&bytes, "wrong-passphrase") {
|
||||
Err(RelicarioError::Decrypt) => {}
|
||||
other => panic!("expected Decrypt (opaque), got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncated_file_rejected() {
|
||||
let bytes = pack_backup(empty_input(), "p").unwrap();
|
||||
let truncated = &bytes[..bytes.len().min(60)]; // shorter than HEADER_LEN + TAG_LEN
|
||||
match unpack_backup(truncated, "p") {
|
||||
Err(RelicarioError::Format(_)) => {}
|
||||
other => panic!("expected Format(truncated), got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tampered_ciphertext_rejected_as_decrypt_error() {
|
||||
let mut bytes = pack_backup(empty_input(), "p").unwrap();
|
||||
let last = bytes.len() - 1;
|
||||
bytes[last] ^= 0xFF; // flip a byte in the auth-tag region
|
||||
match unpack_backup(&bytes, "p") {
|
||||
Err(RelicarioError::Decrypt) => {}
|
||||
other => panic!("expected Decrypt for tampered tag, got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user