use crate::utils::{EmbedExt, TestResources, archive::corrupt_first_chunk, setup};
use assert_cmd::cargo::cargo_bin_cmd;
use clap::Parser;
use portable_network_archive::cli;
use predicates::boolean::PredicateBooleanExt;
use predicates::str::contains;
#[test]
fn verify_without_corruption() {
setup();
TestResources::extract_in("raw/", "verify_ok/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_ok/verify_ok.pna",
"--overwrite",
"verify_ok/in/",
])
.unwrap()
.execute()
.unwrap();
cargo_bin_cmd!("pna")
.args(["experimental", "verify", "-f", "verify_ok/verify_ok.pna"])
.assert()
.success()
.stdout(contains("failed: 0"));
}
#[test]
fn verify_with_crc_mismatch() {
setup();
TestResources::extract_in("raw/", "verify_crc/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_crc/verify_crc.pna",
"--overwrite",
"verify_crc/in/",
])
.unwrap()
.execute()
.unwrap();
assert!(corrupt_first_chunk("verify_crc/verify_crc.pna", *b"FDAT", false).unwrap());
cargo_bin_cmd!("pna")
.args(["experimental", "verify", "-f", "verify_crc/verify_crc.pna"])
.assert()
.failure()
.stdout(
contains("FAILED")
.and(contains("failed: 1,"))
.and(contains("ok: 0,").not()),
);
}
#[test]
fn verify_with_stream_corruption() {
setup();
TestResources::extract_in("raw/", "verify_stream/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_stream/verify_stream.pna",
"--deflate",
"--overwrite",
"verify_stream/in/",
])
.unwrap()
.execute()
.unwrap();
assert!(corrupt_first_chunk("verify_stream/verify_stream.pna", *b"FDAT", true).unwrap());
cargo_bin_cmd!("pna")
.args([
"experimental",
"verify",
"-f",
"verify_stream/verify_stream.pna",
])
.assert()
.failure()
.stdout(contains("FAILED"));
}
#[test]
fn verify_with_fast_on_stream_corruption() {
setup();
TestResources::extract_in("raw/", "verify_fast/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_fast/verify_fast.pna",
"--deflate",
"--overwrite",
"verify_fast/in/",
])
.unwrap()
.execute()
.unwrap();
assert!(corrupt_first_chunk("verify_fast/verify_fast.pna", *b"FDAT", true).unwrap());
cargo_bin_cmd!("pna")
.args([
"experimental",
"verify",
"-f",
"verify_fast/verify_fast.pna",
"--fast",
])
.assert()
.success()
.stdout(contains("failed: 0"));
}
#[test]
fn verify_without_password_on_encrypted_archive() {
setup();
TestResources::extract_in("raw/", "verify_enc_skip/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_enc_skip/verify_enc_skip.pna",
"--overwrite",
"verify_enc_skip/in/",
"--password",
"password",
"--aes",
"ctr",
])
.unwrap()
.execute()
.unwrap();
cargo_bin_cmd!("pna")
.args([
"experimental",
"verify",
"-f",
"verify_enc_skip/verify_enc_skip.pna",
])
.assert()
.success()
.stdout(
contains("entries skipped (encrypted; no password provided)")
.and(contains("failed: 0"))
.and(contains("skipped (encrypted): 0").not()),
);
}
#[test]
fn verify_with_password_on_encrypted_archive() {
setup();
TestResources::extract_in("raw/", "verify_enc_ok/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_enc_ok/verify_enc_ok.pna",
"--overwrite",
"verify_enc_ok/in/",
"--password",
"password",
"--aes",
"ctr",
])
.unwrap()
.execute()
.unwrap();
cargo_bin_cmd!("pna")
.args([
"experimental",
"verify",
"-f",
"verify_enc_ok/verify_enc_ok.pna",
"--password",
"password",
])
.assert()
.success()
.stdout(contains("failed: 0").and(contains("skipped (encrypted): 0")));
}
#[test]
fn verify_with_wrong_password_on_encrypted_archive() {
setup();
TestResources::extract_in("raw/", "verify_enc_wrong/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_enc_wrong/verify_enc_wrong.pna",
"--overwrite",
"verify_enc_wrong/in/",
"--password",
"password",
"--aes",
"ctr",
])
.unwrap()
.execute()
.unwrap();
cargo_bin_cmd!("pna")
.args([
"experimental",
"verify",
"-f",
"verify_enc_wrong/verify_enc_wrong.pna",
"--password",
"wrong-password",
])
.assert()
.failure()
.stdout(contains("FAILED").and(contains(
"note: a wrong password is indistinguishable from corruption",
)));
}
#[test]
fn verify_with_solid_archive() {
setup();
TestResources::extract_in("raw/", "verify_solid/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_solid/verify_solid.pna",
"--overwrite",
"--solid",
"verify_solid/in/",
])
.unwrap()
.execute()
.unwrap();
cargo_bin_cmd!("pna")
.args([
"experimental",
"verify",
"-f",
"verify_solid/verify_solid.pna",
])
.assert()
.success()
.stdout(contains(
"total: 17, ok: 17, failed: 0, skipped (encrypted): 0",
));
}
#[test]
fn verify_with_fast_on_corrupted_solid_archive() {
setup();
TestResources::extract_in("raw/", "verify_fast_solid/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_fast_solid/verify_fast_solid.pna",
"--overwrite",
"--solid",
"verify_fast_solid/in/",
])
.unwrap()
.execute()
.unwrap();
assert!(
corrupt_first_chunk("verify_fast_solid/verify_fast_solid.pna", *b"SDAT", true).unwrap()
);
cargo_bin_cmd!("pna")
.args([
"experimental",
"verify",
"-f",
"verify_fast_solid/verify_fast_solid.pna",
"--fast",
])
.assert()
.failure()
.stdout(contains("FAILED"));
}
#[test]
fn verify_without_password_on_encrypted_solid_archive() {
setup();
TestResources::extract_in("raw/", "verify_solid_enc/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_solid_enc/verify_solid_enc.pna",
"--overwrite",
"--solid",
"verify_solid_enc/in/",
"--password",
"password",
"--aes",
"ctr",
])
.unwrap()
.execute()
.unwrap();
cargo_bin_cmd!("pna")
.args([
"experimental",
"verify",
"-f",
"verify_solid_enc/verify_solid_enc.pna",
])
.assert()
.success()
.stdout(
contains("<solid block #1>: skipped (encrypted)")
.and(contains("skipped (encrypted): 1")),
);
}
#[test]
fn verify_with_multipart_archive() {
setup();
TestResources::extract_in("raw/", "verify_multi/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_multi/verify_multi.pna",
"--overwrite",
"verify_multi/in/",
"--unstable",
"--split",
"1000",
])
.unwrap()
.execute()
.unwrap();
cargo_bin_cmd!("pna")
.args([
"experimental",
"verify",
"-f",
"verify_multi/verify_multi.part1.pna",
])
.assert()
.success()
.stdout(contains(
"total: 17, ok: 17, failed: 0, skipped (encrypted): 0",
));
}
#[test]
fn verify_with_size_hint_mismatch() {
setup();
TestResources::extract_in("raw/", "verify_fsiz/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_fsiz/verify_fsiz.pna",
"--overwrite",
"--store",
"verify_fsiz/in/",
])
.unwrap()
.execute()
.unwrap();
assert!(corrupt_first_chunk("verify_fsiz/verify_fsiz.pna", *b"fSIZ", true).unwrap());
cargo_bin_cmd!("pna")
.args([
"experimental",
"verify",
"-f",
"verify_fsiz/verify_fsiz.pna",
])
.assert()
.success()
.stderr(contains("size hint (fSIZ) mismatch"));
}
#[test]
fn verify_with_truncated_archive() {
setup();
TestResources::extract_in("raw/", "verify_trunc/in/").unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"c",
"-f",
"verify_trunc/verify_trunc.pna",
"--overwrite",
"verify_trunc/in/",
])
.unwrap()
.execute()
.unwrap();
let len = std::fs::metadata("verify_trunc/verify_trunc.pna")
.unwrap()
.len();
let file = std::fs::OpenOptions::new()
.write(true)
.open("verify_trunc/verify_trunc.pna")
.unwrap();
file.set_len(len / 2).unwrap();
cargo_bin_cmd!("pna")
.args([
"experimental",
"verify",
"-f",
"verify_trunc/verify_trunc.pna",
])
.assert()
.failure()
.stdout(contains("total: "))
.stderr(contains("archive structure is broken"));
}