e256f73439
iroh-blobs 0.35 fs store under <store_dir>/blobs. Add imports files or whole directory trees (as Collections, deterministic order), Materialize exports them with a real FICLONE reflink attempt and streaming-copy fallback, Gc is an explicit mark-and-sweep rooted at the pins. Pins, trusted peers and hash formats persist in meta.json (atomic writes). Store reads run on a LocalPool because iroh-blobs entry readers are not Send. Integration tests drive the real daemon binary: directory round trip byte-identical, gc keeps pinned/drops unpinned, reflink verified on the repo's own filesystem (XFS), plus a 32-case proptest round trip. Dependencies: iroh-blobs =0.35.0 (the store itself; pinned per spec), iroh-io (AsyncSliceReader traits to read store entries), reflink-copy (FICLONE with copy fallback, per spec), proptest (dev-only, round-trip property test). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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();
|
|
}
|