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 property testing for Felt bit shifts #701

Merged
merged 11 commits into from
Jan 12, 2023
24 changes: 24 additions & 0 deletions felt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,16 @@ mod test {

proptest! {
#[test]
// Property-based test that ensures, for 100 felt values that are randomly generated each time tests are run, that a new felt doesn't fall outside the range [0, p].
// In this and some of the following tests, The value of {x} can be either [0] or a very large number, in order to try to overflow the value of {p} and thus ensure the modular arithmetic is working correctly.
fn new_in_range(ref x in "(0|[1-9][0-9]*)") {
let x = &Felt::parse_bytes(x.as_bytes(), 10).unwrap();
let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
prop_assert!(&x.to_biguint() < p);
}

#[test]
// Property-based test that ensures, for 100 {x} and {y} values that are randomly generated each time tests are run, that a multiplication between two felts {x} and {y} and doesn't fall outside the range [0, p]. The values of {x} and {y} can be either [0] or a very large number.
fn mul_in_range(ref x in "(0|[1-9][0-9]*)", ref y in "(0|[1-9][0-9]*)") {
let x = &Felt::parse_bytes(x.as_bytes(), 10).unwrap();
let y = &Felt::parse_bytes(y.as_bytes(), 10).unwrap();
Expand All @@ -177,6 +180,7 @@ mod test {
}

#[test]
// Property-based test that ensures, for 100 {x} and {y} values that are randomly generated each time tests are run, that the result of the division of {x} by {y} is the inverse multiplicative of {x} --that is, multiplying the result by {y} returns the original number {x}. The values of {x} and {y} can be either [0] or a very large number.
fn div_is_mul_inv(ref x in "(0|[1-9][0-9]*)", ref y in "[1-9][0-9]*") {
prop_assume!("0" != y);

Expand All @@ -189,5 +193,25 @@ mod test {
prop_assert!(as_uint < p, "{}", as_uint);
prop_assert_eq!(&(q * y), x);
}

#[test]
// Property-based test that ensures, for 100 {value}s that are randomly generated each time tests are run, that performing a bit shift to the left by {shift_amount} of bits (between 0 and 999) returns a result that is inside of the range [0, p].
fn shift_left_in_range(ref value in "(0|[1-9][0-9]*)", ref shift_amount in "[0-9]{1,3}"){
let value = Felt::parse_bytes(value.as_bytes(), 10).unwrap();
let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
let shift_amount:u32 = shift_amount.parse::<u32>().unwrap();
let result = (value << shift_amount).to_biguint();
prop_assert!(&result < p);
}

#[test]
// Property-based test that ensures, for 100 {value}s that are randomly generated each time tests are run, that performing a bit shift to the right by {shift_amount} of bits (between 0 and 999) returns a result that is inside of the range [0, p].
fn shift_right_in_range(ref value in "(0|[1-9][0-9]*)", ref shift_amount in "[0-9]{1,3}"){
let value = Felt::parse_bytes(value.as_bytes(), 10).unwrap();
let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
let shift_amount:u32 = shift_amount.parse::<u32>().unwrap();
let result = (value >> shift_amount).to_biguint();
prop_assert!(&result < p);
}
}
}