diff --git a/reed-solomon-novelpoly/Cargo.toml b/reed-solomon-novelpoly/Cargo.toml index f09bf1c..49189be 100644 --- a/reed-solomon-novelpoly/Cargo.toml +++ b/reed-solomon-novelpoly/Cargo.toml @@ -35,6 +35,7 @@ itertools = "0.12" reed-solomon-tester = { path = "../reed-solomon-tester" } rand = { version = "0.8.3", features = ["alloc", "small_rng"] } assert_matches = "1.5.0" +quickcheck = { version = "1.0.3", default-features = false } [features] default = [] diff --git a/reed-solomon-novelpoly/src/field/inc_encode.rs b/reed-solomon-novelpoly/src/field/inc_encode.rs index 6e30bf0..5a0aeb2 100644 --- a/reed-solomon-novelpoly/src/field/inc_encode.rs +++ b/reed-solomon-novelpoly/src/field/inc_encode.rs @@ -190,7 +190,7 @@ pub fn encode_sub_plain(bytes: &[u8], n: usize, k: usize) -> Result Result Additive { @@ -463,3 +464,32 @@ fn shard_len_is_reasonable() { // needs 3 bytes to fit, rounded up to next even number. assert_eq!(rs.shard_len(19), 6); } + +#[derive(Clone, Debug)] +struct ArbitraryData(Vec); + +impl Arbitrary for ArbitraryData { + fn arbitrary(g: &mut Gen) -> Self { + // Limit the len to 1 mib, otherwise the test will take forever + let len = (u32::arbitrary(g) % (1024 * 1024)).max(2); + + let data: Vec = (0..len).map(|_| u8::arbitrary(g)).collect(); + + ArbitraryData(data) + } +} + +#[test] +fn round_trip_quickcheck() { + fn property(available_data: ArbitraryData, n_validators: u16) { + let n_validators = n_validators.max(2); + let wanted_k = (n_validators as usize - 1) / 3 + 1; + let rs = CodeParams::derive_parameters(n_validators as usize, wanted_k).unwrap().make_encoder(); + let chunks = rs.encode::(&available_data.0).unwrap(); + let mut res = rs.reconstruct(chunks.into_iter().take(wanted_k).map(|s| Some(s)).collect()).unwrap(); + res.truncate(available_data.0.len()); + assert_eq!(res, available_data.0); + } + + QuickCheck::new().quickcheck(property as fn(ArbitraryData, u16)) +}