Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add quickcheck tests and fix off-by-one bug introduced in #31 #35

Merged
merged 3 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions reed-solomon-novelpoly/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down
4 changes: 2 additions & 2 deletions reed-solomon-novelpoly/src/field/inc_encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ pub fn encode_sub_plain(bytes: &[u8], n: usize, k: usize) -> Result<Vec<Additive
// so we get a buffer of size `N` in `GF` symbols
let mut elm_data = vec![Additive(0); n];

for i in 0..(bytes_len / 2) {
for i in 0..((bytes_len + 1) / 2) {
elm_data[i] = Additive(Elt::from_be_bytes([
bytes.get(2 * i).copied().unwrap_or_default(),
bytes.get(2 * i + 1).copied().unwrap_or_default(),
Expand Down Expand Up @@ -241,7 +241,7 @@ pub fn encode_sub_faster8(bytes: &[u8], n: usize, k: usize) -> Result<Vec<Additi
// so we get a buffer of size `N` in `GF` symbols
let mut elm_data = vec![Additive(0); n];

for i in 0..(bytes_len / 2) {
for i in 0..((bytes_len + 1) / 2) {
elm_data[i] = Additive(Elt::from_be_bytes([
bytes.get(2 * i).map(|x| *x).unwrap_or_default(),
bytes.get(2 * i + 1).map(|x| *x).unwrap_or_default(),
Expand Down
30 changes: 30 additions & 0 deletions reed-solomon-novelpoly/src/novel_poly_basis/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use rand::rngs::SmallRng;
use rand::seq::index::IndexVec;
use rand::thread_rng;
use reed_solomon_tester::*;
use quickcheck::{Arbitrary, Gen, QuickCheck};

/// Generate a random index
fn rand_gf_element() -> Additive {
Expand Down Expand Up @@ -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<u8>);

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<u8> = (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::<WrappedShard>(&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))
}
Loading