From f74e9bb2b1b8770f7b91eebc2edf97dbe664820b Mon Sep 17 00:00:00 2001 From: Oleksii Filonenko <12615679+Br1ght0ne@users.noreply.github.com> Date: Fri, 15 Dec 2023 17:06:06 +0200 Subject: [PATCH] chore: add test for compute_calls_instructions_len (#1183) Close #1129. I added a test case for an empty (random) contract, would like some feedback on what kinds of non-empty contracts to test. ### Checklist - [x] I have linked to any relevant issues. - [x] I have updated the documentation. - [x] I have added tests that prove my fix is effective or that my feature works. - [x] I have added necessary labels. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. --------- Co-authored-by: MujkicA <32431923+MujkicA@users.noreply.github.com> Co-authored-by: iqdecay Co-authored-by: hal3e Co-authored-by: Ahmed Sagdati <37515857+segfault-magnet@users.noreply.github.com> --- packages/fuels-programs/src/call_utils.rs | 108 ++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/packages/fuels-programs/src/call_utils.rs b/packages/fuels-programs/src/call_utils.rs index d8586b55b6..28aa12259e 100644 --- a/packages/fuels-programs/src/call_utils.rs +++ b/packages/fuels-programs/src/call_utils.rs @@ -946,4 +946,112 @@ mod test { expected_asset_id_amounts ) } + + mod compute_calls_instructions_len { + use fuel_asm::Instruction; + use fuels_core::types::{enum_variants::EnumVariants, param_types::ParamType}; + + use crate::{call_utils::compute_calls_instructions_len, contract::ContractCall}; + + // movi, movi, lw, movi + call (for gas) + const BASE_INSTRUCTION_COUNT: usize = 5; + // 2 instructions (movi and lw) added in get_single_call_instructions when gas_offset is set + const GAS_OFFSET_INSTRUCTION_COUNT: usize = 2; + // 4 instructions (lw, lw, muli, retd) added by extract_data_receipt + const EXTRACT_DATA_RECEIPT_INSTRUCTION_COUNT: usize = 4; + // 4 instructions (movi, lw, jnef, retd) added by extract_heap_data + const EXTRACT_HEAP_DATA_INSTRUCTION_COUNT: usize = 4; + + #[test] + fn test_simple() { + let call = ContractCall::new_with_random_id(); + let instructions_len = compute_calls_instructions_len(&[call]).unwrap(); + assert_eq!(instructions_len, Instruction::SIZE * BASE_INSTRUCTION_COUNT); + } + + #[test] + fn test_with_gas_offset() { + let mut call = ContractCall::new_with_random_id(); + call.call_parameters = call.call_parameters.with_gas_forwarded(0); + let instructions_len = compute_calls_instructions_len(&[call]).unwrap(); + assert_eq!( + instructions_len, + Instruction::SIZE * (BASE_INSTRUCTION_COUNT + GAS_OFFSET_INSTRUCTION_COUNT) + ); + } + + #[test] + fn test_with_heap_type() { + let output_params = vec![ + ParamType::Vector(Box::new(ParamType::U8)), + ParamType::String, + ParamType::Bytes, + ]; + for output_param in output_params { + let mut call = ContractCall::new_with_random_id(); + call.output_param = output_param; + let instructions_len = compute_calls_instructions_len(&[call]).unwrap(); + assert_eq!( + instructions_len, + Instruction::SIZE + * (BASE_INSTRUCTION_COUNT + EXTRACT_DATA_RECEIPT_INSTRUCTION_COUNT) + ); + } + } + + #[test] + fn test_with_gas_offset_and_heap_type() { + let mut call = ContractCall::new_with_random_id(); + call.call_parameters = call.call_parameters.with_gas_forwarded(0); + call.output_param = ParamType::Vector(Box::new(ParamType::U8)); + let instructions_len = compute_calls_instructions_len(&[call]).unwrap(); + assert_eq!( + instructions_len, + // combines extra instructions from two above tests + Instruction::SIZE + * (BASE_INSTRUCTION_COUNT + + GAS_OFFSET_INSTRUCTION_COUNT + + EXTRACT_DATA_RECEIPT_INSTRUCTION_COUNT) + ); + } + + #[test] + fn test_with_enum_with_heap_and_non_heap_variant() { + let variant_sets = vec![ + vec![ParamType::Vector(Box::new(ParamType::U8)), ParamType::U8], + vec![ParamType::String, ParamType::U8], + vec![ParamType::Bytes, ParamType::U8], + ]; + for variant_set in variant_sets { + let mut call = ContractCall::new_with_random_id(); + call.output_param = ParamType::Enum { + variants: EnumVariants::new(variant_set).unwrap(), + generics: Vec::new(), + }; + let instructions_len = compute_calls_instructions_len(&[call]).unwrap(); + assert_eq!( + instructions_len, + Instruction::SIZE + * (BASE_INSTRUCTION_COUNT + + EXTRACT_DATA_RECEIPT_INSTRUCTION_COUNT + + EXTRACT_HEAP_DATA_INSTRUCTION_COUNT) + ); + } + } + + #[test] + fn test_with_enum_with_only_non_heap_variants() { + let mut call = ContractCall::new_with_random_id(); + call.output_param = ParamType::Enum { + variants: EnumVariants::new(vec![ParamType::Bool, ParamType::U8]).unwrap(), + generics: Vec::new(), + }; + let instructions_len = compute_calls_instructions_len(&[call]).unwrap(); + assert_eq!( + instructions_len, + // no extra instructions if there are no heap type variants + Instruction::SIZE * BASE_INSTRUCTION_COUNT + ); + } + } }