diff --git a/compiler/tests/runtime.rs b/compiler/tests/runtime.rs index cc1cbcf417..595b23891a 100644 --- a/compiler/tests/runtime.rs +++ b/compiler/tests/runtime.rs @@ -34,9 +34,7 @@ fn test_revert_with_reason_string(reason: &str) { let reason_id = format!(r#""{}""#, keccak::full(reason.as_bytes())); with_executor(&|mut executor| { - test_runtime_functions_revert( - &mut executor, - Runtime::default() + Runtime::default() .with_data( vec![yul::Data { name: keccak::full(reason.as_bytes()), value: reason.to_owned() }] ) @@ -44,18 +42,18 @@ fn test_revert_with_reason_string(reason: &str) { statements! { (let reason := load_data_string((dataoffset([literal_expression! { (reason_id) }])), (datasize([literal_expression! { (reason_id) }])))) (revert_with_reason_string(reason)) - }), - &encode_error_reason(reason) - ); + }) + .execute(&mut executor) + .expect_revert() + .expect_revert_reason(reason); }) } #[test] fn test_runtime_alloc_and_avail() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements(statements! { + Runtime::default() + .with_test_statements(statements! { (let a := avail()) (let b := alloc(5)) (let c := alloc(10)) @@ -64,17 +62,17 @@ fn test_runtime_alloc_and_avail() { [assert_eq!(b, a)] [assert_eq!(c, (add(b, 5)))] [assert_eq!(d, (add(c, 10)))] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } #[test] fn test_runtime_mcopys() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements(statements! { + Runtime::default() + .with_test_statements(statements! { (let a := 0x0111114211111111011111112342311101111112221151110111111111111111) (let b := 0x0111111234111111011123411111111101112431111111110111111234411111) (let c := 0x0111341111111111011111111123411101111123411111110111111234111111) @@ -100,17 +98,17 @@ fn test_runtime_mcopys() { [assert_eq!(b, (sload(47)))] [assert_eq!(c, (sload(48)))] [assert_eq!(d, (sload(49)))] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } #[test] fn test_runtime_scopym() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements(statements! { + Runtime::default() + .with_test_statements(statements! { (let a := 0x0111114211111111011111112342311101111112221151110111111111111111) (let b := 0x0111111234111111011123411111111101112431111111110111111234411111) (let c := 0x0111341111111111011111111123411101111123411111110111111234111111) @@ -142,17 +140,17 @@ fn test_runtime_scopym() { [assert_eq!(b, (mload(ptr6)))] [assert_eq!(c, (mload(ptr7)))] [assert_eq!(d, (mload(ptr8)))] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } #[test] fn test_runtime_mloadn() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements(statements! { + Runtime::default() + .with_test_statements(statements! { (let a := 0x4200000000000000000000000000000000000000000000000000000000420026) (mstore(100, a)) @@ -160,17 +158,17 @@ fn test_runtime_mloadn() { [assert_eq!(0x420026, (mloadn(129, 3)))] [assert_eq!(0x26, (mloadn(130, 2)))] [assert_eq!(0x26, (mloadn(131, 1)))] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } #[test] fn test_runtime_storage_sanity() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::new().with_test_statements(statements! { + Runtime::new() + .with_test_statements(statements! { (let a := 0x4200000000000000000000000000000000000000000000000000000000000026) (let b := 0x9900000000000000000000000000000000000000000000000000000000000077) (sstore(0, a)) @@ -178,17 +176,17 @@ fn test_runtime_storage_sanity() { [assert_eq!(a, (sload(0)))] [assert_eq!(b, (sload(1)))] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } #[test] fn test_runtime_sloadn() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements(statements! { + Runtime::default() + .with_test_statements(statements! { (let a := 0x4200000000000000000000000000000000000000000000000000000000000026) (let b := 0x9900530000003900000000000000000000000000000000000000000000000077) (sstore(1000, a)) @@ -205,17 +203,17 @@ fn test_runtime_sloadn() { [assert_eq!(0x77, (sloadn(1001, 31, 1)))] [assert_eq!(0x990053, (sloadn(1001, 0, 3)))] [assert_eq!(0x5300000039, (sloadn(1001, 2, 5)))] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } #[test] fn test_runtime_sstoren() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements(statements! { + Runtime::default() + .with_test_statements(statements! { (let a := 0x0111111111111111011111111111111101111111111111110111111111111111) // dashes indicate which bytes are to be replaced in this test // 0----2 8----10 15----------------23 31--32 @@ -233,46 +231,46 @@ fn test_runtime_sstoren() { (sstoren(1000, 0, 32, c)) [assert_eq!(c, (sload(1000)))] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } #[test] fn test_runtime_ceil32() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements(statements! { + Runtime::default() + .with_test_statements(statements! { [assert_eq!(32, (ceil32(29)))] [assert_eq!(256, (ceil32(225)))] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } #[test] fn test_runtime_ternary() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements(statements! { + Runtime::default() + .with_test_statements(statements! { (let a := ternary(0, 42, 26)) (let b := ternary(1, 42, 26)) [assert_eq!(a, 26)] [assert_eq!(b, 42)] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } #[test] fn test_runtime_abi_unpack() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements(statements! { + Runtime::default() + .with_test_statements(statements! { (let a := 0x0042002600530000000000000000000000000000000000000000000000000000) (let packed := alloc_mstoren(a, 32)) (let unpacked := avail()) @@ -285,17 +283,16 @@ fn test_runtime_abi_unpack() { [assert_eq!(elem0, 0x0042)] [assert_eq!(elem1, 0x0026)] [assert_eq!(elem2, 0x0053)] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } #[test] fn test_keccak256() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements( + Runtime::default().with_test_statements( statements! { (let num := 63806209331542711802848847270949280092855778197726125910674179583545433573378) (let result :=109966633016701122630199943745061001312678661825260870342362413625737614346915) @@ -306,16 +303,16 @@ fn test_keccak256() { [assert_eq!(result, (keccak256(0, 32)))] }, ) - ); + .execute(&mut executor) + .expect_success(); }) } #[test] fn test_runtime_set_zero() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements(statements! { + Runtime::default() + .with_test_statements(statements! { (let a := 0x1111111111111111111111111111111111111111111111111111111111111111) (let b := 0x1111110000000000000000000000000000000000000000000000001111111111) (let c := 0x1111100000000000000000000000000000000000000000000000000000000000) @@ -324,8 +321,9 @@ fn test_runtime_set_zero() { [assert_eq!(0x11, (set_zero(0, 248, a)))] [assert_eq!(b, (set_zero(24, 216, a)))] [assert_eq!(c, (set_zero(20, 256, a)))] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } @@ -345,9 +343,7 @@ fn test_runtime_house_struct() { let house_api = functions::structs::struct_apis(house); with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::new().with_functions([functions::std(), house_api.clone()].concat()).with_test_statements( + Runtime::new().with_functions([functions::std(), house_api.clone()].concat()).with_test_statements( statements! { (let price := 42) (let size := 26) @@ -387,18 +383,19 @@ fn test_runtime_house_struct() { [assert_eq!(vacant, (bytes_sloadn((struct_House_get_vacant_ptr(house_storage)), 1)))] }, ) - ); + .execute(&mut executor) + .expect_success(); }) } #[test] fn checked_exp_signed() { with_executor(&|mut executor| { - test_runtime_functions( - &mut executor, - Runtime::default().with_test_statements(statements! { + Runtime::default() + .with_test_statements(statements! { [assert_eq!(4, (checked_exp_signed(2, 2, 0, 100)))] - }), - ); + }) + .execute(&mut executor) + .expect_success(); }) } diff --git a/compiler/tests/utils.rs b/compiler/tests/utils.rs index 7c8f7b451e..e2777dc35c 100644 --- a/compiler/tests/utils.rs +++ b/compiler/tests/utils.rs @@ -326,36 +326,17 @@ pub fn load_contract(address: H160, fixture: &str, contract_name: &str) -> Contr ContractHarness::new(address, abi) } -#[allow(dead_code)] -pub fn test_runtime_functions(executor: &mut Executor, runtime: Runtime) { - let (reason, _) = execute_runtime_functions(executor, runtime); - if !matches!(reason, ExitReason::Succeed(_)) { - panic!("Runtime function test failed: {:?}", reason) - } -} - -#[allow(dead_code)] -pub fn test_runtime_functions_revert( - executor: &mut Executor, - runtime: Runtime, - expected_output: &[u8], -) { - let (reason, output) = execute_runtime_functions(executor, runtime); - if output != expected_output { - panic!("Runtime function test failed (wrong output): {:?}", output) - } - - if !matches!(reason, ExitReason::Revert(_)) { - panic!("Runtime function did not revert: {:?}", reason) - } -} - pub struct Runtime { functions: Vec, test_statements: Vec, data: Vec, } +pub struct ExecutionOutput { + exit_reason: ExitReason, + data: Vec, +} + #[allow(dead_code)] impl Runtime { /// Create a `Runtime` instance with all `std` functions. @@ -403,9 +384,54 @@ impl Runtime { data: self.data.clone(), } } + + pub fn execute(&self, executor: &mut Executor) -> ExecutionOutput { + let (exit_reason, data) = execute_runtime_functions(executor, &self); + ExecutionOutput::new(exit_reason, data) + } +} + +#[allow(dead_code)] +impl ExecutionOutput { + /// Create an `ExecutionOutput` instance + pub fn new(exit_reason: ExitReason, data: Vec) -> ExecutionOutput { + ExecutionOutput { exit_reason, data } + } + + /// Panic if the execution did not succeed. + pub fn expect_success(self) -> ExecutionOutput { + if let ExecutionOutput { + exit_reason: ExitReason::Succeed(_), + .. + } = &self + { + self + } else { + panic!("Execution did not succeed: {:?}", &self.exit_reason) + } + } + + /// Panic if the execution did not revert. + pub fn expect_revert(self) -> ExecutionOutput { + if let ExecutionOutput { + exit_reason: ExitReason::Revert(_), + .. + } = &self + { + self + } else { + panic!("Execution did not revert: {:?}", &self.exit_reason) + } + } + + /// Panic if the output is not an encoded error reason of the given string. + pub fn expect_revert_reason(self, reason: &str) -> ExecutionOutput { + assert_eq!(self.data, encode_error_reason(reason)); + self + } } -fn execute_runtime_functions(executor: &mut Executor, runtime: Runtime) -> (ExitReason, Vec) { +fn execute_runtime_functions(executor: &mut Executor, runtime: &Runtime) -> (ExitReason, Vec) { let yul_code = runtime.to_yul().to_string().replace("\"", "\\\""); let bytecode = compiler::evm::compile_single_contract("Contract", yul_code, false) .expect("failed to compile Yul");