Skip to content

Commit

Permalink
update property testing based on #229
Browse files Browse the repository at this point in the history
  • Loading branch information
johnchandlerburnham committed Feb 1, 2023
2 parents 80e3609 + 65bafd6 commit 49a19f3
Show file tree
Hide file tree
Showing 9 changed files with 587 additions and 519 deletions.
270 changes: 185 additions & 85 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ multihash = { version = "0.16.1", default-features = false, features = ["alloc",
num-bigint = "0.4.3"
num-integer = "0.1.45"
num-traits = "0.2.15"
proptest = "1.0.0"
proptest-derive = "0.3.0"

[features]
default = []
Expand All @@ -53,8 +55,7 @@ gpu = ["neptune/opencl"]
[dev-dependencies]
criterion = "0.3.5"
structopt = { version = "0.3", default-features = false }
quickcheck = "1.0.3"
quickcheck_macros = "1.0.0"
tap = "1.0.1"

[[bench]]
name = "eval"
Expand Down
63 changes: 33 additions & 30 deletions src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,12 +281,15 @@ pub mod tests {
use blstrs::Scalar as Fr;

use super::*;
use quickcheck::{Arbitrary, Gen};
use proptest::prelude::*;

impl<F: LurkField> Arbitrary for FWrap<F> {
fn arbitrary(_: &mut Gen) -> Self {
let f = F::random(rand::thread_rng());
FWrap(f)
type Parameters = ();
type Strategy = BoxedStrategy<Self>;

fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
let strategy = Just(FWrap(F::random(rand::thread_rng())));
strategy.boxed()
}
}

Expand All @@ -295,43 +298,43 @@ pub mod tests {
pub struct VecFWrap<F: LurkField>(pub Vec<F>);

impl<F: LurkField> Arbitrary for VecFWrap<F> {
fn arbitrary(g: &mut Gen) -> Self {
let vec_f: Vec<FWrap<F>> = Arbitrary::arbitrary(g);
VecFWrap(vec_f.into_iter().map(|f| f.0).collect())
type Parameters = ();
type Strategy = BoxedStrategy<Self>;

fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
let strategy = prop::collection::vec(any::<FWrap<F>>(), 0..=10)
.prop_map(|x| VecFWrap(x.iter().map(|x| x.0).collect()));
strategy.boxed()
}
}

#[quickcheck]
fn prop_repr_bytes_consistency(f1: FWrap<Fr>) -> bool {
proptest! {
#[test]
fn prop_repr_bytes_consistency(f1 in any::<FWrap<Fr>>()) {
let bytes = f1.0.to_repr().as_ref().to_owned();
let f2 = <Fr as LurkField>::from_repr_bytes(&bytes);
Some(f1.0) == f2
let f2 = <Fr as LurkField>::from_repr_bytes(&bytes).expect("from_repr_bytes");
assert_eq!(f1.0,f2)
}
}

#[quickcheck]
fn prop_byte_digits_consistency(f1: FWrap<Fr>) -> bool {
proptest! {
#[test]
fn prop_byte_digits_consistency(f1 in any::<FWrap<Fr>>()) {
let bytes = f1.0.to_le_bytes_canonical();
let f2 = Fr::from_le_bytes_canonical(&bytes);
println!("{:?}", bytes);
println!("f1 0x{}", f1.0.hex_digits());
println!("f2 0x{}", f2.hex_digits());
Some(f1.0) == Some(f2)
//println!("{:?}", bytes);
//println!("f1 0x{}", f1.0.hex_digits());
//println!("f2 0x{}", f2.hex_digits());
assert_eq!(f1.0, f2)
}

#[quickcheck]
fn prop_tag_consistency(x: ExprTag) -> bool {
let f1 = Fr::from_expr_tag(x);
let tag = <Fr as LurkField>::to_expr_tag(&f1).unwrap();
let f2 = Fr::from_expr_tag(tag);
f1 == f2 && x == tag
}

#[quickcheck]
fn prop_vec_f_consistency(vec_f: VecFWrap<Fr>) -> bool {
proptest! {
#[test]
fn prop_vec_f_consistency(vec_f in any::<VecFWrap<Fr>>()) {
let bytes = Fr::vec_f_to_bytes(vec_f.0.clone());
match Fr::vec_f_from_bytes(&bytes) {
Some(vec_f2) => vec_f.0 == vec_f2,
None => false,
}
let vec_f2 = Fr::vec_f_from_bytes(&bytes).expect("vec_f_from_bytes");
assert_eq!(vec_f.0, vec_f2)
}
}
}
34 changes: 0 additions & 34 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ extern crate core;
#[macro_use]
extern crate alloc;

#[cfg(test)]
extern crate quickcheck;
#[cfg(test)]
#[macro_use(quickcheck)]
extern crate quickcheck_macros;

pub mod circuit;
pub mod eval;
pub mod field;
Expand All @@ -35,31 +29,3 @@ pub use uint::UInt;
pub const TEST_SEED: [u8; 16] = [
0x62, 0x59, 0x5d, 0xbe, 0x3d, 0x76, 0x3d, 0x8d, 0xdb, 0x17, 0x32, 0x37, 0x06, 0x54, 0xe5, 0xbc,
];

#[cfg(test)]
pub mod test {
use quickcheck::Gen;
use rand::Rng;

// This is a useful testing utility for generating Arbitrary instances of
// enums, by providing generators for each variant, plus a frequency weight
// for how often to choose that variant. It's included in lib::test to make
// it easier to import in the test modules of specific submodules.
pub fn frequency<T, F: Fn(&mut Gen) -> T>(g: &mut Gen, gens: Vec<(i64, F)>) -> T {
if gens.iter().any(|(v, _)| *v < 0) {
panic!("Negative weight");
}
let sum: i64 = gens.iter().map(|x| x.0).sum();
let mut rng = rand::thread_rng();
let mut weight: i64 = rng.gen_range(1..=sum);
// let mut weight: i64 = g.rng.gen_range(1, sum);
for gen in gens {
if weight - gen.0 <= 0 {
return gen.1(g);
} else {
weight -= gen.0;
}
}
panic!("Calculation error for weight = {}", weight);
}
}
43 changes: 18 additions & 25 deletions src/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,40 +262,33 @@ impl<'de, F: LurkField> Deserialize<'de> for Num<F> {
mod tests {
use super::*;

use quickcheck::{Arbitrary, Gen};
use proptest::prelude::*;

use crate::field::FWrap;
use crate::test::frequency;
use blstrs::Scalar;
use blstrs::Scalar as Fr;
use ff::Field;

impl Arbitrary for Num<Fr> {
fn arbitrary(g: &mut Gen) -> Self {
let input: Vec<(i64, Box<dyn Fn(&mut Gen) -> Num<Fr>>)> = vec![
(100, Box::new(|g| Num::U64(Arbitrary::arbitrary(g)))),
(
100,
Box::new(|g| {
let f = FWrap::arbitrary(g);
Num::Scalar(f.0)
}),
),
];
frequency(g, input)
impl<Fr: LurkField> Arbitrary for Num<Fr> {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;

fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
prop_oneof!(
any::<u64>().prop_map(Num::U64),
any::<FWrap<Fr>>().prop_map(|f| Num::Scalar(f.0)),
)
.boxed()
}
}

#[quickcheck]
fn prop_num_ipld(x: Num<Fr>) -> bool {
if let Ok(ipld) = libipld::serde::to_ipld(x) {
if let Ok(y) = libipld::serde::from_ipld(ipld) {
Num::Scalar(x.into_scalar()) == y
} else {
false
}
} else {
false
proptest! {
#[test]
fn prop_num_ipld(x: Num<Fr>) {
let to_ipld = libipld::serde::to_ipld(x).unwrap();
let y = libipld::serde::from_ipld(to_ipld).unwrap();
assert_eq!(
Num::Scalar(x.into_scalar()), y);
}
}

Expand Down
Loading

0 comments on commit 49a19f3

Please sign in to comment.