54 lines
1.8 KiB
Rust
54 lines
1.8 KiB
Rust
|
|
//! Property test: any file round-trips add→materialize bit-identically.
|
||
|
|
|
||
|
|
mod support;
|
||
|
|
|
||
|
|
use proptest::prelude::*;
|
||
|
|
use varde_proto::{MaterializeMode, Request, ResponseData};
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn any_file_round_trips_bit_identically() {
|
||
|
|
let daemon = support::spawn_daemon();
|
||
|
|
let dir = tempfile::tempdir().unwrap();
|
||
|
|
|
||
|
|
let mut runner = proptest::test_runner::TestRunner::new(proptest::test_runner::Config {
|
||
|
|
cases: 32,
|
||
|
|
..Default::default()
|
||
|
|
});
|
||
|
|
|
||
|
|
// Sizes span the store's inline/file boundary (~16 KiB) and chunk
|
||
|
|
// boundaries; contents are arbitrary bytes.
|
||
|
|
let strategy = prop::collection::vec(any::<u8>(), 0..=64 * 1024);
|
||
|
|
|
||
|
|
let result = runner.run(&strategy, |payload| {
|
||
|
|
let mut client = support::Client::connect(&daemon.socket);
|
||
|
|
let src = dir.path().join("in.bin");
|
||
|
|
let dest = dir.path().join("out.bin");
|
||
|
|
std::fs::write(&src, &payload).unwrap();
|
||
|
|
|
||
|
|
let reply = client.request(&Request::Add {
|
||
|
|
path: src.display().to_string(),
|
||
|
|
recursive: false,
|
||
|
|
});
|
||
|
|
prop_assert!(reply.ok, "add failed: {:?}", reply.error);
|
||
|
|
let hash = match reply.data {
|
||
|
|
Some(ResponseData::Added { hash, bytes }) => {
|
||
|
|
prop_assert_eq!(bytes, payload.len() as u64);
|
||
|
|
hash
|
||
|
|
}
|
||
|
|
other => return Err(TestCaseError::fail(format!("bad reply: {other:?}"))),
|
||
|
|
};
|
||
|
|
|
||
|
|
let reply = client.request(&Request::Materialize {
|
||
|
|
hash,
|
||
|
|
dest: dest.display().to_string(),
|
||
|
|
mode: MaterializeMode::ReflinkOrCopy,
|
||
|
|
});
|
||
|
|
prop_assert!(reply.ok, "materialize failed: {:?}", reply.error);
|
||
|
|
|
||
|
|
let round_tripped = std::fs::read(&dest).unwrap();
|
||
|
|
prop_assert_eq!(round_tripped, payload);
|
||
|
|
Ok(())
|
||
|
|
});
|
||
|
|
result.unwrap();
|
||
|
|
}
|