diff --git a/README.md b/README.md index c6ef5c7..19229ef 100644 --- a/README.md +++ b/README.md @@ -6,16 +6,13 @@ This repository contains the standard library for [SimplicityHL](https://github. > If you are using the VS Code syntax highlighting extension, you may see errors because the extension does not support modules and imports yet. ## Dev Info + ### Installation > Project currently uses Simplex version 0.0.6 from the dev branch. To compile the project, execute the following command: -```bash -cargo build -``` - To download simplexup, run: ```bash @@ -62,6 +59,12 @@ To run a specific test: simplex test test_name ``` +To run a specific test module: + +```bash +simplex test u8_test +``` + ### Linting To format the rust files, execute the following command: diff --git a/simf/asserts_mock.simf b/simf/asserts_mock.simf deleted file mode 100644 index 32daeb6..0000000 --- a/simf/asserts_mock.simf +++ /dev/null @@ -1,102 +0,0 @@ -use crate::lib::asserts::{assert_eq_8, assert_eq_16, assert_eq_32, assert_eq_64, assert_eq_256, assert_none_8, assert_none_16, assert_none_32, assert_none_64,assert_none_128, assert_none_256}; - -use crate::helper::if_test_this_function; - -fn main() { - let function_index: u8 = witness::FUNCTION_INDEX; - - let first_arg_u8: Option = witness::FIRST_ARG_U8; - let second_arg_u8: Option = witness::SECOND_ARG_U8; - - let first_arg_u16: Option = witness::FIRST_ARG_U16; - let second_arg_u16: Option = witness::SECOND_ARG_U16; - - let first_arg_u32: Option = witness::FIRST_ARG_U32; - let second_arg_u32: Option = witness::SECOND_ARG_U32; - - let first_arg_u64: Option = witness::FIRST_ARG_U64; - let second_arg_u64: Option = witness::SECOND_ARG_U64; - - let first_arg_u128: Option = witness::FIRST_ARG_U128; - let second_arg_u128: Option = witness::SECOND_ARG_U128; - - let first_arg_u256: Option = witness::FIRST_ARG_U256; - let second_arg_u256: Option = witness::SECOND_ARG_U256; - - match if_test_this_function(0, function_index) { - true => { - assert_eq_8(unwrap(first_arg_u8), unwrap(second_arg_u8)); - }, - false => (), - }; - - match if_test_this_function(1, function_index) { - true => { - assert_eq_16(unwrap(first_arg_u16), unwrap(second_arg_u16)); - }, - false => (), - }; - - match if_test_this_function(2, function_index) { - true => { - assert_eq_32(unwrap(first_arg_u32), unwrap(second_arg_u32)); - }, - false => (), - }; - - match if_test_this_function(3, function_index) { - true => { - assert_eq_64(unwrap(first_arg_u64), unwrap(second_arg_u64)); - }, - false => (), - }; - - match if_test_this_function(4, function_index) { - true => { - assert_eq_256(unwrap(first_arg_u256), unwrap(second_arg_u256)); - }, - false => (), - }; - - match if_test_this_function(5, function_index) { - true => { - assert_none_8(first_arg_u8); - }, - false => (), - }; - - match if_test_this_function(6, function_index) { - true => { - assert_none_16(first_arg_u16); - }, - false => (), - }; - - match if_test_this_function(7, function_index) { - true => { - assert_none_32(first_arg_u32); - }, - false => (), - }; - - match if_test_this_function(8, function_index) { - true => { - assert_none_64(first_arg_u64); - }, - false => (), - }; - - match if_test_this_function(9, function_index) { - true => { - assert_none_128(first_arg_u128); - }, - false => (), - }; - - match if_test_this_function(10, function_index) { - true => { - assert_none_256(first_arg_u256); - }, - false => (), - }; -} diff --git a/simf/asserts_test.simf b/simf/asserts_test.simf new file mode 100644 index 0000000..bfda99e --- /dev/null +++ b/simf/asserts_test.simf @@ -0,0 +1,40 @@ +use crate::lib::asserts::{assert_eq_8, assert_eq_16, assert_eq_32, assert_eq_64, assert_eq_256, assert_none_8, assert_none_16, assert_none_32, assert_none_64,assert_none_128, assert_none_256}; + +use crate::helper::if_test_this_function; + +fn main() { + let fn_idx: u8 = witness::FUNCTION_INDEX; + + let a_u8: Option = witness::FIRST_ARG_U8; + let b_u8: Option = witness::SECOND_ARG_U8; + + let a_u16: Option = witness::FIRST_ARG_U16; + let b_u16: Option = witness::SECOND_ARG_U16; + + let a_u32: Option = witness::FIRST_ARG_U32; + let b_u32: Option = witness::SECOND_ARG_U32; + + let a_u64: Option = witness::FIRST_ARG_U64; + let b_u64: Option = witness::SECOND_ARG_U64; + + let a_u128: Option = witness::FIRST_ARG_U128; + let b_u128: Option = witness::SECOND_ARG_U128; + + let a_u256: Option = witness::FIRST_ARG_U256; + let b_u256: Option = witness::SECOND_ARG_U256; + + // Assert Eq + match if_test_this_function(0, fn_idx) { true => { assert_eq_8(unwrap(a_u8), unwrap(b_u8)); }, false => (), }; + match if_test_this_function(1, fn_idx) { true => { assert_eq_16(unwrap(a_u16), unwrap(b_u16)); }, false => (), }; + match if_test_this_function(2, fn_idx) { true => { assert_eq_32(unwrap(a_u32), unwrap(b_u32)); }, false => (), }; + match if_test_this_function(3, fn_idx) { true => { assert_eq_64(unwrap(a_u64), unwrap(b_u64)); }, false => (), }; + match if_test_this_function(4, fn_idx) { true => { assert_eq_256(unwrap(a_u256), unwrap(b_u256)); }, false => (), }; + + // Assert None + match if_test_this_function(5, fn_idx) { true => { assert_none_8(a_u8); }, false => (), }; + match if_test_this_function(6, fn_idx) { true => { assert_none_16(a_u16); }, false => (), }; + match if_test_this_function(7, fn_idx) { true => { assert_none_32(a_u32); }, false => (), }; + match if_test_this_function(8, fn_idx) { true => { assert_none_64(a_u64); }, false => (), }; + match if_test_this_function(9, fn_idx) { true => { assert_none_128(a_u128); }, false => (), }; + match if_test_this_function(10, fn_idx) { true => { assert_none_256(a_u256); }, false => (), }; +} diff --git a/simf/logical_operations_mock.simf b/simf/logical_ops_test.simf similarity index 92% rename from simf/logical_operations_mock.simf rename to simf/logical_ops_test.simf index e428ec6..45e48e4 100644 --- a/simf/logical_operations_mock.simf +++ b/simf/logical_ops_test.simf @@ -2,7 +2,7 @@ use crate::lib::logical_operations::{not, or, and}; fn main() { assert!(not(false)); - assert!(not((not(true)))); + assert!(not(not(true))); assert!(or(true, false)); assert!(or(false, true)); diff --git a/simf/u16_mock.simf b/simf/u16_mock.simf deleted file mode 100644 index ffe58c0..0000000 --- a/simf/u16_mock.simf +++ /dev/null @@ -1,140 +0,0 @@ -use crate::lib::u16::{checked_add_16, safe_add_16, checked_sub_16, safe_sub_16, checked_mul_16, safe_mul_16, checked_div_16, safe_div_16}; - -use crate::helper::if_test_this_function; - -fn main() { - let function_index: u8 = witness::FUNCTION_INDEX; - let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; - - let first_arg: u16 = witness::FIRST_ARG; - let second_arg: u16 = witness::SECOND_ARG; - let result: u16 = witness::RESULT; - - // add - match if_test_this_function(0, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: Option = checked_add_16(first_arg, second_arg); - assert!(is_none::(overflowing_u16)); - }, - false => { - let fitting_u16: Option = checked_add_16(first_arg, second_arg); - assert!(jet::eq_16(unwrap(fitting_u16), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(1, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: u16 = safe_add_16(first_arg, second_arg); - }, - false => { - let fitting_u16: u16 = safe_add_16(first_arg, second_arg); - assert!(jet::eq_16(fitting_u16, result)); - } - } - }, - false => (), - }; - - // subtract - match if_test_this_function(2, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: Option = checked_sub_16(first_arg, second_arg); - assert!(is_none::(overflowing_u16)); - }, - false => { - let fitting_u16: Option = checked_sub_16(first_arg, second_arg); - assert!(jet::eq_16(unwrap(fitting_u16), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(3, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: u16 = safe_sub_16(first_arg, second_arg); - }, - false => { - let fitting_u16: u16 = safe_sub_16(first_arg, second_arg); - assert!(jet::eq_16(fitting_u16, result)); - } - } - }, - false => (), - }; - - // multiply - match if_test_this_function(4, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: Option = checked_mul_16(first_arg, second_arg); - assert!(is_none::(overflowing_u16)); - }, - false => { - let fitting_u16: Option = checked_mul_16(first_arg, second_arg); - assert!(jet::eq_16(unwrap(fitting_u16), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(5, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: u16 = safe_mul_16(first_arg, second_arg); - }, - false => { - let fitting_u16: u16 = safe_mul_16(first_arg, second_arg); - assert!(jet::eq_16(fitting_u16, result)); - } - } - }, - false => (), - }; - - // divide - match if_test_this_function(6, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: Option = checked_div_16(first_arg, second_arg); - assert!(is_none::(overflowing_u16)); - }, - false => { - let fitting_u16: Option = checked_div_16(first_arg, second_arg); - assert!(jet::eq_16(unwrap(fitting_u16), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(7, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u16: u16 = safe_div_16(first_arg, second_arg); - }, - false => { - let fitting_u16: u16 = safe_div_16(first_arg, second_arg); - assert!(jet::eq_16(fitting_u16, result)); - } - } - }, - false => (), - }; -} diff --git a/simf/u16_test.simf b/simf/u16_test.simf new file mode 100644 index 0000000..d603ec2 --- /dev/null +++ b/simf/u16_test.simf @@ -0,0 +1,37 @@ +use crate::lib::u16::{checked_add_16, safe_add_16, checked_sub_16, safe_sub_16, checked_mul_16, safe_mul_16, checked_div_16, safe_div_16}; + +use crate::helper::if_test_this_function; + +// Asserts a `checked_*` result equals the expected Option. +// `None` encodes the overflow case, `Some(e)` the fitting case, so a single +// witness value carries both, removing the need for a separate overflow flag. +fn assert_eq_opt(result: Option, expected: Option) { + match expected { + None => assert!(is_none::(result)), + Some(e: u16) => assert!(jet::eq_16(unwrap(result), e)), + } +} + +fn main() { + let fn_idx: u8 = witness::FUNCTION_INDEX; + + let a: u16 = witness::FIRST_ARG; + let b: u16 = witness::SECOND_ARG; + let expected: Option = witness::EXPECTED; + + // add + match if_test_this_function(0, fn_idx) { true => { assert_eq_opt(checked_add_16(a, b), expected); }, false => (), }; + match if_test_this_function(1, fn_idx) { true => { assert!(jet::eq_16(safe_add_16(a, b), unwrap(expected))); }, false => (), }; + + // sub + match if_test_this_function(2, fn_idx) { true => { assert_eq_opt(checked_sub_16(a, b), expected); }, false => (), }; + match if_test_this_function(3, fn_idx) { true => { assert!(jet::eq_16(safe_sub_16(a, b), unwrap(expected))); }, false => (), }; + + // mul + match if_test_this_function(4, fn_idx) { true => { assert_eq_opt(checked_mul_16(a, b), expected); }, false => (), }; + match if_test_this_function(5, fn_idx) { true => { assert!(jet::eq_16(safe_mul_16(a, b), unwrap(expected))); }, false => (), }; + + // div + match if_test_this_function(6, fn_idx) { true => { assert_eq_opt(checked_div_16(a, b), expected); }, false => (), }; + match if_test_this_function(7, fn_idx) { true => { assert!(jet::eq_16(safe_div_16(a, b), unwrap(expected))); }, false => (), }; +} diff --git a/simf/u32_mock.simf b/simf/u32_mock.simf deleted file mode 100644 index a1ae4b4..0000000 --- a/simf/u32_mock.simf +++ /dev/null @@ -1,140 +0,0 @@ -use crate::lib::u32::{checked_add_32, safe_add_32, checked_sub_32, safe_sub_32, checked_mul_32, safe_mul_32, checked_div_32, safe_div_32}; - -use crate::helper::if_test_this_function; - -fn main() { - let function_index: u8 = witness::FUNCTION_INDEX; - let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; - - let first_arg: u32 = witness::FIRST_ARG; - let second_arg: u32 = witness::SECOND_ARG; - let result: u32 = witness::RESULT; - - // add - match if_test_this_function(0, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: Option = checked_add_32(first_arg, second_arg); - assert!(is_none::(overflowing_u32)); - }, - false => { - let fitting_u32: Option = checked_add_32(first_arg, second_arg); - assert!(jet::eq_32(unwrap(fitting_u32), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(1, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: u32 = safe_add_32(first_arg, second_arg); - }, - false => { - let fitting_u32: u32 = safe_add_32(first_arg, second_arg); - assert!(jet::eq_32(fitting_u32, result)); - } - } - }, - false => (), - }; - - // subtract - match if_test_this_function(2, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: Option = checked_sub_32(first_arg, second_arg); - assert!(is_none::(overflowing_u32)); - }, - false => { - let fitting_u32: Option = checked_sub_32(first_arg, second_arg); - assert!(jet::eq_32(unwrap(fitting_u32), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(3, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: u32 = safe_sub_32(first_arg, second_arg); - }, - false => { - let fitting_u32: u32 = safe_sub_32(first_arg, second_arg); - assert!(jet::eq_32(fitting_u32, result)); - } - } - }, - false => (), - }; - - // multiply - match if_test_this_function(4, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: Option = checked_mul_32(first_arg, second_arg); - assert!(is_none::(overflowing_u32)); - }, - false => { - let fitting_u32: Option = checked_mul_32(first_arg, second_arg); - assert!(jet::eq_32(unwrap(fitting_u32), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(5, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: u32 = safe_mul_32(first_arg, second_arg); - }, - false => { - let fitting_u32: u32 = safe_mul_32(first_arg, second_arg); - assert!(jet::eq_32(fitting_u32, result)); - } - } - }, - false => (), - }; - - // divide - match if_test_this_function(6, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: Option = checked_div_32(first_arg, second_arg); - assert!(is_none::(overflowing_u32)); - }, - false => { - let fitting_u32: Option = checked_div_32(first_arg, second_arg); - assert!(jet::eq_32(unwrap(fitting_u32), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(7, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u32: u32 = safe_div_32(first_arg, second_arg); - }, - false => { - let fitting_u32: u32 = safe_div_32(first_arg, second_arg); - assert!(jet::eq_32(fitting_u32, result)); - } - } - }, - false => (), - }; -} diff --git a/simf/u32_test.simf b/simf/u32_test.simf new file mode 100644 index 0000000..f5654cc --- /dev/null +++ b/simf/u32_test.simf @@ -0,0 +1,34 @@ +use crate::lib::u32::{checked_add_32, safe_add_32, checked_sub_32, safe_sub_32, checked_mul_32, safe_mul_32, checked_div_32, safe_div_32}; + +use crate::helper::if_test_this_function; + +fn assert_eq_opt(result: Option, expected: Option) { + match expected { + None => assert!(is_none::(result)), + Some(e: u32) => assert!(jet::eq_32(unwrap(result), e)), + } +} + +fn main() { + let fn_idx: u8 = witness::FUNCTION_INDEX; + + let a: u32 = witness::FIRST_ARG; + let b: u32 = witness::SECOND_ARG; + let expected: Option = witness::EXPECTED; + + // add + match if_test_this_function(0, fn_idx) { true => { assert_eq_opt(checked_add_32(a, b), expected); }, false => (), }; + match if_test_this_function(1, fn_idx) { true => { assert!(jet::eq_32(safe_add_32(a, b), unwrap(expected))); }, false => (), }; + + // sub + match if_test_this_function(2, fn_idx) { true => { assert_eq_opt(checked_sub_32(a, b), expected); }, false => (), }; + match if_test_this_function(3, fn_idx) { true => { assert!(jet::eq_32(safe_sub_32(a, b), unwrap(expected))); }, false => (), }; + + // mul + match if_test_this_function(4, fn_idx) { true => { assert_eq_opt(checked_mul_32(a, b), expected); }, false => (), }; + match if_test_this_function(5, fn_idx) { true => { assert!(jet::eq_32(safe_mul_32(a, b), unwrap(expected))); }, false => (), }; + + // div + match if_test_this_function(6, fn_idx) { true => { assert_eq_opt(checked_div_32(a, b), expected); }, false => (), }; + match if_test_this_function(7, fn_idx) { true => { assert!(jet::eq_32(safe_div_32(a, b), unwrap(expected))); }, false => (), }; +} diff --git a/simf/u64_mock.simf b/simf/u64_mock.simf deleted file mode 100644 index 5f20922..0000000 --- a/simf/u64_mock.simf +++ /dev/null @@ -1,140 +0,0 @@ -use crate::lib::u64::{checked_add_64, safe_add_64, checked_sub_64, safe_sub_64, checked_mul_64, safe_mul_64, checked_div_64, safe_div_64}; - -use crate::helper::if_test_this_function; - -fn main() { - let function_index: u8 = witness::FUNCTION_INDEX; - let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; - - let first_arg: u64 = witness::FIRST_ARG; - let second_arg: u64 = witness::SECOND_ARG; - let result: u64 = witness::RESULT; - - // add - match if_test_this_function(0, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: Option = checked_add_64(first_arg, second_arg); - assert!(is_none::(overflowing_u64)); - }, - false => { - let fitting_u64: Option = checked_add_64(first_arg, second_arg); - assert!(jet::eq_64(unwrap(fitting_u64), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(1, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: u64 = safe_add_64(first_arg, second_arg); - }, - false => { - let fitting_u64: u64 = safe_add_64(first_arg, second_arg); - assert!(jet::eq_64(fitting_u64, result)); - } - } - }, - false => (), - }; - - // subtract - match if_test_this_function(2, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: Option = checked_sub_64(first_arg, second_arg); - assert!(is_none::(overflowing_u64)); - }, - false => { - let fitting_u64: Option = checked_sub_64(first_arg, second_arg); - assert!(jet::eq_64(unwrap(fitting_u64), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(3, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: u64 = safe_sub_64(first_arg, second_arg); - }, - false => { - let fitting_u64: u64 = safe_sub_64(first_arg, second_arg); - assert!(jet::eq_64(fitting_u64, result)); - } - } - }, - false => (), - }; - - // multiply - match if_test_this_function(4, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: Option = checked_mul_64(first_arg, second_arg); - assert!(is_none::(overflowing_u64)); - }, - false => { - let fitting_u64: Option = checked_mul_64(first_arg, second_arg); - assert!(jet::eq_64(unwrap(fitting_u64), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(5, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: u64 = safe_mul_64(first_arg, second_arg); - }, - false => { - let fitting_u64: u64 = safe_mul_64(first_arg, second_arg); - assert!(jet::eq_64(fitting_u64, result)); - } - } - }, - false => (), - }; - - // divide - match if_test_this_function(6, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: Option = checked_div_64(first_arg, second_arg); - assert!(is_none::(overflowing_u64)); - }, - false => { - let fitting_u64: Option = checked_div_64(first_arg, second_arg); - assert!(jet::eq_64(unwrap(fitting_u64), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(7, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u64: u64 = safe_div_64(first_arg, second_arg); - }, - false => { - let fitting_u64: u64 = safe_div_64(first_arg, second_arg); - assert!(jet::eq_64(fitting_u64, result)); - } - } - }, - false => (), - }; -} diff --git a/simf/u64_test.simf b/simf/u64_test.simf new file mode 100644 index 0000000..8d01e15 --- /dev/null +++ b/simf/u64_test.simf @@ -0,0 +1,34 @@ +use crate::lib::u64::{checked_add_64, safe_add_64, checked_sub_64, safe_sub_64, checked_mul_64, safe_mul_64, checked_div_64, safe_div_64}; + +use crate::helper::if_test_this_function; + +fn assert_eq_opt(result: Option, expected: Option) { + match expected { + None => assert!(is_none::(result)), + Some(e: u64) => assert!(jet::eq_64(unwrap(result), e)), + } +} + +fn main() { + let fn_idx: u8 = witness::FUNCTION_INDEX; + + let a: u64 = witness::FIRST_ARG; + let b: u64 = witness::SECOND_ARG; + let expected: Option = witness::EXPECTED; + + match if_test_this_function(0, fn_idx) { true => { assert_eq_opt(checked_add_64(a, b), expected); }, false => (), }; + match if_test_this_function(1, fn_idx) { true => { assert!(jet::eq_64(safe_add_64(a, b), unwrap(expected))); }, false => (), }; + + // sub + match if_test_this_function(2, fn_idx) { true => { assert_eq_opt(checked_sub_64(a, b), expected); }, false => (), }; + match if_test_this_function(3, fn_idx) { true => { assert!(jet::eq_64(safe_sub_64(a, b), unwrap(expected))); }, false => (), }; + + // mul + match if_test_this_function(4, fn_idx) { true => { assert_eq_opt(checked_mul_64(a, b), expected); }, false => (), }; + match if_test_this_function(5, fn_idx) { true => { assert!(jet::eq_64(safe_mul_64(a, b), unwrap(expected))); }, false => (), }; + + // div + match if_test_this_function(6, fn_idx) { true => { assert_eq_opt(checked_div_64(a, b), expected); }, false => (), }; + match if_test_this_function(7, fn_idx) { true => { assert!(jet::eq_64(safe_div_64(a, b), unwrap(expected))); }, false => (), }; + +} diff --git a/simf/u8_mock.simf b/simf/u8_mock.simf deleted file mode 100644 index d45fcd3..0000000 --- a/simf/u8_mock.simf +++ /dev/null @@ -1,140 +0,0 @@ -use crate::lib::u8::{checked_add_8, safe_add_8, checked_sub_8, safe_sub_8, checked_mul_8, safe_mul_8, checked_div_8, safe_div_8}; - -use crate::helper::if_test_this_function; - -fn main() { - let function_index: u8 = witness::FUNCTION_INDEX; - let if_test_overflow: bool = witness::IF_TEST_OVERFLOW; - - let first_arg: u8 = witness::FIRST_ARG; - let second_arg: u8 = witness::SECOND_ARG; - let result: u8 = witness::RESULT; - - // add - match if_test_this_function(0, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: Option = checked_add_8(first_arg, second_arg); - assert!(is_none::(overflowing_u8)); - }, - false => { - let fitting_u8: Option = checked_add_8(first_arg, second_arg); - assert!(jet::eq_8(unwrap(fitting_u8), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(1, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: u8 = safe_add_8(first_arg, second_arg); - }, - false => { - let fitting_u8: u8 = safe_add_8(first_arg, second_arg); - assert!(jet::eq_8(fitting_u8, result)); - } - } - }, - false => (), - }; - - // subtract - match if_test_this_function(2, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: Option = checked_sub_8(first_arg, second_arg); - assert!(is_none::(overflowing_u8)); - }, - false => { - let fitting_u8: Option = checked_sub_8(first_arg, second_arg); - assert!(jet::eq_8(unwrap(fitting_u8), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(3, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: u8 = safe_sub_8(first_arg, second_arg); - }, - false => { - let fitting_u8: u8 = safe_sub_8(first_arg, second_arg); - assert!(jet::eq_8(fitting_u8, result)); - } - } - }, - false => (), - }; - - // multiply - match if_test_this_function(4, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: Option = checked_mul_8(first_arg, second_arg); - assert!(is_none::(overflowing_u8)); - }, - false => { - let fitting_u8: Option = checked_mul_8(first_arg, second_arg); - assert!(jet::eq_8(unwrap(fitting_u8), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(5, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: u8 = safe_mul_8(first_arg, second_arg); - }, - false => { - let fitting_u8: u8 = safe_mul_8(first_arg, second_arg); - assert!(jet::eq_8(fitting_u8, result)); - } - } - }, - false => (), - }; - - // divide - match if_test_this_function(6, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: Option = checked_div_8(first_arg, second_arg); - assert!(is_none::(overflowing_u8)); - }, - false => { - let fitting_u8: Option = checked_div_8(first_arg, second_arg); - assert!(jet::eq_8(unwrap(fitting_u8), result)); - } - } - }, - false => (), - }; - - match if_test_this_function(7, function_index) { - true => { - match if_test_overflow { - true => { - let overflowing_u8: u8 = safe_div_8(first_arg, second_arg); - }, - false => { - let fitting_u8: u8 = safe_div_8(first_arg, second_arg); - assert!(jet::eq_8(fitting_u8, result)); - } - } - }, - false => (), - }; -} diff --git a/simf/u8_test.simf b/simf/u8_test.simf new file mode 100644 index 0000000..40fa44e --- /dev/null +++ b/simf/u8_test.simf @@ -0,0 +1,37 @@ +use crate::lib::u8::{checked_add_8, safe_add_8, checked_sub_8, safe_sub_8, checked_mul_8, safe_mul_8, checked_div_8, safe_div_8}; + +use crate::helper::if_test_this_function; + +// Asserts a `checked_*` result equals the expected Option. +// `None` encodes the overflow case, `Some(e)` the fitting case, so a single +// witness value carries both, removing the need for a separate overflow flag. +fn assert_eq_opt(result: Option, expected: Option) { + match expected { + None => assert!(is_none::(result)), + Some(e: u8) => assert!(jet::eq_8(unwrap(result), e)), + } +} + +fn main() { + let fn_idx: u8 = witness::FUNCTION_INDEX; + + let a: u8 = witness::FIRST_ARG; + let b: u8 = witness::SECOND_ARG; + let expected: Option = witness::EXPECTED; + + // add + match if_test_this_function(0, fn_idx) { true => { assert_eq_opt(checked_add_8(a, b), expected); }, false => (), }; + match if_test_this_function(1, fn_idx) { true => { assert!(jet::eq_8(safe_add_8(a, b), unwrap(expected))); }, false => (), }; + + // sub + match if_test_this_function(2, fn_idx) { true => { assert_eq_opt(checked_sub_8(a, b), expected); }, false => (), }; + match if_test_this_function(3, fn_idx) { true => { assert!(jet::eq_8(safe_sub_8(a, b), unwrap(expected))); }, false => (), }; + + // mul + match if_test_this_function(4, fn_idx) { true => { assert_eq_opt(checked_mul_8(a, b), expected); }, false => (), }; + match if_test_this_function(5, fn_idx) { true => { assert!(jet::eq_8(safe_mul_8(a, b), unwrap(expected))); }, false => (), }; + + // div + match if_test_this_function(6, fn_idx) { true => { assert_eq_opt(checked_div_8(a, b), expected); }, false => (), }; + match if_test_this_function(7, fn_idx) { true => { assert!(jet::eq_8(safe_div_8(a, b), unwrap(expected))); }, false => (), }; +} diff --git a/tests/asserts_test.rs b/tests/asserts_test.rs index a13a988..c7dc178 100644 --- a/tests/asserts_test.rs +++ b/tests/asserts_test.rs @@ -1,16 +1,16 @@ -use simplex::simplicityhl::elements::Script; +mod common; -use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; +use rand::Rng; -use simplicityhl_std::artifacts::asserts_mock::AssertsMockProgram; -use simplicityhl_std::artifacts::asserts_mock::derived_asserts_mock::{ - AssertsMockArguments, AssertsMockWitness, -}; - -mod helper; +use common::{Expect, run}; -use crate::helper::{cast_to_bool, generate_uints_in_one_range}; +use simplicityhl_std::artifacts::asserts_test::AssertsTestProgram; +use simplicityhl_std::artifacts::asserts_test::derived_asserts_test::{ + AssertsTestArguments, AssertsTestWitness, +}; +// Dispatch indices — must match the `if_test_this_function(N, ..)` arms in +// simf/asserts_test.simf. enum FunctionToTest { AssertEq8, AssertEq16, @@ -32,42 +32,36 @@ const DEFAULT_SOME_U64: Option = Some(0); const DEFAULT_SOME_U128: Option = Some(0); const DEFAULT_SOME_U256: Option<[u8; 32]> = Some([0; 32]); -pub enum IfTestSameValues { - DifferentValues, - SameValues, +fn program() -> AssertsTestProgram { + AssertsTestProgram::new(AssertsTestArguments {}) } -pub enum IfTestNoneValue { - NotNoneValue, - NoneValue, -} - -fn get_asserts_test_script(context: &simplex::TestContext) -> (AssertsMockProgram, Script) { - let arguments = AssertsMockArguments {}; - let asserts_program = AssertsMockProgram::new(arguments); +/// Returns two values in `[min, max]` that are equal when `same`, distinct otherwise. +pub fn generate_uints_in_one_range(same: bool, min_val: u128, max_val: u128) -> (u128, u128) { + let some_u = rand::thread_rng().gen_range(min_val..=max_val); - let asserts_script = asserts_program.get_script_pubkey(context.get_network()); - - (asserts_program, asserts_script) -} + if same { + return (some_u, some_u); + } -fn fund_script(context: &simplex::TestContext) -> anyhow::Result<()> { - let signer = context.get_default_signer(); + assert!( + min_val != max_val, + "cannot generate distinct values in a single-value range" + ); - let (_, asserts_script) = get_asserts_test_script(context); + let mut other_u = rand::thread_rng().gen_range(min_val..=max_val); - let tx_receipt = signer.send(asserts_script.clone(), 50)?; - println!("Broadcast: {}", tx_receipt); + while other_u == some_u { + other_u = rand::thread_rng().gen_range(min_val..=max_val); + } - Ok(()) + (some_u, other_u) } -fn generate_test_witness( - function_index: FunctionToTest, - if_same_values: bool, - if_none_value: bool, -) -> AssertsMockWitness { - let mut witness: AssertsMockWitness = AssertsMockWitness { +/// Builds the witness for one assert call. `same` controls the two `assert_eq` +/// args; `none` makes the single `assert_none` arg `None`. +fn build_witness(function: FunctionToTest, same: bool, none: bool) -> AssertsTestWitness { + let mut witness = AssertsTestWitness { function_index: 0, first_arg_u8: DEFAULT_SOME_U8, second_arg_u8: DEFAULT_SOME_U8, @@ -83,500 +77,317 @@ fn generate_test_witness( second_arg_u256: DEFAULT_SOME_U256, }; - match function_index { + match function { FunctionToTest::AssertEq8 => { - let (first_arg, second_arg) = - generate_uints_in_one_range(if_same_values, 0, u8::MAX as u128); - - (witness.first_arg_u8, witness.second_arg_u8) = - (Some(first_arg as u8), Some(second_arg as u8)); + let (a, b) = generate_uints_in_one_range(same, 0, u8::MAX as u128); + (witness.first_arg_u8, witness.second_arg_u8) = (Some(a as u8), Some(b as u8)); } FunctionToTest::AssertEq16 => { - let (first_arg, second_arg) = - generate_uints_in_one_range(if_same_values, 0, u16::MAX as u128); - - (witness.first_arg_u16, witness.second_arg_u16) = - (Some(first_arg as u16), Some(second_arg as u16)); + let (a, b) = generate_uints_in_one_range(same, 0, u16::MAX as u128); + (witness.first_arg_u16, witness.second_arg_u16) = (Some(a as u16), Some(b as u16)); } FunctionToTest::AssertEq32 => { - let (first_arg, second_arg) = - generate_uints_in_one_range(if_same_values, 0, u32::MAX as u128); - - (witness.first_arg_u32, witness.second_arg_u32) = - (Some(first_arg as u32), Some(second_arg as u32)); + let (a, b) = generate_uints_in_one_range(same, 0, u32::MAX as u128); + (witness.first_arg_u32, witness.second_arg_u32) = (Some(a as u32), Some(b as u32)); } FunctionToTest::AssertEq64 => { - let (first_arg, second_arg) = - generate_uints_in_one_range(if_same_values, 0, u64::MAX as u128); - - (witness.first_arg_u64, witness.second_arg_u64) = - (Some(first_arg as u64), Some(second_arg as u64)); + let (a, b) = generate_uints_in_one_range(same, 0, u64::MAX as u128); + (witness.first_arg_u64, witness.second_arg_u64) = (Some(a as u64), Some(b as u64)); } FunctionToTest::AssertEq256 => { - let (first_arg, second_arg) = - generate_uints_in_one_range(if_same_values, 0, u8::MAX as u128); - + let (a, b) = generate_uints_in_one_range(same, 0, u8::MAX as u128); (witness.first_arg_u256, witness.second_arg_u256) = - (Some([first_arg as u8; 32]), Some([second_arg as u8; 32])); + (Some([a as u8; 32]), Some([b as u8; 32])); } FunctionToTest::AssertNone8 => { - if if_none_value { + if none { witness.first_arg_u8 = None; - }; + } } FunctionToTest::AssertNone16 => { - if if_none_value { + if none { witness.first_arg_u16 = None; - }; + } } FunctionToTest::AssertNone32 => { - if if_none_value { + if none { witness.first_arg_u32 = None; - }; + } } FunctionToTest::AssertNone64 => { - if if_none_value { + if none { witness.first_arg_u64 = None; - }; + } } FunctionToTest::AssertNone128 => { - if if_none_value { + if none { witness.first_arg_u128 = None; - }; + } } FunctionToTest::AssertNone256 => { - if if_none_value { + if none { witness.first_arg_u256 = None; - }; + } } } - witness.function_index = function_index as u8; + witness.function_index = function as u8; witness } -fn spend_script( +fn run_assert( context: &simplex::TestContext, - function_index: FunctionToTest, - if_same_values: IfTestSameValues, - if_none_value: IfTestNoneValue, + function: FunctionToTest, + same: bool, + none: bool, + expect: Expect, ) -> anyhow::Result<()> { - let signer = context.get_default_signer(); - let provider = context.get_default_provider(); - - let (asserts_program, asserts_script) = get_asserts_test_script(context); - - let asserts_utxos = provider.fetch_scripthash_utxos(&asserts_script)?; - - let mut ft = FinalTransaction::new(); - - let witness: AssertsMockWitness = generate_test_witness( - function_index, - cast_to_bool(if_same_values as u8), - cast_to_bool(if_none_value as u8), - ); - - ft.add_program_input( - PartialInput::new(asserts_utxos[0].clone()), - ProgramInput::new( - Box::new(asserts_program.as_ref().clone()), - Box::new(witness.clone()), - ), - RequiredSignature::None, - ); - - let tx_receipt = signer.broadcast(&ft)?; - println!("Broadcast: {}", tx_receipt); - - Ok(()) -} - -#[simplex::test] -fn assert_eq_8_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertEq8, - IfTestSameValues::SameValues, - IfTestNoneValue::NotNoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_eq_8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertEq8, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_eq_16_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertEq16, - IfTestSameValues::SameValues, - IfTestNoneValue::NotNoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_eq_16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertEq16, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_eq_32_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertEq32, - IfTestSameValues::SameValues, - IfTestNoneValue::NotNoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_eq_32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertEq32, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_eq_64_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertEq64, - IfTestSameValues::SameValues, - IfTestNoneValue::NotNoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_eq_64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertEq64, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_eq_256_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertEq256, - IfTestSameValues::SameValues, - IfTestNoneValue::NotNoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_eq_256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertEq256, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_none_8_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - spend_script( - &context, - FunctionToTest::AssertNone8, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_none_8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone8, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_none_16_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - spend_script( - &context, - FunctionToTest::AssertNone16, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; - - Ok(()) + run( + context, + program(), + build_witness(function, same, none), + expect, + ) } -#[simplex::test] -fn assert_none_16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone16, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} - -#[simplex::test] -fn assert_none_32_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - spend_script( - &context, - FunctionToTest::AssertNone32, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; - - Ok(()) -} - -#[simplex::test] -fn assert_none_32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone32, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); - - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); - - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); - - Ok(()) -} +mod asserts_test { + use super::*; -#[simplex::test] -fn assert_none_64_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; - - spend_script( - &context, - FunctionToTest::AssertNone64, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; - - Ok(()) -} + // ---------- assert_eq: happy = equal args, unhappy = distinct args ---------- + #[simplex::test] + fn assert_eq_8_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert(&context, FunctionToTest::AssertEq8, true, false, Expect::Ok) + } -#[simplex::test] -fn assert_none_64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; + #[simplex::test] + fn assert_eq_8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq8, + false, + false, + Expect::AssertFailed, + ) + } - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone64, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); + #[simplex::test] + fn assert_eq_16_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq16, + true, + false, + Expect::Ok, + ) + } - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); + #[simplex::test] + fn assert_eq_16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq16, + false, + false, + Expect::AssertFailed, + ) + } - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); + #[simplex::test] + fn assert_eq_32_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq32, + true, + false, + Expect::Ok, + ) + } - Ok(()) -} + #[simplex::test] + fn assert_eq_32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq32, + false, + false, + Expect::AssertFailed, + ) + } -#[simplex::test] -fn assert_none_128_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; + #[simplex::test] + fn assert_eq_64_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq64, + true, + false, + Expect::Ok, + ) + } - spend_script( - &context, - FunctionToTest::AssertNone128, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; + #[simplex::test] + fn assert_eq_64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq64, + false, + false, + Expect::AssertFailed, + ) + } - Ok(()) -} + #[simplex::test] + fn assert_eq_256_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq256, + true, + false, + Expect::Ok, + ) + } -#[simplex::test] -fn assert_none_128_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; + #[simplex::test] + fn assert_eq_256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertEq256, + false, + false, + Expect::AssertFailed, + ) + } - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone128, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); + // ---------- assert_none: happy = None arg, unhappy = Some arg ---------- + #[simplex::test] + fn assert_none_8_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone8, + false, + true, + Expect::Ok, + ) + } - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); + #[simplex::test] + fn assert_none_8_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone8, + false, + false, + Expect::AssertFailed, + ) + } - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); + #[simplex::test] + fn assert_none_16_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone16, + false, + true, + Expect::Ok, + ) + } - Ok(()) -} + #[simplex::test] + fn assert_none_16_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone16, + false, + false, + Expect::AssertFailed, + ) + } -#[simplex::test] -fn assert_none_256_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; + #[simplex::test] + fn assert_none_32_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone32, + false, + true, + Expect::Ok, + ) + } - spend_script( - &context, - FunctionToTest::AssertNone256, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NoneValue, - )?; + #[simplex::test] + fn assert_none_32_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone32, + false, + false, + Expect::AssertFailed, + ) + } - Ok(()) -} + #[simplex::test] + fn assert_none_64_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone64, + false, + true, + Expect::Ok, + ) + } -#[simplex::test] -fn assert_none_256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { - fund_script(&context)?; + #[simplex::test] + fn assert_none_64_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone64, + false, + false, + Expect::AssertFailed, + ) + } - let txid_result = spend_script( - &context, - FunctionToTest::AssertNone256, - IfTestSameValues::DifferentValues, - IfTestNoneValue::NotNoneValue, - ); + #[simplex::test] + fn assert_none_128_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone128, + false, + true, + Expect::Ok, + ) + } - assert!( - txid_result.is_err(), - "Expected this test to fail but it succeeded" - ); + #[simplex::test] + fn assert_none_128_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone128, + false, + false, + Expect::AssertFailed, + ) + } - let err: String = txid_result.unwrap_err().to_string(); - assert_eq!(err, "Failed to prune program: Jet failed during execution"); + #[simplex::test] + fn assert_none_256_happy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone256, + false, + true, + Expect::Ok, + ) + } - Ok(()) + #[simplex::test] + fn assert_none_256_unhappy_path(context: simplex::TestContext) -> anyhow::Result<()> { + run_assert( + &context, + FunctionToTest::AssertNone256, + false, + false, + Expect::AssertFailed, + ) + } } diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..6e2fb5e --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,97 @@ +// Each `tests/*.rs` is a separate crate that mounts this module but uses only +// part of it, so per-crate dead-code analysis would warn about the rest. +#![allow(dead_code)] + +use simplex::program::{Program, WitnessTrait}; +use simplex::simplicityhl::elements::Script; +use simplex::transaction::{FinalTransaction, PartialInput, ProgramInput, RequiredSignature}; + +pub mod uint; + +// --------------------------------------------------------------------------- +// Spend plumbing (shared by every test, of every category) +// --------------------------------------------------------------------------- + +#[derive(Clone, Copy)] +pub enum Expect { + /// The spend succeeds. + Ok, + /// A failed `assert!` in the contract — the assertion jet fails. + AssertFailed, + /// Execution reached a pruned branch (e.g. `unwrap(None)`, a `safe_*` overflow). + PrunedBranch, +} + +impl Expect { + /// The exact broadcast error message for a failing expectation (`None` for `Ok`). + fn error_message(self) -> Option<&'static str> { + match self { + Expect::Ok => None, + Expect::AssertFailed => Some("Failed to prune program: Jet failed during execution"), + Expect::PrunedBranch => { + Some("Failed to prune program: Execution reached a pruned branch") + } + } + } +} + +/// Send sats to the program's script so it has a UTXO to spend. +pub fn fund( + context: &simplex::TestContext, + program: &impl AsRef, +) -> anyhow::Result