From ff3a619b01f3932a2a27e069eede05dbfe72bd20 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 3 Jul 2019 19:08:41 +0100 Subject: [PATCH] rust: add test for ExecutionContext.call() --- bindings/rust/evmc-vm/src/lib.rs | 105 ++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/bindings/rust/evmc-vm/src/lib.rs b/bindings/rust/evmc-vm/src/lib.rs index 08b8be3..5b7c55f 100644 --- a/bindings/rust/evmc-vm/src/lib.rs +++ b/bindings/rust/evmc-vm/src/lib.rs @@ -731,6 +731,36 @@ mod tests { 105023 as usize } + unsafe extern "C" fn execute_call( + _context: *mut ffi::evmc_context, + _msg: *const ffi::evmc_message, + ) -> ffi::evmc_result { + // Some dumb validation for testing. + let msg = *_msg; + let success = if msg.input_size != 0 && msg.input_data == std::ptr::null() { + false + } else if msg.input_size == 0 && msg.input_data != std::ptr::null() { + false + } else { + true + }; + + ffi::evmc_result { + status_code: if success { + ffi::evmc_status_code::EVMC_SUCCESS + } else { + ffi::evmc_status_code::EVMC_INTERNAL_ERROR + }, + gas_left: 2, + // NOTE: we are passing the input pointer here, but for testing the lifetime is ok + output_data: msg.input_data, + output_size: msg.input_size, + release: None, + create_address: ffi::evmc_address::default(), + padding: [0u8; 4], + } + } + // Update these when needed for tests fn get_dummy_context() -> ffi::evmc_context { ffi::evmc_context { @@ -743,7 +773,7 @@ mod tests { get_code_hash: None, copy_code: None, selfdestruct: None, - call: None, + call: Some(execute_call), get_tx_context: Some(get_dummy_tx_context), get_block_hash: None, emit_log: None, @@ -824,4 +854,77 @@ mod tests { dummy_context_dispose(context_raw); } + + #[test] + fn test_call_empty_data() { + let msg = get_dummy_message(); + + // This address is useless. Just a dummy parameter for the interface function. + let test_addr = ffi::evmc_address { bytes: [0u8; 20] }; + let mut context_raw = get_dummy_context(); + let mut exe_context = ExecutionContext::new(&msg, &mut context_raw); + + let message = ExecutionMessage::new( + ffi::evmc_call_kind::EVMC_CALL, + 0, + 0, + 6566, + test_addr, + test_addr, + None, + ffi::evmc_uint256be::default(), + ffi::evmc_bytes32::default(), + ); + + let b = exe_context.call(&message); + + assert_eq!(b.get_status_code(), ffi::evmc_status_code::EVMC_SUCCESS); + assert_eq!(b.get_gas_left(), 2); + assert!(b.get_output().is_none()); + assert!(b.get_create_address().is_some()); + assert_eq!( + b.get_create_address().unwrap(), + &ffi::evmc_address::default() + ); + + dummy_context_dispose(context_raw); + } + + #[test] + fn test_call_with_data() { + let msg = get_dummy_message(); + + // This address is useless. Just a dummy parameter for the interface function. + let test_addr = ffi::evmc_address { bytes: [0u8; 20] }; + let mut context_raw = get_dummy_context(); + let mut exe_context = ExecutionContext::new(&msg, &mut context_raw); + + let data = vec![0xc0, 0xff, 0xfe]; + + let message = ExecutionMessage::new( + ffi::evmc_call_kind::EVMC_CALL, + 0, + 0, + 6566, + test_addr, + test_addr, + Some(&data), + ffi::evmc_uint256be::default(), + ffi::evmc_bytes32::default(), + ); + + let b = exe_context.call(&message); + + assert_eq!(b.get_status_code(), ffi::evmc_status_code::EVMC_SUCCESS); + assert_eq!(b.get_gas_left(), 2); + assert!(b.get_output().is_some()); + assert_eq!(b.get_output().unwrap(), &data); + assert!(b.get_create_address().is_some()); + assert_eq!( + b.get_create_address().unwrap(), + &ffi::evmc_address::default() + ); + + dummy_context_dispose(context_raw); + } }