From 427e8fcb5d3aaea05a62eff6cb5367b6e12ba05d Mon Sep 17 00:00:00 2001 From: Tom French Date: Thu, 14 Mar 2024 14:25:36 +0000 Subject: [PATCH 1/3] feat: allow usage of noir `#[test]` syntax in stdlib --- noir_stdlib/src/field/bn254.nr | 78 +++++++++++++++++ .../field_comparisons/Nargo.toml | 6 -- .../field_comparisons/Prover.toml | 1 - .../field_comparisons/src/main.nr | 86 ------------------- tooling/nargo_cli/tests/stdlib-tests.rs | 61 +++++++++++++ 5 files changed, 139 insertions(+), 93 deletions(-) delete mode 100644 test_programs/compile_success_empty/field_comparisons/Nargo.toml delete mode 100644 test_programs/compile_success_empty/field_comparisons/Prover.toml delete mode 100644 test_programs/compile_success_empty/field_comparisons/src/main.nr create mode 100644 tooling/nargo_cli/tests/stdlib-tests.rs diff --git a/noir_stdlib/src/field/bn254.nr b/noir_stdlib/src/field/bn254.nr index 9e1445fd3ba..765f8a9d849 100644 --- a/noir_stdlib/src/field/bn254.nr +++ b/noir_stdlib/src/field/bn254.nr @@ -101,3 +101,81 @@ pub fn gt(a: Field, b: Field) -> bool { pub fn lt(a: Field, b: Field) -> bool { gt(b, a) } + +mod tests { + // TODO: Allow imports from "super" + use crate::field::bn254::{decompose_unsafe, decompose, lt_unsafe, assert_gt, gt, lt, TWO_POW_128, lte_unsafe, PLO, PHI}; + + #[test] + fn check_decompose_unsafe() { + assert_eq(decompose_unsafe(TWO_POW_128), (0, 1)); + assert_eq(decompose_unsafe(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); + assert_eq(decompose_unsafe(0x1234567890), (0x1234567890, 0)); + } + + #[test] + fn check_decompose() { + assert_eq(decompose(TWO_POW_128), (0, 1)); + assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); + assert_eq(decompose(0x1234567890), (0x1234567890, 0)); + } + + #[test] + fn check_lt_unsafe() { + assert(lt_unsafe(0, 1, 16)); + assert(lt_unsafe(0, 0x100, 16)); + assert(lt_unsafe(0x100, TWO_POW_128 - 1, 16)); + assert(!lt_unsafe(0, TWO_POW_128, 16)); + } + + #[test] + fn check_lte_unsafe() { + assert(lte_unsafe(0, 1, 16)); + assert(lte_unsafe(0, 0x100, 16)); + assert(lte_unsafe(0x100, TWO_POW_128 - 1, 16)); + assert(!lte_unsafe(0, TWO_POW_128, 16)); + + assert(lte_unsafe(0, 0, 16)); + assert(lte_unsafe(0x100, 0x100, 16)); + assert(lte_unsafe(TWO_POW_128 - 1, TWO_POW_128 - 1, 16)); + assert(lte_unsafe(TWO_POW_128, TWO_POW_128, 16)); + } + + #[test] + fn check_assert_gt() { + assert_gt(1, 0); + assert_gt(0x100, 0); + assert_gt((0 - 1), (0 - 2)); + assert_gt(TWO_POW_128, 0); + assert_gt(0 - 1, 0); + } + + #[test] + fn check_gt() { + assert(gt(1, 0)); + assert(gt(0x100, 0)); + assert(gt((0 - 1), (0 - 2))); + assert(gt(TWO_POW_128, 0)); + assert(!gt(0, 0)); + assert(!gt(0, 0x100)); + assert(gt(0 - 1, 0 - 2)); + assert(!gt(0 - 2, 0 - 1)); + } + + #[test] + fn check_plo_phi() { + assert_eq(PLO + PHI * TWO_POW_128, 0); + let p_bytes = crate::field::modulus_le_bytes(); + let mut p_low: Field = 0; + let mut p_high: Field = 0; + + let mut offset = 1; + for i in 0..16 { + p_low += (p_bytes[i] as Field) * offset; + p_high += (p_bytes[i + 16] as Field) * offset; + offset *= 256; + } + assert_eq(p_low, PLO); + assert_eq(p_high, PHI); + } +} diff --git a/test_programs/compile_success_empty/field_comparisons/Nargo.toml b/test_programs/compile_success_empty/field_comparisons/Nargo.toml deleted file mode 100644 index e8b06655c58..00000000000 --- a/test_programs/compile_success_empty/field_comparisons/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "field_comparisons" -type = "bin" -authors = [""] - -[dependencies] diff --git a/test_programs/compile_success_empty/field_comparisons/Prover.toml b/test_programs/compile_success_empty/field_comparisons/Prover.toml deleted file mode 100644 index 8b137891791..00000000000 --- a/test_programs/compile_success_empty/field_comparisons/Prover.toml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/test_programs/compile_success_empty/field_comparisons/src/main.nr b/test_programs/compile_success_empty/field_comparisons/src/main.nr deleted file mode 100644 index 48cca6c89fc..00000000000 --- a/test_programs/compile_success_empty/field_comparisons/src/main.nr +++ /dev/null @@ -1,86 +0,0 @@ -use dep::std::field::bn254::{PLO, PHI, TWO_POW_128, decompose, decompose_unsafe, lt_unsafe, lte_unsafe, assert_gt, gt}; - -fn check_plo_phi() { - assert_eq(PLO + PHI * TWO_POW_128, 0); - let p_bytes = dep::std::field::modulus_le_bytes(); - let mut p_low: Field = 0; - let mut p_high: Field = 0; - - let mut offset = 1; - for i in 0..16 { - p_low += (p_bytes[i] as Field) * offset; - p_high += (p_bytes[i + 16] as Field) * offset; - offset *= 256; - } - assert_eq(p_low, PLO); - assert_eq(p_high, PHI); -} - -fn check_decompose_unsafe() { - assert_eq(decompose_unsafe(TWO_POW_128), (0, 1)); - assert_eq(decompose_unsafe(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); - assert_eq(decompose_unsafe(0x1234567890), (0x1234567890, 0)); -} - -fn check_decompose() { - assert_eq(decompose(TWO_POW_128), (0, 1)); - assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1)); - assert_eq(decompose(0x1234567890), (0x1234567890, 0)); -} - -fn check_lt_unsafe() { - assert(lt_unsafe(0, 1, 16)); - assert(lt_unsafe(0, 0x100, 16)); - assert(lt_unsafe(0x100, TWO_POW_128 - 1, 16)); - assert(!lt_unsafe(0, TWO_POW_128, 16)); -} - -fn check_lte_unsafe() { - assert(lte_unsafe(0, 1, 16)); - assert(lte_unsafe(0, 0x100, 16)); - assert(lte_unsafe(0x100, TWO_POW_128 - 1, 16)); - assert(!lte_unsafe(0, TWO_POW_128, 16)); - - assert(lte_unsafe(0, 0, 16)); - assert(lte_unsafe(0x100, 0x100, 16)); - assert(lte_unsafe(TWO_POW_128 - 1, TWO_POW_128 - 1, 16)); - assert(lte_unsafe(TWO_POW_128, TWO_POW_128, 16)); -} - -fn check_assert_gt() { - assert_gt(1, 0); - assert_gt(0x100, 0); - assert_gt((0 - 1), (0 - 2)); - assert_gt(TWO_POW_128, 0); - assert_gt(0 - 1, 0); -} - -fn check_gt() { - assert(gt(1, 0)); - assert(gt(0x100, 0)); - assert(gt((0 - 1), (0 - 2))); - assert(gt(TWO_POW_128, 0)); - assert(!gt(0, 0)); - assert(!gt(0, 0x100)); - assert(gt(0 - 1, 0 - 2)); - assert(!gt(0 - 2, 0 - 1)); -} - -fn checks() { - check_plo_phi(); - check_decompose_unsafe(); - check_decompose(); - check_lt_unsafe(); - check_lte_unsafe(); - check_assert_gt(); - check_gt(); -} - -unconstrained fn checks_in_brillig() { - checks(); -} - -fn main() { - checks(); - checks_in_brillig(); -} diff --git a/tooling/nargo_cli/tests/stdlib-tests.rs b/tooling/nargo_cli/tests/stdlib-tests.rs new file mode 100644 index 00000000000..add978bbb3a --- /dev/null +++ b/tooling/nargo_cli/tests/stdlib-tests.rs @@ -0,0 +1,61 @@ +use std::{collections::BTreeMap, path::PathBuf}; + +use acvm::blackbox_solver::StubbedBlackBoxSolver; +use noirc_driver::{check_crate, file_manager_with_stdlib, CompileOptions}; +use noirc_frontend::hir::FunctionNameMatch; + +use nargo::{ + ops::{report_errors, run_test, TestStatus}, + package::{Package, PackageType}, + parse_all, prepare_package, +}; + +#[test] +fn stdlib_noir_tests() { + let mut file_manager = file_manager_with_stdlib(&PathBuf::from(".")); + file_manager.add_file_with_source_canonical_path(&PathBuf::from("main.nr"), "".to_owned()); + let parsed_files = parse_all(&file_manager); + + // We need a dummy package as we cannot compile the stdlib on its own. + let dummy_package = Package { + version: None, + compiler_required_version: None, + root_dir: PathBuf::from("."), + package_type: PackageType::Binary, + entry_path: PathBuf::from("main.nr"), + name: "dummy".parse().unwrap(), + dependencies: BTreeMap::new(), + }; + + let (mut context, dummy_crate_id) = + prepare_package(&file_manager, &parsed_files, &dummy_package); + + let result = check_crate(&mut context, dummy_crate_id, true, false); + report_errors(result, &context.file_manager, true, false).unwrap(); + + // We can now search within the stdlib for any test functions to compile. + + let test_functions = context.get_all_test_functions_in_crate_matching( + context.stdlib_crate_id(), + FunctionNameMatch::Anything, + ); + + let test_report: Vec<(String, TestStatus)> = test_functions + .into_iter() + .map(|(test_name, test_function)| { + let status = run_test( + &StubbedBlackBoxSolver, + &mut context, + &test_function, + false, + None, + &CompileOptions::default(), + ); + + (test_name, status) + }) + .collect(); + + assert!(!test_report.is_empty(), "Could not find any tests within the stdlib"); + assert!(test_report.iter().all(|(_, status)| !status.failed())); +} From 58d88ade70ea1c60a7d125047b4146923f9d5be9 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:43:51 +0000 Subject: [PATCH 2/3] Update tooling/nargo_cli/tests/stdlib-tests.rs --- tooling/nargo_cli/tests/stdlib-tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling/nargo_cli/tests/stdlib-tests.rs b/tooling/nargo_cli/tests/stdlib-tests.rs index add978bbb3a..77548284126 100644 --- a/tooling/nargo_cli/tests/stdlib-tests.rs +++ b/tooling/nargo_cli/tests/stdlib-tests.rs @@ -31,7 +31,7 @@ fn stdlib_noir_tests() { prepare_package(&file_manager, &parsed_files, &dummy_package); let result = check_crate(&mut context, dummy_crate_id, true, false); - report_errors(result, &context.file_manager, true, false).unwrap(); + report_errors(result, &context.file_manager, true, false).expect("Error encountered while compiling standard library"); // We can now search within the stdlib for any test functions to compile. From 8e293ca5201aaa715a5f3a0fb70282c631181c83 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Fri, 15 Mar 2024 14:57:16 +0000 Subject: [PATCH 3/3] chore: formatting --- tooling/nargo_cli/tests/stdlib-tests.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tooling/nargo_cli/tests/stdlib-tests.rs b/tooling/nargo_cli/tests/stdlib-tests.rs index 77548284126..9d377cfaee9 100644 --- a/tooling/nargo_cli/tests/stdlib-tests.rs +++ b/tooling/nargo_cli/tests/stdlib-tests.rs @@ -31,7 +31,8 @@ fn stdlib_noir_tests() { prepare_package(&file_manager, &parsed_files, &dummy_package); let result = check_crate(&mut context, dummy_crate_id, true, false); - report_errors(result, &context.file_manager, true, false).expect("Error encountered while compiling standard library"); + report_errors(result, &context.file_manager, true, false) + .expect("Error encountered while compiling standard library"); // We can now search within the stdlib for any test functions to compile.