mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-27 23:47:29 +00:00
79 lines
1.9 KiB
Rust
79 lines
1.9 KiB
Rust
#![no_main]
|
|
|
|
use garage_model::s3::version_table::{Version, VersionBacklink, VersionBlock, VersionBlockKey};
|
|
use garage_table::crdt::Crdt;
|
|
use libfuzzer_sys::fuzz_target;
|
|
|
|
/// Build a Version from an arbitrary deleted flag and block list, using a fixed uuid/backlink
|
|
/// so that CRDT state can be compared across merge results.
|
|
/// Duplicate block keys are dropped before construction.
|
|
/// If deleted, blocks are cleared to ensure a valid initial CRDT state.
|
|
fn make_version(deleted: bool, mut blocks: Vec<(VersionBlockKey, VersionBlock)>) -> Version {
|
|
blocks.sort_by_key(|(k, _)| *k);
|
|
blocks.dedup_by_key(|(k, _)| *k);
|
|
let mut v = Version::new(
|
|
[0u8; 32].into(),
|
|
VersionBacklink::Object {
|
|
bucket_id: [0u8; 32].into(),
|
|
key: String::new(),
|
|
},
|
|
deleted,
|
|
);
|
|
for (key, block) in blocks {
|
|
v.blocks.put(key, block);
|
|
}
|
|
if v.deleted.get() {
|
|
v.blocks.clear();
|
|
}
|
|
v
|
|
}
|
|
|
|
fuzz_target!(|inputs: (
|
|
(bool, Vec<(VersionBlockKey, VersionBlock)>),
|
|
(bool, Vec<(VersionBlockKey, VersionBlock)>),
|
|
(bool, Vec<(VersionBlockKey, VersionBlock)>)
|
|
)| {
|
|
let ((d1, b1), (d2, b2), (d3, b3)) = inputs;
|
|
let a = make_version(d1, b1);
|
|
let b = make_version(d2, b2);
|
|
let c = make_version(d3, b3);
|
|
|
|
// Idempotency: merge(a, a) == a
|
|
{
|
|
let mut a2 = a.clone();
|
|
a2.merge(&a.clone());
|
|
assert_eq!(a2, a, "merge is not idempotent: {a2:#?} != {a:#?}");
|
|
}
|
|
|
|
// Commutativity: merge(a, b) == merge(b, a)
|
|
let ab = {
|
|
let mut t = a.clone();
|
|
t.merge(&b);
|
|
t
|
|
};
|
|
let ba = {
|
|
let mut t = b.clone();
|
|
t.merge(&a);
|
|
t
|
|
};
|
|
assert_eq!(ab, ba, "merge is not commutative: {ab:#?} != {ba:#?}");
|
|
|
|
// Associativity: merge(merge(a, b), c) == merge(a, merge(b, c))
|
|
let ab_c = {
|
|
let mut t = ab.clone();
|
|
t.merge(&c);
|
|
t
|
|
};
|
|
let bc = {
|
|
let mut t = b.clone();
|
|
t.merge(&c);
|
|
t
|
|
};
|
|
let a_bc = {
|
|
let mut t = a.clone();
|
|
t.merge(&bc);
|
|
t
|
|
};
|
|
assert_eq!(ab_c, a_bc, "merge is not associative: {ab_c:#?} != {a_bc:#?}");
|
|
});
|