#![cfg(feature = "lzma2")]
use std::io::Cursor;
use zesven::ArchivePath;
use zesven::write::{WriteOptions, Writer};
fn payload(len: usize) -> Vec<u8> {
let mut data = Vec::with_capacity(len);
let mut state = 0x2545_F491_4F6C_DD1Du64;
while data.len() < len {
state ^= state << 13;
state ^= state >> 7;
state ^= state << 17;
data.extend_from_slice(b"an option that does nothing is worse than no option ");
data.extend_from_slice(&state.to_le_bytes());
}
data.truncate(len);
data
}
fn x86_like_payload(len: usize) -> Vec<u8> {
let mut data = Vec::with_capacity(len);
let mut target = 0u32;
while data.len() < len {
data.extend_from_slice(&[0x55, 0x48, 0x89, 0xe5]); data.push(0xe8);
data.extend_from_slice(&target.to_le_bytes());
data.extend_from_slice(&[0x48, 0x83, 0xec, 0x20]); target = target.wrapping_add(0x40);
}
data.truncate(len);
data
}
fn archive_with(options: WriteOptions) -> (Vec<u8>, Vec<u8>) {
archive_of(options, &payload(96 * 1024))
}
fn archive_of(options: WriteOptions, data: &[u8]) -> (Vec<u8>, Vec<u8>) {
const SIGNATURE_HEADER: usize = 32;
let mut writer = Writer::create(Cursor::new(Vec::new()))
.unwrap()
.options(options);
writer
.add_bytes(ArchivePath::new("first.bin").unwrap(), data)
.unwrap();
writer
.add_bytes(ArchivePath::new("second.bin").unwrap(), data)
.unwrap();
let (result, cursor) = writer.finish_into_inner().unwrap();
let bytes = cursor.into_inner();
let packed =
bytes[SIGNATURE_HEADER..SIGNATURE_HEADER + result.compressed_size as usize].to_vec();
(bytes, packed)
}
fn assert_changes_compressed_data(what: &str, options: WriteOptions) {
let (_, baseline) = archive_with(WriteOptions::new());
let (_, changed) = archive_with(options);
assert_ne!(
baseline,
changed,
"{what} produced byte-identical packed streams ({} bytes), \
so it is not reaching the encoder",
baseline.len(),
);
}
fn assert_changes_archive(what: &str, options: WriteOptions) {
let (baseline, _) = archive_with(WriteOptions::new());
let (changed, _) = archive_with(options);
assert_ne!(
baseline, changed,
"{what} produced a byte-identical archive, so nothing reads it",
);
}
#[test]
fn test_level_reaches_the_encoder() {
assert_changes_compressed_data("level(1)", WriteOptions::new().level(1).unwrap());
assert_changes_compressed_data("level(9)", WriteOptions::new().level(9).unwrap());
}
#[test]
fn test_method_reaches_the_encoder() {
use zesven::codec::CodecMethod;
let methods: &[(&str, CodecMethod)] = &[
("method(Copy)", CodecMethod::Copy),
#[cfg(feature = "lzma")]
("method(Lzma)", CodecMethod::Lzma),
#[cfg(feature = "deflate")]
("method(Deflate)", CodecMethod::Deflate),
#[cfg(feature = "bzip2")]
("method(BZip2)", CodecMethod::BZip2),
#[cfg(feature = "ppmd")]
("method(PPMd)", CodecMethod::PPMd),
];
for (what, method) in methods {
assert_changes_compressed_data(what, WriteOptions::new().method(*method));
}
}
#[test]
fn test_filter_reaches_the_encoder() {
use zesven::WriteFilter;
assert_changes_compressed_data("filter(Delta)", WriteOptions::new().delta(4));
let code = x86_like_payload(96 * 1024);
let (_, baseline) = archive_of(WriteOptions::new(), &code);
let (_, filtered) = archive_of(WriteOptions::new().filter(WriteFilter::BcjX86), &code);
assert_ne!(
baseline, filtered,
"filter(BcjX86) produced byte-identical packed streams on x86-shaped \
data, so it is not reaching the encoder",
);
}
#[test]
fn test_solid_reaches_the_encoder() {
assert_changes_compressed_data("solid()", WriteOptions::new().solid());
}
#[test]
fn test_comment_reaches_the_header() {
assert_changes_archive("comment()", WriteOptions::new().comment("a comment"));
}
#[cfg(feature = "aes")]
#[test]
fn test_encryption_options_reach_the_encoder() {
use zesven::crypto::NoncePolicy;
let encrypted = || {
WriteOptions::new()
.password("correct horse battery staple")
.nonce_policy(NoncePolicy::random_with_params(4, 8))
};
assert_changes_compressed_data("encrypt_data(true)", encrypted().encrypt_data(true));
assert_changes_archive("encrypt_header(true)", encrypted().encrypt_header(true));
}