impl integer tester trait and macro. test u32

This commit is contained in:
collin 2020-06-05 14:09:12 -07:00
parent 31d2542d52
commit c5868b430a
13 changed files with 227 additions and 56 deletions

View File

@ -366,7 +366,7 @@ impl Integer {
let result = left_u8.div(
cs.ns(|| {
format!(
"enforce {} / {}",
"enforce {} ÷ {}",
left_u8.value.unwrap(),
right_u8.value.unwrap()
)
@ -379,7 +379,7 @@ impl Integer {
let result = left_u16.div(
cs.ns(|| {
format!(
"enforce {} / {}",
"enforce {} ÷ {}",
left_u16.value.unwrap(),
right_u16.value.unwrap()
)
@ -392,7 +392,7 @@ impl Integer {
let result = left_u32.div(
cs.ns(|| {
format!(
"enforce {} / {}",
"enforce {} ÷ {}",
left_u32.value.unwrap(),
right_u32.value.unwrap()
)
@ -405,7 +405,7 @@ impl Integer {
let result = left_u64.div(
cs.ns(|| {
format!(
"enforce {} / {}",
"enforce {} ÷ {}",
left_u64.value.unwrap(),
right_u64.value.unwrap()
)
@ -418,7 +418,7 @@ impl Integer {
let result = left_u128.div(
cs.ns(|| {
format!(
"enforce {} / {}",
"enforce {} ÷ {}",
left_u128.value.unwrap(),
right_u128.value.unwrap()
)
@ -428,7 +428,7 @@ impl Integer {
Integer::U128(result)
}
(left, right) => {
return Err(IntegerError::CannotEnforce(format!("{} / {}", left, right)))
return Err(IntegerError::CannotEnforce(format!("{} ÷ {}", left, right)))
}
})
}

View File

@ -0,0 +1,146 @@
macro_rules! test_uint {
($name: ident, $_type: ty, $gadget: ty, $directory: expr) => {
pub struct $name {}
impl $name {
fn test_min(min: $_type) {
let min_allocated = <$gadget>::constant(min);
let program = compile_program($directory, "min.leo").unwrap();
output_expected_allocated(program, min_allocated);
}
fn test_max(max: $_type) {
let max_allocated = <$gadget>::constant(max);
let program = compile_program($directory, "max.leo").unwrap();
output_expected_allocated(program, max_allocated);
}
}
impl IntegerTester for $name {
fn test_input() {
// valid input
let num: $_type = rand::random();
let expected = <$gadget>::constant(num);
let mut program = compile_program($directory, "input.leo").unwrap();
program.set_inputs(vec![Some(InputValue::Integer(num as usize))]);
output_expected_allocated(program, expected);
// invalid input
let mut program = compile_program($directory, "input.leo").unwrap();
program.set_inputs(vec![Some(InputValue::Boolean(true))]);
fail_integer(program);
// None input
let mut program = compile_program($directory, "input.leo").unwrap();
program.set_inputs(vec![None]);
fail_synthesis(program);
}
fn test_add() {
for _ in 0..10 {
let r1: $_type = rand::random();
let r2: $_type = rand::random();
let sum = r1.wrapping_add(r2);
let cs = TestConstraintSystem::<Fq>::new();
let sum_allocated = <$gadget>::alloc(cs, || Ok(sum)).unwrap();
let mut program = compile_program($directory, "add.leo").unwrap();
program.set_inputs(vec![
Some(InputValue::Integer(r1 as usize)),
Some(InputValue::Integer(r2 as usize)),
]);
output_expected_allocated(program, sum_allocated);
}
}
fn test_sub() {
for _ in 0..10 {
let r1: $_type = rand::random();
let r2: $_type = rand::random();
let sum = r1.wrapping_sub(r2);
let cs = TestConstraintSystem::<Fq>::new();
let sum_allocated = <$gadget>::alloc(cs, || Ok(sum)).unwrap();
let mut program = compile_program($directory, "sub.leo").unwrap();
program.set_inputs(vec![
Some(InputValue::Integer(r1 as usize)),
Some(InputValue::Integer(r2 as usize)),
]);
output_expected_allocated(program, sum_allocated);
}
}
fn test_mul() {
for _ in 0..10 {
let r1: $_type = rand::random();
let r2: $_type = rand::random();
let sum = r1.wrapping_mul(r2);
let cs = TestConstraintSystem::<Fq>::new();
let sum_allocated = <$gadget>::alloc(cs, || Ok(sum)).unwrap();
let mut program = compile_program($directory, "mul.leo").unwrap();
program.set_inputs(vec![
Some(InputValue::Integer(r1 as usize)),
Some(InputValue::Integer(r2 as usize)),
]);
output_expected_allocated(program, sum_allocated);
}
}
fn test_div() {
for _ in 0..10 {
let r1: $_type = rand::random();
let r2: $_type = rand::random();
let sum = r1.wrapping_div(r2);
let cs = TestConstraintSystem::<Fq>::new();
let sum_allocated = <$gadget>::alloc(cs, || Ok(sum)).unwrap();
let mut program = compile_program($directory, "div.leo").unwrap();
program.set_inputs(vec![
Some(InputValue::Integer(r1 as usize)),
Some(InputValue::Integer(r2 as usize)),
]);
output_expected_allocated(program, sum_allocated);
}
}
fn test_pow() {
for _ in 0..10 {
let r1: $_type = rand::random();
let r2: $_type = rand::random();
let sum = r1.wrapping_pow(r2);
let cs = TestConstraintSystem::<Fq>::new();
let sum_allocated = <$gadget>::alloc(cs, || Ok(sum)).unwrap();
let mut program = compile_program($directory, "pow.leo").unwrap();
program.set_inputs(vec![
Some(InputValue::Integer(r1 as usize)),
Some(InputValue::Integer(r2 as usize)),
]);
output_expected_allocated(program, sum_allocated);
}
}
}
};
}

View File

@ -1 +1,26 @@
#[macro_use]
pub mod macros;
pub use self::macros::*;
pub trait IntegerTester {
/// Tests use of the integer in a function input
fn test_input();
/// Tests a wrapping addition
fn test_add();
/// Tests a wrapping subtraction
fn test_sub();
/// Tests a wrapping multiplication
fn test_mul();
/// Tests a non-wrapping division
fn test_div();
/// Tests a wrapping exponentiation
fn test_pow();
}
// must be below macro definitions!
pub mod u32;

View File

@ -1,4 +0,0 @@
// This program should panic at compilation.
function main() -> u32 {
return 1 - 2
}

View File

@ -0,0 +1,3 @@
function main(a: u32, b: u32) -> u32 {
return a + b
}

View File

@ -0,0 +1,3 @@
function main(a: u32, b: u32) -> u32 {
return a / b
}

View File

@ -1,3 +1,3 @@
function main() -> u32 {
return 1 - 1
}
return 4294967295
}

View File

@ -1,3 +1,3 @@
function main() -> u32 {
return 1 + 1
}
return 0
}

View File

@ -1,14 +1,31 @@
use crate::{compile_program, get_error, get_output, EdwardsConstrainedValue, EdwardsTestCompiler};
use crate::{
compile_program, get_error, get_output, integer::IntegerTester, EdwardsConstrainedValue,
EdwardsTestCompiler,
};
use leo_compiler::{
errors::{CompilerError, FunctionError, IntegerError},
types::Integer,
ConstrainedValue, InputValue,
};
use snarkos_models::gadgets::utilities::uint::UInt32;
use snarkos_curves::edwards_bls12::Fq;
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
use snarkos_models::gadgets::utilities::{alloc::AllocGadget, uint::UInt32};
const DIRECTORY_NAME: &str = "tests/integer/u32/";
fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt32) {
let output = get_output(program);
match output {
EdwardsConstrainedValue::Return(vec) => match vec.as_slice() {
[ConstrainedValue::Integer(Integer::U32(actual))] => assert_eq!(*actual, expected),
_ => panic!("program output unknown return value"),
},
_ => panic!("program output unknown return value"),
}
}
pub(crate) fn output_zero(program: EdwardsTestCompiler) {
let output = get_output(program);
assert_eq!(
@ -31,17 +48,6 @@ pub(crate) fn output_one(program: EdwardsTestCompiler) {
)
}
fn output_two(program: EdwardsTestCompiler) {
let output = get_output(program);
assert_eq!(
EdwardsConstrainedValue::Return(vec![ConstrainedValue::Integer(Integer::U32(
UInt32::constant(2u32)
))])
.to_string(),
output.to_string()
)
}
fn fail_integer(program: EdwardsTestCompiler) {
match get_error(program) {
CompilerError::FunctionError(FunctionError::IntegerError(
@ -61,17 +67,19 @@ fn fail_synthesis(program: EdwardsTestCompiler) {
}
#[test]
fn test_input_u32_bool() {
let mut program = compile_program(DIRECTORY_NAME, "input_u32.leo").unwrap();
program.set_inputs(vec![Some(InputValue::Boolean(true))]);
fail_integer(program);
}
fn test_u32() {
test_uint!(TestU32, u32, UInt32, DIRECTORY_NAME);
#[test]
fn test_input_u32_none() {
let mut program = compile_program(DIRECTORY_NAME, "input_u32.leo").unwrap();
program.set_inputs(vec![None]);
fail_synthesis(program);
TestU32::test_min(std::u32::MIN);
TestU32::test_max(std::u32::MAX);
TestU32::test_input();
TestU32::test_add();
// TestU32::test_sub(); //Todo: Catch subtraction overflow error in gadget
TestU32::test_mul();
TestU32::test_div();
TestU32::test_pow();
}
#[test]
@ -85,22 +93,3 @@ fn test_one() {
let program = compile_program(DIRECTORY_NAME, "one.leo").unwrap();
output_one(program);
}
#[test]
fn test_1_plus_1() {
let program = compile_program(DIRECTORY_NAME, "1+1.leo").unwrap();
output_two(program);
}
#[test]
fn test_1_minus_1() {
let program = compile_program(DIRECTORY_NAME, "1-1.leo").unwrap();
output_zero(program)
}
// #[test] // Todo: Catch subtraction overflow error in gadget
// fn test_1_minus_2() {
// let program = compile_program(DIRECTORY_NAME, "1-2.leo").unwrap();
// let error = get_error(program);
// println!("{}", error);
// }

View File

@ -0,0 +1,3 @@
function main(a: u32, b: u32) -> u32 {
return a * b
}

View File

@ -0,0 +1,3 @@
function main(a: u32, b: u32) -> u32 {
return a ** b
}

View File

@ -0,0 +1,3 @@
function main(a: u32, b: u32) -> u32 {
return a - b
}