use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;
use bzip2::write::BzEncoder;
fn corpus(len: usize) -> Vec<u8> {
const WORDS: &[&str] = &[
"the", "quick", "brown", "fox", "GET", "POST", "200", "404", "error", "info", "debug",
"user", "session", "token", "request", "response", "latency", "bytes", "cache", "hit",
"miss", "shard", "commit", "deploy", "node", "cluster", "worker", "thread", "queue",
"buffer", "stream", "decode", "payload", "checksum", "offset", "length", "dur_ms=42",
];
let mut state: u64 = 0x9E37_79B9_7F4A_7C15;
let mut next = || {
state = state.wrapping_add(0x9E37_79B9_7F4A_7C15);
let mut z = state;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
};
let mut out = Vec::with_capacity(len + 256);
while out.len() < len {
let n = 6 + (next() % 10) as usize;
for i in 0..n {
if i > 0 {
out.push(b' ');
}
out.extend_from_slice(WORDS[(next() as usize) % WORDS.len()].as_bytes());
}
out.push(b'\n');
}
out.truncate(len);
out
}
fn write_bz2(path: &Path, data: &[u8]) {
let f = File::create(path).expect("create bz2");
let mut enc = BzEncoder::new(std::io::BufWriter::new(f), bzip2::Compression::best());
enc.write_all(data).expect("bz2 write");
enc.finish().expect("bz2 finish").flush().expect("flush bz2");
}
fn run_lbunzip2(bz2_path: &Path, out_path: &Path) {
let status = Command::new(env!("CARGO_BIN_EXE_lbunzip2"))
.arg(bz2_path)
.arg(out_path)
.status()
.expect("spawn lbunzip2");
assert!(status.success(), "lbunzip2 exited with {status}");
}
fn tmp_dir(tag: &str) -> PathBuf {
let d = std::env::temp_dir().join(format!("lbz-large-{tag}-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&d);
std::fs::create_dir_all(&d).unwrap();
d
}
fn roundtrip(total: usize, tag: &str) {
let dir = tmp_dir(tag);
let bz2 = dir.join("corpus.bz2");
let out = dir.join("out.bin");
let data = corpus(total);
assert_eq!(data.len(), total);
write_bz2(&bz2, &data);
run_lbunzip2(&bz2, &out);
let decoded = std::fs::read(&out).expect("read decoded");
assert_eq!(
decoded.len(),
data.len(),
"decoded length {} != input length {} (truncation?)",
decoded.len(),
data.len()
);
assert!(decoded == data, "decoded bytes differ from the input corpus");
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn multiblock_roundtrip_is_byte_identical() {
roundtrip(24 * 1024 * 1024, "light");
}
#[test]
#[ignore = "heavy: materialises >512 MiB; run with --ignored"]
fn over_512_mib_roundtrip_is_byte_identical() {
let total = 512 * 1024 * 1024 + 16 * 1024 * 1024;
roundtrip(total, "heavy");
}