mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
Merge pull request #43 from AleoHQ/feature/test-syntax-new
Feature/test syntax new
This commit is contained in:
commit
e985027e86
@ -1225,6 +1225,16 @@ pub struct Import<'ast> {
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
// Tests
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::test))]
|
||||
pub struct Test<'ast> {
|
||||
pub function: Function<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
}
|
||||
|
||||
// File
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
@ -1233,6 +1243,7 @@ pub struct File<'ast> {
|
||||
pub imports: Vec<Import<'ast>>,
|
||||
pub circuits: Vec<Circuit<'ast>>,
|
||||
pub functions: Vec<Function<'ast>>,
|
||||
pub tests: Vec<Test<'ast>>,
|
||||
pub eoi: EOI,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use crate::{
|
||||
ast,
|
||||
constraints::{generate_constraints, ConstrainedValue},
|
||||
constraints::{generate_constraints, generate_test_constraints, ConstrainedValue},
|
||||
errors::CompilerError,
|
||||
GroupType, InputValue, Program,
|
||||
};
|
||||
@ -10,7 +10,7 @@ use crate::{
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::r1cs::{ConstraintSynthesizer, ConstraintSystem},
|
||||
gadgets::r1cs::{ConstraintSynthesizer, ConstraintSystem, TestConstraintSystem},
|
||||
};
|
||||
|
||||
use from_pest::FromPest;
|
||||
@ -68,6 +68,13 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
generate_constraints(cs, self.program, self.program_inputs)
|
||||
}
|
||||
|
||||
pub fn compile_test_constraints(
|
||||
self,
|
||||
cs: &mut TestConstraintSystem<F>,
|
||||
) -> Result<(), CompilerError> {
|
||||
generate_test_constraints::<F, G>(cs, self.program)
|
||||
}
|
||||
|
||||
// pub fn compile(&self) -> Result<ast::File, CompilerError> {
|
||||
// // Read in the main file as string
|
||||
// let unparsed_file = fs::read_to_string(&self.main_file_path).map_err(|_| CompilerError::FileReadError(self.main_file_path.clone()))?;
|
||||
|
@ -236,6 +236,10 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
right: ConstrainedValue<F, G>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
let result = num_1.ge(&num_2);
|
||||
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
|
||||
}
|
||||
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
|
||||
let result = fe_1.ge(&fe_2);
|
||||
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
|
||||
@ -261,6 +265,10 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
right: ConstrainedValue<F, G>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
let result = num_1.gt(&num_2);
|
||||
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
|
||||
}
|
||||
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
|
||||
let result = fe_1.gt(&fe_2);
|
||||
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
|
||||
@ -286,6 +294,10 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
right: ConstrainedValue<F, G>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
let result = num_1.le(&num_2);
|
||||
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
|
||||
}
|
||||
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
|
||||
let result = fe_1.le(&fe_2);
|
||||
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
|
||||
@ -311,6 +323,10 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
right: ConstrainedValue<F, G>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
let result = num_1.lt(&num_2);
|
||||
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
|
||||
}
|
||||
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
|
||||
let result = fe_1.lt(&fe_2);
|
||||
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
|
||||
|
@ -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)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ use crate::{
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::r1cs::ConstraintSystem,
|
||||
gadgets::r1cs::{ConstraintSystem, TestConstraintSystem},
|
||||
};
|
||||
|
||||
pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||
@ -66,3 +66,40 @@ pub fn generate_constraints<F: Field + PrimeField, G: GroupType<F>, CS: Constrai
|
||||
_ => Err(CompilerError::NoMainFunction),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_test_constraints<F: Field + PrimeField, G: GroupType<F>>(
|
||||
cs: &mut TestConstraintSystem<F>,
|
||||
program: Program,
|
||||
) -> Result<(), CompilerError> {
|
||||
let mut resolved_program = ConstrainedProgram::<F, G, TestConstraintSystem<F>>::new();
|
||||
let program_name = program.get_name();
|
||||
|
||||
let tests = program.tests.clone();
|
||||
|
||||
resolved_program.resolve_definitions(cs, program)?;
|
||||
|
||||
log::info!("Running {} tests", tests.len());
|
||||
|
||||
for (test_name, test_function) in tests.into_iter() {
|
||||
let full_test_name = format!("{}::{}", program_name.clone(), test_name.to_string());
|
||||
|
||||
let result = resolved_program.enforce_main_function(
|
||||
cs,
|
||||
program_name.clone(),
|
||||
test_function.0,
|
||||
vec![], // test functions should not take any inputs
|
||||
);
|
||||
|
||||
if result.is_ok() {
|
||||
log::info!(
|
||||
"test {} passed. Constraint system satisfied: {}",
|
||||
full_test_name,
|
||||
cs.is_satisfied()
|
||||
);
|
||||
} else {
|
||||
log::error!("test {} errored: {}", full_test_name, result.unwrap_err());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -414,14 +414,16 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
self.enforce_boolean_eq(cs, bool_1, bool_2)?
|
||||
}
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.enforce_equal(cs, &num_2)?
|
||||
}
|
||||
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
|
||||
fe_1.enforce_equal(cs, &fe_2)?
|
||||
}
|
||||
(ConstrainedValue::Group(ge_1), ConstrainedValue::Group(ge_2)) => {
|
||||
ge_1.enforce_equal(cs, &ge_2)?
|
||||
num_1.enforce_equal(cs, &num_2).map_err(|_| {
|
||||
StatementError::AssertionFailed(num_1.to_string(), num_2.to_string())
|
||||
})?
|
||||
}
|
||||
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => fe_1
|
||||
.enforce_equal(cs, &fe_2)
|
||||
.map_err(|_| StatementError::AssertionFailed(fe_1.to_string(), fe_2.to_string()))?,
|
||||
(ConstrainedValue::Group(ge_1), ConstrainedValue::Group(ge_2)) => ge_1
|
||||
.enforce_equal(cs, &ge_2)
|
||||
.map_err(|_| StatementError::AssertionFailed(ge_1.to_string(), ge_2.to_string()))?,
|
||||
(ConstrainedValue::Array(arr_1), ConstrainedValue::Array(arr_2)) => {
|
||||
for (left, right) in arr_1.into_iter().zip(arr_2.into_iter()) {
|
||||
self.enforce_assert_eq_statement(cs, left, right)?;
|
||||
|
@ -34,6 +34,9 @@ pub enum StatementError {
|
||||
#[error("Cannot assert equality between {} == {}", _0, _1)]
|
||||
AssertEq(String, String),
|
||||
|
||||
#[error("Assertion {:?} == {:?} failed", _0, _1)]
|
||||
AssertionFailed(String, String),
|
||||
|
||||
#[error("If, else conditional must resolve to a boolean, got {}", _0)]
|
||||
IfElseConditional(String),
|
||||
|
||||
|
@ -287,3 +287,9 @@ impl<F: Field + PrimeField> ToBytesGadget<F> for FieldType<F> {
|
||||
self_gadget.to_bytes_strict(cs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> std::fmt::Display for FieldType<F> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self.get_value().ok_or(std::fmt::Error))
|
||||
}
|
||||
}
|
||||
|
@ -304,3 +304,12 @@ impl ToBytesGadget<Fq> for EdwardsGroupType {
|
||||
self_gadget.to_bytes_strict(cs)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for EdwardsGroupType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
EdwardsGroupType::Constant(constant) => write!(f, "{:?}", constant),
|
||||
EdwardsGroupType::Allocated(allocated) => write!(f, "{:?}", allocated),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use snarkos_models::{
|
||||
},
|
||||
},
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
pub mod edwards_bls12;
|
||||
|
||||
@ -22,6 +22,7 @@ pub trait GroupType<F: Field>:
|
||||
Sized
|
||||
+ Clone
|
||||
+ Debug
|
||||
+ Display
|
||||
+ EqGadget<F>
|
||||
+ ConditionalEqGadget<F>
|
||||
+ AllocGadget<String, F>
|
||||
|
@ -226,6 +226,10 @@ import_symbol_tuple = _{ import_symbol ~ ("," ~ NEWLINE* ~ import_symbol)* }
|
||||
|
||||
import = { "from" ~ "\"" ~ import_source ~ "\"" ~ "import" ~ ("*" | ("{" ~ NEWLINE* ~ import_symbol_tuple ~ NEWLINE* ~ "}") | import_symbol) ~ LINE_END}
|
||||
|
||||
/// Tests
|
||||
|
||||
test = {"test" ~ function_definition}
|
||||
|
||||
/// Program File
|
||||
|
||||
file = { SOI ~ NEWLINE* ~ import* ~ NEWLINE* ~ circuit_definition* ~ NEWLINE* ~ function_definition* ~ NEWLINE* ~ EOI }
|
||||
file = { SOI ~ NEWLINE* ~ import* ~ NEWLINE* ~ circuit_definition* ~ NEWLINE* ~ function_definition* ~ NEWLINE* ~ test* ~ NEWLINE* ~ EOI }
|
||||
|
@ -34,7 +34,7 @@ pub struct Variable {
|
||||
}
|
||||
|
||||
/// An integer type enum wrapping the integer value. Used only in expressions.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
|
||||
pub enum Integer {
|
||||
U8(UInt8),
|
||||
U16(UInt16),
|
||||
@ -219,7 +219,7 @@ pub struct InputModel {
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum InputValue {
|
||||
Integer(usize),
|
||||
Integer(u128),
|
||||
Field(String),
|
||||
Group(String),
|
||||
Boolean(bool),
|
||||
@ -240,6 +240,11 @@ impl Function {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Test(pub Function);
|
||||
|
||||
/// A simple program with statement expressions, program arguments and program returns.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Program {
|
||||
@ -248,6 +253,7 @@ pub struct Program {
|
||||
pub imports: Vec<Import>,
|
||||
pub circuits: HashMap<Identifier, Circuit>,
|
||||
pub functions: HashMap<Identifier, Function>,
|
||||
pub tests: HashMap<Identifier, Test>,
|
||||
}
|
||||
|
||||
impl<'ast> Program {
|
||||
@ -258,6 +264,7 @@ impl<'ast> Program {
|
||||
imports: vec![],
|
||||
circuits: HashMap::new(),
|
||||
functions: HashMap::new(),
|
||||
tests: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -788,6 +788,13 @@ impl<'ast> From<ast::Import<'ast>> for Import {
|
||||
}
|
||||
}
|
||||
|
||||
/// pest ast -> Test
|
||||
impl<'ast> From<ast::Test<'ast>> for types::Test {
|
||||
fn from(test: ast::Test) -> Self {
|
||||
types::Test(types::Function::from(test.function))
|
||||
}
|
||||
}
|
||||
|
||||
/// pest ast -> types::Program
|
||||
|
||||
impl<'ast> types::Program {
|
||||
@ -801,6 +808,7 @@ impl<'ast> types::Program {
|
||||
|
||||
let mut circuits = HashMap::new();
|
||||
let mut functions = HashMap::new();
|
||||
let mut tests = HashMap::new();
|
||||
let mut num_parameters = 0usize;
|
||||
|
||||
file.circuits.into_iter().for_each(|circuit| {
|
||||
@ -815,6 +823,12 @@ impl<'ast> types::Program {
|
||||
types::Function::from(function_def),
|
||||
);
|
||||
});
|
||||
file.tests.into_iter().for_each(|test_def| {
|
||||
tests.insert(
|
||||
types::Identifier::from(test_def.function.function_name.clone()),
|
||||
types::Test::from(test_def),
|
||||
);
|
||||
});
|
||||
|
||||
if let Some(main_function) = functions.get(&types::Identifier::new("main".into())) {
|
||||
num_parameters = main_function.inputs.len();
|
||||
@ -826,6 +840,7 @@ impl<'ast> types::Program {
|
||||
imports,
|
||||
circuits,
|
||||
functions,
|
||||
tests,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ fn test_input_array() {
|
||||
let mut program = compile_program(DIRECTORY_NAME, "input_array.leo").unwrap();
|
||||
program.set_inputs(vec![Some(InputValue::Array(vec![
|
||||
InputValue::Integer(
|
||||
1usize
|
||||
1u128
|
||||
);
|
||||
3
|
||||
]))]);
|
||||
@ -101,7 +101,7 @@ fn test_input_array() {
|
||||
#[test]
|
||||
fn test_input_array_fail() {
|
||||
let mut program = compile_program(DIRECTORY_NAME, "input_array.leo").unwrap();
|
||||
program.set_inputs(vec![Some(InputValue::Integer(1usize))]);
|
||||
program.set_inputs(vec![Some(InputValue::Integer(1u128))]);
|
||||
fail_array(program);
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ fn test_false() {
|
||||
#[test]
|
||||
fn test_input_bool_field() {
|
||||
let mut program = compile_program(DIRECTORY_NAME, "input_bool.leo").unwrap();
|
||||
program.set_inputs(vec![Some(InputValue::Integer(1usize))]);
|
||||
program.set_inputs(vec![Some(InputValue::Integer(1u128))]);
|
||||
fail_boolean(program);
|
||||
}
|
||||
|
||||
|
348
compiler/tests/integer/macros.rs
Normal file
348
compiler/tests/integer/macros.rs
Normal file
@ -0,0 +1,348 @@
|
||||
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 u128))]);
|
||||
|
||||
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 u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_allocated(program, sum_allocated);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_sub() {
|
||||
for _ in 0..10 {
|
||||
let r1: $_type = rand::random();
|
||||
let r2: $_type = rand::random();
|
||||
|
||||
let difference = r1.wrapping_sub(r2);
|
||||
|
||||
let cs = TestConstraintSystem::<Fq>::new();
|
||||
let difference_allocated = <$gadget>::alloc(cs, || Ok(difference)).unwrap();
|
||||
|
||||
let mut program = compile_program($directory, "sub.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_allocated(program, difference_allocated);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_mul() {
|
||||
for _ in 0..10 {
|
||||
let r1: $_type = rand::random();
|
||||
let r2: $_type = rand::random();
|
||||
|
||||
let product = r1.wrapping_mul(r2);
|
||||
|
||||
let cs = TestConstraintSystem::<Fq>::new();
|
||||
let product_allocated = <$gadget>::alloc(cs, || Ok(product)).unwrap();
|
||||
|
||||
let mut program = compile_program($directory, "mul.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_allocated(program, product_allocated);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_div() {
|
||||
for _ in 0..10 {
|
||||
let r1: $_type = rand::random();
|
||||
let r2: $_type = rand::random();
|
||||
|
||||
let quotient = r1.wrapping_div(r2);
|
||||
|
||||
let cs = TestConstraintSystem::<Fq>::new();
|
||||
let quotient_allocated = <$gadget>::alloc(cs, || Ok(quotient)).unwrap();
|
||||
|
||||
let mut program = compile_program($directory, "div.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_allocated(program, quotient_allocated);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_pow() {
|
||||
// for _ in 0..10 {// these loops take an excessive amount of time
|
||||
let r1: $_type = rand::random();
|
||||
let r2: $_type = rand::random();
|
||||
let r2 = r2 as u32; // we cast to u32 here because of rust pow() requirements
|
||||
|
||||
let result = r1.wrapping_pow(r2);
|
||||
|
||||
let cs = TestConstraintSystem::<Fq>::new();
|
||||
let result_allocated = <$gadget>::alloc(cs, || Ok(result)).unwrap();
|
||||
|
||||
let mut program = compile_program($directory, "pow.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_allocated(program, result_allocated);
|
||||
// }
|
||||
}
|
||||
|
||||
fn test_eq() {
|
||||
for _ in 0..10 {
|
||||
let r1: $_type = rand::random();
|
||||
|
||||
// test equal
|
||||
let mut program = compile_program($directory, "eq.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
]);
|
||||
|
||||
output_true(program);
|
||||
|
||||
// test not equal
|
||||
let r2: $_type = rand::random();
|
||||
|
||||
let result = r1.eq(&r2);
|
||||
|
||||
let mut program = compile_program($directory, "eq.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_boolean(program, result);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_ge() {
|
||||
for _ in 0..10 {
|
||||
let r1: $_type = rand::random();
|
||||
|
||||
// test equal
|
||||
let mut program = compile_program($directory, "ge.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
]);
|
||||
|
||||
output_true(program);
|
||||
|
||||
// test not equal
|
||||
let r2: $_type = rand::random();
|
||||
|
||||
let result = r1.ge(&r2);
|
||||
|
||||
let mut program = compile_program($directory, "ge.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_boolean(program, result);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_gt() {
|
||||
for _ in 0..10 {
|
||||
let r1: $_type = rand::random();
|
||||
|
||||
// test equal
|
||||
let mut program = compile_program($directory, "gt.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
]);
|
||||
|
||||
output_false(program);
|
||||
|
||||
// test not equal
|
||||
let r2: $_type = rand::random();
|
||||
|
||||
let result = r1.gt(&r2);
|
||||
|
||||
let mut program = compile_program($directory, "gt.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_boolean(program, result);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_le() {
|
||||
for _ in 0..10 {
|
||||
let r1: $_type = rand::random();
|
||||
|
||||
// test equal
|
||||
let mut program = compile_program($directory, "le.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
]);
|
||||
|
||||
output_true(program);
|
||||
|
||||
// test not equal
|
||||
let r2: $_type = rand::random();
|
||||
|
||||
let result = r1.le(&r2);
|
||||
|
||||
let mut program = compile_program($directory, "le.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_boolean(program, result);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_lt() {
|
||||
for _ in 0..10 {
|
||||
let r1: $_type = rand::random();
|
||||
|
||||
// test equal
|
||||
let mut program = compile_program($directory, "lt.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
]);
|
||||
|
||||
output_false(program);
|
||||
|
||||
// test not equal
|
||||
let r2: $_type = rand::random();
|
||||
|
||||
let result = r1.lt(&r2);
|
||||
|
||||
let mut program = compile_program($directory, "lt.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_boolean(program, result);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_assert_eq() {
|
||||
for _ in 0..10 {
|
||||
let r1: $_type = rand::random();
|
||||
|
||||
// test equal
|
||||
let mut program = compile_program($directory, "assert_eq.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
]);
|
||||
|
||||
let _ = get_output(program);
|
||||
|
||||
// test not equal
|
||||
let r2: $_type = rand::random();
|
||||
|
||||
if r1 == r2 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut program = compile_program($directory, "assert_eq.leo").unwrap();
|
||||
program.set_inputs(vec![
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
||||
let _ = program.compile_constraints(&mut cs).unwrap();
|
||||
assert!(!cs.is_satisfied());
|
||||
}
|
||||
}
|
||||
|
||||
fn test_ternary() {
|
||||
let r1: $_type = rand::random();
|
||||
let r2: $_type = rand::random();
|
||||
|
||||
let g1 = <$gadget>::constant(r1);
|
||||
let g2 = <$gadget>::constant(r2);
|
||||
|
||||
let mut program_1 = compile_program($directory, "ternary.leo").unwrap();
|
||||
let mut program_2 = program_1.clone();
|
||||
|
||||
// true -> field 1
|
||||
program_1.set_inputs(vec![
|
||||
Some(InputValue::Boolean(true)),
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_allocated(program_1, g1);
|
||||
|
||||
// false -> field 2
|
||||
program_2.set_inputs(vec![
|
||||
Some(InputValue::Boolean(false)),
|
||||
Some(InputValue::Integer(r1 as u128)),
|
||||
Some(InputValue::Integer(r2 as u128)),
|
||||
]);
|
||||
|
||||
output_expected_allocated(program_2, g2);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -1 +1,71 @@
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
|
||||
use crate::{get_error, EdwardsTestCompiler};
|
||||
use leo_compiler::errors::{CompilerError, FunctionError, IntegerError};
|
||||
|
||||
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();
|
||||
|
||||
/// Tests == evaluation
|
||||
fn test_eq();
|
||||
|
||||
/// Tests >= evaluation
|
||||
fn test_ge();
|
||||
|
||||
/// Tests > evaluation
|
||||
fn test_gt();
|
||||
|
||||
/// Tests <= evaluation
|
||||
fn test_le();
|
||||
|
||||
/// Tests < evaluation
|
||||
fn test_lt();
|
||||
|
||||
/// Test assert equals constraint keyword
|
||||
fn test_assert_eq();
|
||||
|
||||
/// Test ternary if bool ? num_1 : num_2;
|
||||
fn test_ternary();
|
||||
}
|
||||
|
||||
pub(crate) fn fail_integer(program: EdwardsTestCompiler) {
|
||||
match get_error(program) {
|
||||
CompilerError::FunctionError(FunctionError::IntegerError(
|
||||
IntegerError::InvalidInteger(_string),
|
||||
)) => {}
|
||||
error => panic!("Expected invalid boolean error, got {}", error),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn fail_synthesis(program: EdwardsTestCompiler) {
|
||||
match get_error(program) {
|
||||
CompilerError::FunctionError(FunctionError::IntegerError(
|
||||
IntegerError::SynthesisError(_string),
|
||||
)) => {}
|
||||
error => panic!("Expected synthesis error, got {}", error),
|
||||
}
|
||||
}
|
||||
|
||||
// must be below macro definitions!
|
||||
pub mod u128;
|
||||
pub mod u16;
|
||||
pub mod u32;
|
||||
pub mod u64;
|
||||
pub mod u8;
|
||||
|
3
compiler/tests/integer/u128/add.leo
Normal file
3
compiler/tests/integer/u128/add.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u128, b: u128) -> u128 {
|
||||
return a + b
|
||||
}
|
3
compiler/tests/integer/u128/assert_eq.leo
Normal file
3
compiler/tests/integer/u128/assert_eq.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u128, b: u128) {
|
||||
assert_eq!(a, b);
|
||||
}
|
3
compiler/tests/integer/u128/div.leo
Normal file
3
compiler/tests/integer/u128/div.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u128, b: u128) -> u128 {
|
||||
return a / b
|
||||
}
|
3
compiler/tests/integer/u128/eq.leo
Normal file
3
compiler/tests/integer/u128/eq.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u128, b: u128) -> bool {
|
||||
return a == b
|
||||
}
|
3
compiler/tests/integer/u128/ge.leo
Normal file
3
compiler/tests/integer/u128/ge.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u128, b: u128) -> bool {
|
||||
return a >= b
|
||||
}
|
3
compiler/tests/integer/u128/gt.leo
Normal file
3
compiler/tests/integer/u128/gt.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u128, b: u128) -> bool {
|
||||
return a > b
|
||||
}
|
3
compiler/tests/integer/u128/input.leo
Normal file
3
compiler/tests/integer/u128/input.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(x: u128) -> u128 {
|
||||
return x
|
||||
}
|
3
compiler/tests/integer/u128/le.leo
Normal file
3
compiler/tests/integer/u128/le.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u128, b: u128) -> bool {
|
||||
return a <= b
|
||||
}
|
3
compiler/tests/integer/u128/lt.leo
Normal file
3
compiler/tests/integer/u128/lt.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u128, b: u128) -> bool {
|
||||
return a < b
|
||||
}
|
3
compiler/tests/integer/u128/max.leo
Normal file
3
compiler/tests/integer/u128/max.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u128 {
|
||||
return 340282366920938463463374607431768211455
|
||||
}
|
3
compiler/tests/integer/u128/min.leo
Normal file
3
compiler/tests/integer/u128/min.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u128 {
|
||||
return 0
|
||||
}
|
50
compiler/tests/integer/u128/mod.rs
Normal file
50
compiler/tests/integer/u128/mod.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use crate::{
|
||||
boolean::{output_expected_boolean, output_false, output_true},
|
||||
compile_program, get_output,
|
||||
integer::{fail_integer, fail_synthesis, IntegerTester},
|
||||
EdwardsConstrainedValue, EdwardsTestCompiler,
|
||||
};
|
||||
use leo_compiler::{types::Integer, ConstrainedValue, InputValue};
|
||||
|
||||
use snarkos_curves::edwards_bls12::Fq;
|
||||
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
|
||||
use snarkos_models::gadgets::utilities::{alloc::AllocGadget, uint::UInt128};
|
||||
|
||||
const DIRECTORY_NAME: &str = "tests/integer/u128/";
|
||||
|
||||
fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt128) {
|
||||
let output = get_output(program);
|
||||
|
||||
match output {
|
||||
EdwardsConstrainedValue::Return(vec) => match vec.as_slice() {
|
||||
[ConstrainedValue::Integer(Integer::U128(actual))] => assert_eq!(*actual, expected),
|
||||
_ => panic!("program output unknown return value"),
|
||||
},
|
||||
_ => panic!("program output unknown return value"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_u128() {
|
||||
test_uint!(TestU128, u128, UInt128, DIRECTORY_NAME);
|
||||
|
||||
TestU128::test_min(std::u128::MIN);
|
||||
TestU128::test_max(std::u128::MAX);
|
||||
|
||||
TestU128::test_input();
|
||||
|
||||
TestU128::test_add();
|
||||
// TestU128::test_sub(); //Todo: Catch subtraction overflow error in gadget
|
||||
TestU128::test_mul();
|
||||
TestU128::test_div();
|
||||
// TestU128::test_pow(); // takes about 10 minutes
|
||||
|
||||
TestU128::test_eq();
|
||||
TestU128::test_ge();
|
||||
TestU128::test_gt();
|
||||
TestU128::test_le();
|
||||
TestU128::test_gt();
|
||||
|
||||
TestU128::test_assert_eq();
|
||||
TestU128::test_ternary();
|
||||
}
|
3
compiler/tests/integer/u128/mul.leo
Normal file
3
compiler/tests/integer/u128/mul.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u128, b: u128) -> u128 {
|
||||
return a * b
|
||||
}
|
3
compiler/tests/integer/u128/one.leo
Normal file
3
compiler/tests/integer/u128/one.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u128 {
|
||||
return 1
|
||||
}
|
3
compiler/tests/integer/u128/pow.leo
Normal file
3
compiler/tests/integer/u128/pow.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u128, b: u128) -> u128 {
|
||||
return a ** b
|
||||
}
|
3
compiler/tests/integer/u128/sub.leo
Normal file
3
compiler/tests/integer/u128/sub.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u128, b: u128) -> u128 {
|
||||
return a - b
|
||||
}
|
3
compiler/tests/integer/u128/ternary.leo
Normal file
3
compiler/tests/integer/u128/ternary.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(b: bool, x: u128, y: u128) -> u128 {
|
||||
return if b ? x : y
|
||||
}
|
3
compiler/tests/integer/u128/zero.leo
Normal file
3
compiler/tests/integer/u128/zero.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u128 {
|
||||
return 0
|
||||
}
|
3
compiler/tests/integer/u16/add.leo
Normal file
3
compiler/tests/integer/u16/add.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u16, b: u16) -> u16 {
|
||||
return a + b
|
||||
}
|
3
compiler/tests/integer/u16/assert_eq.leo
Normal file
3
compiler/tests/integer/u16/assert_eq.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u16, b: u16) {
|
||||
assert_eq!(a, b);
|
||||
}
|
3
compiler/tests/integer/u16/div.leo
Normal file
3
compiler/tests/integer/u16/div.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u16, b: u16) -> u16 {
|
||||
return a / b
|
||||
}
|
3
compiler/tests/integer/u16/eq.leo
Normal file
3
compiler/tests/integer/u16/eq.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u16, b: u16) -> bool {
|
||||
return a == b
|
||||
}
|
3
compiler/tests/integer/u16/ge.leo
Normal file
3
compiler/tests/integer/u16/ge.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u16, b: u16) -> bool {
|
||||
return a >= b
|
||||
}
|
3
compiler/tests/integer/u16/gt.leo
Normal file
3
compiler/tests/integer/u16/gt.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u16, b: u16) -> bool {
|
||||
return a > b
|
||||
}
|
3
compiler/tests/integer/u16/input.leo
Normal file
3
compiler/tests/integer/u16/input.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(x: u16) -> u16 {
|
||||
return x
|
||||
}
|
3
compiler/tests/integer/u16/le.leo
Normal file
3
compiler/tests/integer/u16/le.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u16, b: u16) -> bool {
|
||||
return a <= b
|
||||
}
|
3
compiler/tests/integer/u16/lt.leo
Normal file
3
compiler/tests/integer/u16/lt.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u16, b: u16) -> bool {
|
||||
return a < b
|
||||
}
|
3
compiler/tests/integer/u16/max.leo
Normal file
3
compiler/tests/integer/u16/max.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u16 {
|
||||
return 65535
|
||||
}
|
3
compiler/tests/integer/u16/min.leo
Normal file
3
compiler/tests/integer/u16/min.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u16 {
|
||||
return 0
|
||||
}
|
50
compiler/tests/integer/u16/mod.rs
Normal file
50
compiler/tests/integer/u16/mod.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use crate::{
|
||||
boolean::{output_expected_boolean, output_false, output_true},
|
||||
compile_program, get_output,
|
||||
integer::{fail_integer, fail_synthesis, IntegerTester},
|
||||
EdwardsConstrainedValue, EdwardsTestCompiler,
|
||||
};
|
||||
use leo_compiler::{types::Integer, ConstrainedValue, InputValue};
|
||||
|
||||
use snarkos_curves::edwards_bls12::Fq;
|
||||
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
|
||||
use snarkos_models::gadgets::utilities::{alloc::AllocGadget, uint::UInt16};
|
||||
|
||||
const DIRECTORY_NAME: &str = "tests/integer/u16/";
|
||||
|
||||
fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt16) {
|
||||
let output = get_output(program);
|
||||
|
||||
match output {
|
||||
EdwardsConstrainedValue::Return(vec) => match vec.as_slice() {
|
||||
[ConstrainedValue::Integer(Integer::U16(actual))] => assert_eq!(*actual, expected),
|
||||
_ => panic!("program output unknown return value"),
|
||||
},
|
||||
_ => panic!("program output unknown return value"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_u16() {
|
||||
test_uint!(Testu16, u16, UInt16, DIRECTORY_NAME);
|
||||
|
||||
Testu16::test_min(std::u16::MIN);
|
||||
Testu16::test_max(std::u16::MAX);
|
||||
|
||||
Testu16::test_input();
|
||||
|
||||
Testu16::test_add();
|
||||
// Testu16::test_sub(); //Todo: Catch subtraction overflow error in gadget
|
||||
Testu16::test_mul();
|
||||
Testu16::test_div();
|
||||
Testu16::test_pow();
|
||||
|
||||
Testu16::test_eq();
|
||||
Testu16::test_ge();
|
||||
Testu16::test_gt();
|
||||
Testu16::test_le();
|
||||
Testu16::test_gt();
|
||||
|
||||
Testu16::test_assert_eq();
|
||||
Testu16::test_ternary();
|
||||
}
|
3
compiler/tests/integer/u16/mul.leo
Normal file
3
compiler/tests/integer/u16/mul.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u16, b: u16) -> u16 {
|
||||
return a * b
|
||||
}
|
3
compiler/tests/integer/u16/one.leo
Normal file
3
compiler/tests/integer/u16/one.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u16 {
|
||||
return 1
|
||||
}
|
3
compiler/tests/integer/u16/pow.leo
Normal file
3
compiler/tests/integer/u16/pow.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u16, b: u16) -> u16 {
|
||||
return a ** b
|
||||
}
|
3
compiler/tests/integer/u16/sub.leo
Normal file
3
compiler/tests/integer/u16/sub.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u16, b: u16) -> u16 {
|
||||
return a - b
|
||||
}
|
3
compiler/tests/integer/u16/ternary.leo
Normal file
3
compiler/tests/integer/u16/ternary.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(b: bool, x: u16, y: u16) -> u16 {
|
||||
return if b ? x : y
|
||||
}
|
3
compiler/tests/integer/u16/zero.leo
Normal file
3
compiler/tests/integer/u16/zero.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u16 {
|
||||
return 0
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
// This program should panic at compilation.
|
||||
function main() -> u32 {
|
||||
return 1 - 2
|
||||
}
|
3
compiler/tests/integer/u32/add.leo
Normal file
3
compiler/tests/integer/u32/add.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u32, b: u32) -> u32 {
|
||||
return a + b
|
||||
}
|
3
compiler/tests/integer/u32/assert_eq.leo
Normal file
3
compiler/tests/integer/u32/assert_eq.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u32, b: u32) {
|
||||
assert_eq!(a, b);
|
||||
}
|
3
compiler/tests/integer/u32/div.leo
Normal file
3
compiler/tests/integer/u32/div.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u32, b: u32) -> u32 {
|
||||
return a / b
|
||||
}
|
3
compiler/tests/integer/u32/eq.leo
Normal file
3
compiler/tests/integer/u32/eq.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u32, b: u32) -> bool {
|
||||
return a == b
|
||||
}
|
3
compiler/tests/integer/u32/ge.leo
Normal file
3
compiler/tests/integer/u32/ge.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u32, b: u32) -> bool {
|
||||
return a >= b
|
||||
}
|
3
compiler/tests/integer/u32/gt.leo
Normal file
3
compiler/tests/integer/u32/gt.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u32, b: u32) -> bool {
|
||||
return a > b
|
||||
}
|
3
compiler/tests/integer/u32/le.leo
Normal file
3
compiler/tests/integer/u32/le.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u32, b: u32) -> bool {
|
||||
return a <= b
|
||||
}
|
3
compiler/tests/integer/u32/lt.leo
Normal file
3
compiler/tests/integer/u32/lt.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u32, b: u32) -> bool {
|
||||
return a < b
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
function main() -> u32 {
|
||||
return 1 - 1
|
||||
}
|
||||
return 4294967295
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
function main() -> u32 {
|
||||
return 1 + 1
|
||||
}
|
||||
return 0
|
||||
}
|
@ -1,14 +1,29 @@
|
||||
use crate::{compile_program, get_error, get_output, EdwardsConstrainedValue, EdwardsTestCompiler};
|
||||
use leo_compiler::{
|
||||
errors::{CompilerError, FunctionError, IntegerError},
|
||||
types::Integer,
|
||||
ConstrainedValue, InputValue,
|
||||
use crate::{
|
||||
boolean::{output_expected_boolean, output_false, output_true},
|
||||
compile_program, get_output,
|
||||
integer::{fail_integer, fail_synthesis, IntegerTester},
|
||||
EdwardsConstrainedValue, EdwardsTestCompiler,
|
||||
};
|
||||
use leo_compiler::{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,47 +46,29 @@ 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(
|
||||
IntegerError::InvalidInteger(_string),
|
||||
)) => {}
|
||||
error => panic!("Expected invalid boolean error, got {}", error),
|
||||
}
|
||||
}
|
||||
|
||||
fn fail_synthesis(program: EdwardsTestCompiler) {
|
||||
match get_error(program) {
|
||||
CompilerError::FunctionError(FunctionError::IntegerError(
|
||||
IntegerError::SynthesisError(_string),
|
||||
)) => {}
|
||||
error => panic!("Expected synthesis error, got {}", error),
|
||||
}
|
||||
}
|
||||
|
||||
#[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(); // takes about 2 mins
|
||||
|
||||
TestU32::test_eq();
|
||||
TestU32::test_ge();
|
||||
TestU32::test_gt();
|
||||
TestU32::test_le();
|
||||
TestU32::test_gt();
|
||||
|
||||
TestU32::test_assert_eq();
|
||||
TestU32::test_ternary();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -85,22 +82,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);
|
||||
// }
|
||||
|
3
compiler/tests/integer/u32/mul.leo
Normal file
3
compiler/tests/integer/u32/mul.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u32, b: u32) -> u32 {
|
||||
return a * b
|
||||
}
|
3
compiler/tests/integer/u32/pow.leo
Normal file
3
compiler/tests/integer/u32/pow.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u32, b: u32) -> u32 {
|
||||
return a ** b
|
||||
}
|
3
compiler/tests/integer/u32/sub.leo
Normal file
3
compiler/tests/integer/u32/sub.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u32, b: u32) -> u32 {
|
||||
return a - b
|
||||
}
|
3
compiler/tests/integer/u32/ternary.leo
Normal file
3
compiler/tests/integer/u32/ternary.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(b: bool, x: u32, y: u32) -> u32 {
|
||||
return if b ? x : y
|
||||
}
|
3
compiler/tests/integer/u64/add.leo
Normal file
3
compiler/tests/integer/u64/add.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u64, b: u64) -> u64 {
|
||||
return a + b
|
||||
}
|
3
compiler/tests/integer/u64/assert_eq.leo
Normal file
3
compiler/tests/integer/u64/assert_eq.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u64, b: u64) {
|
||||
assert_eq!(a, b);
|
||||
}
|
3
compiler/tests/integer/u64/div.leo
Normal file
3
compiler/tests/integer/u64/div.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u64, b: u64) -> u64 {
|
||||
return a / b
|
||||
}
|
3
compiler/tests/integer/u64/eq.leo
Normal file
3
compiler/tests/integer/u64/eq.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u64, b: u64) -> bool {
|
||||
return a == b
|
||||
}
|
3
compiler/tests/integer/u64/ge.leo
Normal file
3
compiler/tests/integer/u64/ge.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u64, b: u64) -> bool {
|
||||
return a >= b
|
||||
}
|
3
compiler/tests/integer/u64/gt.leo
Normal file
3
compiler/tests/integer/u64/gt.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u64, b: u64) -> bool {
|
||||
return a > b
|
||||
}
|
3
compiler/tests/integer/u64/input.leo
Normal file
3
compiler/tests/integer/u64/input.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(x: u64) -> u64 {
|
||||
return x
|
||||
}
|
3
compiler/tests/integer/u64/le.leo
Normal file
3
compiler/tests/integer/u64/le.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u64, b: u64) -> bool {
|
||||
return a <= b
|
||||
}
|
3
compiler/tests/integer/u64/lt.leo
Normal file
3
compiler/tests/integer/u64/lt.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u64, b: u64) -> bool {
|
||||
return a < b
|
||||
}
|
3
compiler/tests/integer/u64/max.leo
Normal file
3
compiler/tests/integer/u64/max.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u64 {
|
||||
return 18446744073709551615
|
||||
}
|
3
compiler/tests/integer/u64/min.leo
Normal file
3
compiler/tests/integer/u64/min.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u64 {
|
||||
return 0
|
||||
}
|
50
compiler/tests/integer/u64/mod.rs
Normal file
50
compiler/tests/integer/u64/mod.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use crate::{
|
||||
boolean::{output_expected_boolean, output_false, output_true},
|
||||
compile_program, get_output,
|
||||
integer::{fail_integer, fail_synthesis, IntegerTester},
|
||||
EdwardsConstrainedValue, EdwardsTestCompiler,
|
||||
};
|
||||
use leo_compiler::{types::Integer, ConstrainedValue, InputValue};
|
||||
|
||||
use snarkos_curves::edwards_bls12::Fq;
|
||||
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
|
||||
use snarkos_models::gadgets::utilities::{alloc::AllocGadget, uint::UInt64};
|
||||
|
||||
const DIRECTORY_NAME: &str = "tests/integer/u64/";
|
||||
|
||||
fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt64) {
|
||||
let output = get_output(program);
|
||||
|
||||
match output {
|
||||
EdwardsConstrainedValue::Return(vec) => match vec.as_slice() {
|
||||
[ConstrainedValue::Integer(Integer::U64(actual))] => assert_eq!(*actual, expected),
|
||||
_ => panic!("program output unknown return value"),
|
||||
},
|
||||
_ => panic!("program output unknown return value"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_u64() {
|
||||
test_uint!(Testu64, u64, UInt64, DIRECTORY_NAME);
|
||||
|
||||
Testu64::test_min(std::u64::MIN);
|
||||
Testu64::test_max(std::u64::MAX);
|
||||
|
||||
Testu64::test_input();
|
||||
|
||||
Testu64::test_add();
|
||||
// Testu64::test_sub(); //Todo: Catch subtraction overflow error in gadget
|
||||
Testu64::test_mul();
|
||||
Testu64::test_div();
|
||||
Testu64::test_pow(); // takes ~2mins
|
||||
|
||||
Testu64::test_eq();
|
||||
Testu64::test_ge();
|
||||
Testu64::test_gt();
|
||||
Testu64::test_le();
|
||||
Testu64::test_gt();
|
||||
|
||||
Testu64::test_assert_eq();
|
||||
Testu64::test_ternary();
|
||||
}
|
3
compiler/tests/integer/u64/mul.leo
Normal file
3
compiler/tests/integer/u64/mul.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u64, b: u64) -> u64 {
|
||||
return a * b
|
||||
}
|
3
compiler/tests/integer/u64/one.leo
Normal file
3
compiler/tests/integer/u64/one.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u64 {
|
||||
return 1
|
||||
}
|
3
compiler/tests/integer/u64/pow.leo
Normal file
3
compiler/tests/integer/u64/pow.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u64, b: u64) -> u64 {
|
||||
return a ** b
|
||||
}
|
3
compiler/tests/integer/u64/sub.leo
Normal file
3
compiler/tests/integer/u64/sub.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u64, b: u64) -> u64 {
|
||||
return a - b
|
||||
}
|
3
compiler/tests/integer/u64/ternary.leo
Normal file
3
compiler/tests/integer/u64/ternary.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(b: bool, x: u64, y: u64) -> u64 {
|
||||
return if b ? x : y
|
||||
}
|
3
compiler/tests/integer/u64/zero.leo
Normal file
3
compiler/tests/integer/u64/zero.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u64 {
|
||||
return 0
|
||||
}
|
3
compiler/tests/integer/u8/add.leo
Normal file
3
compiler/tests/integer/u8/add.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u8, b: u8) -> u8 {
|
||||
return a + b
|
||||
}
|
3
compiler/tests/integer/u8/assert_eq.leo
Normal file
3
compiler/tests/integer/u8/assert_eq.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u8, b: u8) {
|
||||
assert_eq!(a, b);
|
||||
}
|
3
compiler/tests/integer/u8/div.leo
Normal file
3
compiler/tests/integer/u8/div.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u8, b: u8) -> u8 {
|
||||
return a / b
|
||||
}
|
3
compiler/tests/integer/u8/eq.leo
Normal file
3
compiler/tests/integer/u8/eq.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u8, b: u8) -> bool {
|
||||
return a == b
|
||||
}
|
3
compiler/tests/integer/u8/ge.leo
Normal file
3
compiler/tests/integer/u8/ge.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u8, b: u8) -> bool {
|
||||
return a >= b
|
||||
}
|
3
compiler/tests/integer/u8/gt.leo
Normal file
3
compiler/tests/integer/u8/gt.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u8, b: u8) -> bool {
|
||||
return a > b
|
||||
}
|
3
compiler/tests/integer/u8/input.leo
Normal file
3
compiler/tests/integer/u8/input.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(x: u8) -> u8 {
|
||||
return x
|
||||
}
|
3
compiler/tests/integer/u8/le.leo
Normal file
3
compiler/tests/integer/u8/le.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u8, b: u8) -> bool {
|
||||
return a <= b
|
||||
}
|
3
compiler/tests/integer/u8/lt.leo
Normal file
3
compiler/tests/integer/u8/lt.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: u8, b: u8) -> bool {
|
||||
return a < b
|
||||
}
|
3
compiler/tests/integer/u8/max.leo
Normal file
3
compiler/tests/integer/u8/max.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u8 {
|
||||
return 255
|
||||
}
|
3
compiler/tests/integer/u8/min.leo
Normal file
3
compiler/tests/integer/u8/min.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() -> u8 {
|
||||
return 0
|
||||
}
|
50
compiler/tests/integer/u8/mod.rs
Normal file
50
compiler/tests/integer/u8/mod.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use crate::{
|
||||
boolean::{output_expected_boolean, output_false, output_true},
|
||||
compile_program, get_output,
|
||||
integer::{fail_integer, fail_synthesis, IntegerTester},
|
||||
EdwardsConstrainedValue, EdwardsTestCompiler,
|
||||
};
|
||||
use leo_compiler::{types::Integer, ConstrainedValue, InputValue};
|
||||
|
||||
use snarkos_curves::edwards_bls12::Fq;
|
||||
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
|
||||
use snarkos_models::gadgets::utilities::{alloc::AllocGadget, uint::UInt8};
|
||||
|
||||
const DIRECTORY_NAME: &str = "tests/integer/u8/";
|
||||
|
||||
fn output_expected_allocated(program: EdwardsTestCompiler, expected: UInt8) {
|
||||
let output = get_output(program);
|
||||
|
||||
match output {
|
||||
EdwardsConstrainedValue::Return(vec) => match vec.as_slice() {
|
||||
[ConstrainedValue::Integer(Integer::U8(actual))] => assert_eq!(*actual, expected),
|
||||
_ => panic!("program output unknown return value"),
|
||||
},
|
||||
_ => panic!("program output unknown return value"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_u8() {
|
||||
test_uint!(Testu8, u8, UInt8, DIRECTORY_NAME);
|
||||
|
||||
Testu8::test_min(std::u8::MIN);
|
||||
Testu8::test_max(std::u8::MAX);
|
||||
|
||||
Testu8::test_input();
|
||||
|
||||
Testu8::test_add();
|
||||
// Testu8::test_sub(); //Todo: Catch subtraction overflow error in gadget
|
||||
Testu8::test_mul();
|
||||
Testu8::test_div();
|
||||
Testu8::test_pow();
|
||||
|
||||
Testu8::test_eq();
|
||||
Testu8::test_ge();
|
||||
Testu8::test_gt();
|
||||
Testu8::test_le();
|
||||
Testu8::test_gt();
|
||||
|
||||
Testu8::test_assert_eq();
|
||||
Testu8::test_ternary();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user