From 9640881407140e16e8655eea719063bcf38db734 Mon Sep 17 00:00:00 2001 From: atoumbre Date: Sun, 9 Feb 2025 20:57:04 +0000 Subject: [PATCH 1/7] small fix --- test-engine/src/environment.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test-engine/src/environment.rs b/test-engine/src/environment.rs index 5a1fe60..6086dd0 100644 --- a/test-engine/src/environment.rs +++ b/test-engine/src/environment.rs @@ -385,7 +385,9 @@ impl EnvironmentEncode for EnvVec { let mut encoded = encoded.iter(); match encoded.next() { None => { - encoder.write_value_kind(ValueKind::I8).unwrap(); + encoder + .write_value_kind(ManifestCustomValueKind::Bucket.into()) + .unwrap(); encoder.write_size(size).expect(""); } Some(elem) => { From c31250c14a4076f13ae6bfd5d7e178de65f255a7 Mon Sep 17 00:00:00 2001 From: atoumbre Date: Thu, 13 Feb 2025 16:54:01 +0000 Subject: [PATCH 2/7] adding global_package_from_binary for testing on built wasm --- test-engine/src/macros.rs | 41 ++++++++++++++++++++++++++++++++++++++ test-engine/src/prelude.rs | 5 ++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/test-engine/src/macros.rs b/test-engine/src/macros.rs index 64f40aa..7127a9a 100644 --- a/test-engine/src/macros.rs +++ b/test-engine/src/macros.rs @@ -76,6 +76,47 @@ macro_rules! none { }; } +#[macro_export] +macro_rules! global_package_from_binary { + ($name:ident, $release_path:expr, $package_name:expr) => { + lazy_static! { + static ref $name: (Vec, PackageDefinition) = { + let package_test_dir = PathBuf::from_str(env!("CARGO_MANIFEST_DIR")).unwrap(); + let release_dir = package_test_dir.join($release_path); + let package_name = if $package_name == "" { + env!("CARGO_PKG_NAME") + } else { + $package_name + }; + + let wasm_path = release_dir.join(format!("{}.wasm", package_name)); + + let definition_path = release_dir.join(format!("{}.rpd", package_name)); + + let code = std::fs::read(&wasm_path).unwrap_or_else(|err| { + panic!( + "Failed to read built WASM from path {:?} - {:?}", + &wasm_path, err + ) + }); + let definition = std::fs::read(&definition_path).unwrap_or_else(|err| { + panic!( + "Failed to read package definition from path {:?} - {:?}", + &definition_path, err + ) + }); + let definition = manifest_decode(&definition).unwrap_or_else(|err| { + panic!( + "Failed to parse package definition from path {:?} - {:?}", + &definition_path, err + ) + }); + (code, definition) + }; + } + }; +} + #[macro_export] macro_rules! global_package_advanced { ($name:ident, $release_path:expr, $package_name:expr, $code_path:expr) => { diff --git a/test-engine/src/prelude.rs b/test-engine/src/prelude.rs index 92a53a4..c5f7110 100644 --- a/test-engine/src/prelude.rs +++ b/test-engine/src/prelude.rs @@ -12,4 +12,7 @@ pub use crate::receipt_traits::*; pub use crate::test_engine::*; pub use crate::to_id::ToId; pub use crate::utils::*; -pub use crate::{env_args, env_vec, global_package, global_package_advanced, nf_ids, none, some}; +pub use crate::{ + env_args, env_vec, global_package, global_package_advanced, global_package_from_binary, nf_ids, + none, some, +}; From fdd0e19bc0ee88df43492e64974a6112f25531f2 Mon Sep 17 00:00:00 2001 From: atoumbre Date: Fri, 14 Feb 2025 05:48:15 +0000 Subject: [PATCH 3/7] extend and push added to EnVec --- test-engine/src/environment.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test-engine/src/environment.rs b/test-engine/src/environment.rs index 6086dd0..1aa7651 100644 --- a/test-engine/src/environment.rs +++ b/test-engine/src/environment.rs @@ -361,6 +361,24 @@ impl EnvVec { pub fn from_vec(elements: Vec>) -> Self { Self { elements } } + + pub fn new() -> Self { + Self { + elements: Vec::new(), + } + } + + pub fn extend(&mut self, elements: EnvVec) { + self.elements.extend(elements.elements); + } +} + +impl Iterator for EnvVec { + type Item = Box; + + fn next(&mut self) -> Option { + self.elements.pop() + } } impl EnvironmentEncode for EnvVec { From 8e54718f0138ffa385c4053c316e2efde4492f68 Mon Sep 17 00:00:00 2001 From: atoumbre Date: Sun, 20 Apr 2025 10:03:20 +0000 Subject: [PATCH 4/7] environnement refactoring around ManifestValue --- test-engine/src/call_builder.rs | 135 +++-- test-engine/src/engine_interface.rs | 10 +- test-engine/src/environment.rs | 466 +++++++++++------- test-engine/src/from_instruction.rs | 18 - test-engine/src/lib.rs | 3 +- test-engine/src/macros.rs | 26 +- test-engine/src/method_call.rs | 18 +- test-engine/src/prelude.rs | 1 + test-engine/src/receipt_traits.rs | 54 +- test-engine/src/test_engine.rs | 32 +- test-engine/tests/general/mod.rs | 10 +- .../tests/gumball_machine/unit_tests.rs | 2 +- 12 files changed, 451 insertions(+), 324 deletions(-) delete mode 100644 test-engine/src/from_instruction.rs diff --git a/test-engine/src/call_builder.rs b/test-engine/src/call_builder.rs index 6816b7c..9b9452c 100644 --- a/test-engine/src/call_builder.rs +++ b/test-engine/src/call_builder.rs @@ -1,18 +1,14 @@ use crate::account::Account; -use crate::environment::{EnvironmentEncode, Fungible, NonFungible}; +use crate::environment::{Fungible, NonFungible}; use crate::internal_prelude::*; use crate::method_call::SimpleMethodCaller; -use crate::references::{ComponentReference, GlobalReference, ReferenceName, ResourceReference}; +use crate::prelude::{ComponentReference, Outcome, ToValue}; +use crate::references::{GlobalReference, ReferenceName, ResourceReference}; use crate::test_engine::TestEngine; use crate::to_id::ToId; use std::collections::BTreeSet; use std::vec::Vec; -struct TransactionManifestData { - transaction_manifest: TransactionManifestV1, - // object_names: KnownManifestObjectNames, -} - pub struct CallBuilder<'a> { caller: Account, manifest_builder: ManifestBuilder, @@ -25,7 +21,7 @@ pub struct CallBuilder<'a> { with_tx_fee: bool, log_title: Option<&'a str>, deposit_destination: ComponentAddress, - manifest_data: Option, + transaction_manifest: Option, } impl<'a> CallBuilder<'a> { @@ -42,7 +38,7 @@ impl<'a> CallBuilder<'a> { output_manifest: None, admin_badge: vec![], with_trace: false, - manifest_data: None, + transaction_manifest: None, with_tx_fee: false, log_title: None, } @@ -69,7 +65,7 @@ impl<'a> CallBuilder<'a> { /// # Arguments /// * `method_name`: name of the method. /// * `args`: environment arguments to call the method. - pub fn call(self, method_name: &str, args: Vec>) -> Self { + pub fn call(self, method_name: &str, args: Vec>) -> Self { let component = *self.test_engine.current_component(); self.call_method_internal(component, method_name, args) } @@ -84,9 +80,10 @@ impl<'a> CallBuilder<'a> { self, entity_name: G, method_name: &str, - args: Vec>, + args: Vec>, ) -> Self { let component = entity_name.address(self.test_engine); + self.call_method_internal(component, method_name, args) } @@ -96,15 +93,13 @@ impl<'a> CallBuilder<'a> { /// * `name`: reference name of the component. pub fn set_current_component(self, name: E) -> Self { self.test_engine.set_current_component(name); + manifest_args!(); self } /// Executes the call. pub fn execute(mut self) -> TransactionReceipt { - self.manifest_data = Some(TransactionManifestData { - // object_names: self.manifest_builder.object_names().clone(), - transaction_manifest: self.manifest_builder.build(), - }); + self.transaction_manifest = Some(self.manifest_builder.build()); self.manifest_builder = ManifestBuilder::new(); @@ -114,7 +109,7 @@ impl<'a> CallBuilder<'a> { self.output_manifest(); let receipt = self.test_engine.execute_call( - self.manifest_data.unwrap().transaction_manifest, + self.transaction_manifest.unwrap(), self.with_trace, btreeset![self.caller.proof()], true, @@ -135,12 +130,16 @@ impl<'a> CallBuilder<'a> { receipt } - pub fn execute_and_expect_success(self) -> CommitResult { - self.execute().expect_commit_success().clone() + pub fn execute_and_expect_success(self) -> TransactionReceipt { + self.execute().assert_is_success() } - pub fn execute_and_expect_failure(self) -> CommitResult { - self.execute().expect_commit_failure().clone() + pub fn execute_and_expect_failure(self) -> TransactionReceipt { + self.execute().assert_failed() + } + + pub fn execute_and_expect_failure_with(self, error: &str) -> TransactionReceipt { + self.execute().assert_failed_with(error) } /// Deposits the batch to the given account. @@ -295,28 +294,21 @@ impl<'a> CallBuilder<'a> { mut self, component: impl ReferencedManifestGlobalAddress, method_name: &str, - args: Vec>, + args: Vec>, ) -> Self { - let mut manifest_builder = self.manifest_builder; - - let mut buf = Vec::new(); - let mut encoder = ManifestEncoder::new(&mut buf, MANIFEST_SBOR_V1_MAX_DEPTH); - encoder - .write_payload_prefix(MANIFEST_SBOR_V1_PAYLOAD_PREFIX) - .unwrap(); - encoder.write_value_kind(ManifestValueKind::Tuple).unwrap(); - encoder.write_size(args.len()).unwrap(); - for arg in args { - manifest_builder = arg.encode( - self.test_engine, - manifest_builder, - &mut encoder, - *self.caller.address(), - ); - } + let manifest_builder = self.manifest_builder; + + let (manifest_builder, values) = args.into_iter().fold( + (manifest_builder, Vec::new()), + |(manifest_builder, mut values), arg| { + let (manifest_builder, encoded) = + arg.to_value(self.test_engine, manifest_builder, *self.caller.address()); + values.push(encoded); + (manifest_builder, values) + }, + ); - let value = manifest_decode(&buf).unwrap(); - let manifest_arg = ManifestArgs::new_from_tuple_or_panic(value); + let manifest_arg = ManifestArgs::new_from_tuple_or_panic(Value::Tuple { fields: values }); let manifest_builder = manifest_builder.call_method(component, method_name, manifest_arg); @@ -326,10 +318,7 @@ impl<'a> CallBuilder<'a> { } pub(crate) fn execute_no_update(mut self) -> TransactionReceipt { - self.manifest_data = Some(TransactionManifestData { - // object_names: self.manifest_builder.object_names().clone(), - transaction_manifest: self.manifest_builder.build(), - }); + self.transaction_manifest = Some(self.manifest_builder.build()); self.manifest_builder = ManifestBuilder::new(); @@ -339,7 +328,7 @@ impl<'a> CallBuilder<'a> { self.output_manifest(); let receipt = self.test_engine.execute_call( - self.manifest_data.unwrap().transaction_manifest, + self.transaction_manifest.unwrap(), self.with_trace, btreeset![self.caller.proof()], false, @@ -365,28 +354,21 @@ impl<'a> CallBuilder<'a> { package_address: PackageAddress, blueprint_name: &str, function_name: &str, - args: Vec>, + args: Vec>, ) -> Self { - let mut manifest_builder = self.manifest_builder; - - let mut buf = Vec::new(); - let mut encoder = ManifestEncoder::new(&mut buf, MANIFEST_SBOR_V1_MAX_DEPTH); - encoder - .write_payload_prefix(MANIFEST_SBOR_V1_PAYLOAD_PREFIX) - .unwrap(); - encoder.write_value_kind(ManifestValueKind::Tuple).unwrap(); - encoder.write_size(args.len()).unwrap(); - for arg in args { - manifest_builder = arg.encode( - self.test_engine, - manifest_builder, - &mut encoder, - *self.caller.address(), - ); - } + let manifest_builder = self.manifest_builder; + + let (manifest_builder, values) = args.into_iter().fold( + (manifest_builder, Vec::new()), + |(manifest_builder, mut values), arg| { + let (manifest_builder, encoded) = + arg.to_value(self.test_engine, manifest_builder, *self.caller.address()); + values.push(encoded); + (manifest_builder, values) + }, + ); - let value = manifest_decode(&buf).unwrap(); - let manifest_arg = ManifestArgs::new_from_tuple_or_panic(value); + let manifest_arg = ManifestArgs::new_from_tuple_or_panic(Value::Tuple { fields: values }); let manifest_builder = manifest_builder.call_function( package_address, @@ -401,7 +383,7 @@ impl<'a> CallBuilder<'a> { } fn write_lock(&mut self) { - let manifest = &mut self.manifest_data.as_mut().unwrap().transaction_manifest; + let manifest = &mut self.transaction_manifest.as_mut().unwrap(); manifest.instructions.insert( 0, @@ -414,7 +396,7 @@ impl<'a> CallBuilder<'a> { } fn write_deposit(&mut self) { - let manifest = &mut self.manifest_data.as_mut().unwrap().transaction_manifest; + let manifest = &mut self.transaction_manifest.as_mut().unwrap(); manifest .instructions @@ -425,7 +407,7 @@ impl<'a> CallBuilder<'a> { })); } fn write_badge(&mut self) { - let manifest = &mut self.manifest_data.as_mut().unwrap().transaction_manifest; + let manifest = &mut self.transaction_manifest.as_mut().unwrap(); for (badge, opt_ids) in &self.admin_badge { if badge.is_fungible() { manifest.instructions.insert( @@ -450,14 +432,13 @@ impl<'a> CallBuilder<'a> { } fn output_manifest(&mut self) { - let manifest = &self.manifest_data.as_mut().unwrap().transaction_manifest; - // let a = manifest.transaction_manifest.clone(); + let manifest = self.transaction_manifest.as_mut().unwrap(); + match &self.output_manifest { None => {} Some((path, name)) => { match dump_manifest_to_file_system( - manifest, //.object_names.clone(), - // &manifest.transaction_manifest, + manifest, path, Some(name), &self.test_engine.network(), @@ -492,11 +473,7 @@ impl<'a> CallBuilder<'a> { } impl SimpleMethodCaller for CallBuilder<'_> { - fn call_method( - self, - method_name: &str, - args: Vec>, - ) -> TransactionReceipt { + fn call_method(self, method_name: &str, args: Vec>) -> TransactionReceipt { let component = *self.test_engine.current_component(); self.call_method_internal(component, method_name, args) .execute() @@ -506,7 +483,7 @@ impl SimpleMethodCaller for CallBuilder<'_> { self, entity_name: G, method_name: &str, - args: Vec>, + args: Vec>, ) -> TransactionReceipt { let component = entity_name.address(self.test_engine); self.call_method_internal(component, method_name, args) @@ -517,7 +494,7 @@ impl SimpleMethodCaller for CallBuilder<'_> { self, method_name: &str, admin_badge: R, - args: Vec>, + args: Vec>, ) -> TransactionReceipt { let component = *self.test_engine.current_component(); self.call_method_internal(component, method_name, args) diff --git a/test-engine/src/engine_interface.rs b/test-engine/src/engine_interface.rs index 237fbae..0683380 100644 --- a/test-engine/src/engine_interface.rs +++ b/test-engine/src/engine_interface.rs @@ -11,7 +11,8 @@ pub struct EngineInterface { impl EngineInterface { pub fn new() -> Self { let test_runner_builder = LedgerSimulatorBuilder::new() - .with_custom_genesis(BabylonSettings::test_default()) + // .with_custom_genesis(BabylonSettings::test_default()) + // .with_custom_protocol(|builder| builder.only_babylon()) .without_kernel_trace() .build(); @@ -20,10 +21,11 @@ impl EngineInterface { } } - pub fn new_with_custom_genesis(genesis: BabylonSettings) -> Self { + pub fn new_with_custom_genesis(_genesis: BabylonSettings) -> Self { let test_runner_builder = LedgerSimulatorBuilder::new() - .with_custom_genesis(genesis) - .without_kernel_trace() + // .with_custom_genesis(genesis) + // .with_custom_protocol(|builder| builder.only_babylon()) + //.without_kernel_trace() .build(); Self { simulator: test_runner_builder, diff --git a/test-engine/src/environment.rs b/test-engine/src/environment.rs index 1aa7651..a85acbd 100644 --- a/test-engine/src/environment.rs +++ b/test-engine/src/environment.rs @@ -1,30 +1,53 @@ use crate::internal_prelude::*; +use crate::prelude::{ComponentReference, TestEngine}; use crate::references::{ReferenceName, ResourceReference}; -use crate::test_engine::TestEngine; use std::vec::Vec; -pub trait ToEncode { - fn to_encode<'a>( +pub trait ToValue { + fn to_value<'a>( &self, test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, caller: ComponentAddress, - ) -> ( - ManifestBuilder, - Box>>, - ); + ) -> (ManifestBuilder, ManifestValue); } -pub trait EnvironmentEncode { - fn encode( - &self, - test_engine: &mut TestEngine, - manifest_builder: ManifestBuilder, - encoder: &mut ManifestEncoder, - caller: ComponentAddress, - ) -> ManifestBuilder; +macro_rules! env_to_value_impl { + ($name:ident, $getter:ident) => { + impl ToValue for $name { + fn to_value<'a>( + &self, + test_engine: &mut TestEngine, + manifest_builder: ManifestBuilder, + _caller: ComponentAddress, + ) -> (ManifestBuilder, ManifestValue) { + let address = test_engine.$getter(self.0.clone()); + ( + manifest_builder, + Value::Custom { + value: ManifestCustomValue::Address((address.clone()).into()), + }, + ) + } + } + }; } +#[derive(Clone, Debug)] +pub struct EnvResource(pub N); +env_to_value_impl!(EnvResource, get_resource); + +#[derive(Clone, Debug)] +pub struct EnvAccount(pub N); +env_to_value_impl!(EnvAccount, get_account); + +#[derive(Clone, Debug)] +pub struct EnvComponent(pub N); +env_to_value_impl!(EnvComponent, get_component); + +pub struct EnvPackage(pub N); +env_to_value_impl!(EnvPackage, get_package); + pub enum Environment { Account(N), Component(N), @@ -32,53 +55,34 @@ pub enum Environment { Resource(N), } -impl ToEncode for Environment { - fn to_encode<'a>( +impl ToValue for Environment { + fn to_value<'a>( &self, test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, _caller: ComponentAddress, - ) -> ( - ManifestBuilder, - Box>>, - ) { - match self { + ) -> (ManifestBuilder, ManifestValue) { + let value = match self { Environment::Resource(resource) => { - let resource_address = test_engine.get_resource(resource.clone()); - (manifest_builder, Box::new(resource_address)) + ManifestCustomValue::Address(test_engine.get_resource(resource.clone()).into()) } Environment::Account(address) => { - let account = *test_engine.get_account(address.clone()); - (manifest_builder, Box::new(account)) + ManifestCustomValue::Address((*test_engine.get_account(address.clone())).into()) } Environment::Component(address) => { - let component = test_engine.get_component(address.clone()); - (manifest_builder, Box::new(component)) + ManifestCustomValue::Address(test_engine.get_component(address.clone()).into()) } Environment::Package(address) => { - let package = test_engine.get_package(address.clone()); - (manifest_builder, Box::new(package)) + ManifestCustomValue::Address(test_engine.get_package(address.clone()).into()) } - } - } -} + }; -impl EnvironmentEncode for Environment { - fn encode( - &self, - test_engine: &mut TestEngine, - manifest_builder: ManifestBuilder, - encoder: &mut ManifestEncoder, - caller: ComponentAddress, - ) -> ManifestBuilder { - let (manifest_builder, encoded) = self.to_encode(test_engine, manifest_builder, caller); - encoder.encode(encoded.as_ref()).expect("Could not encode"); - manifest_builder + (manifest_builder, Value::Custom { value }) } } // Fungible - +#[derive(Clone, Debug)] pub enum Fungible { FromAccount(R, Decimal), FromWorkTop(R, Decimal), @@ -86,16 +90,13 @@ pub enum Fungible { AllFromWorktop(R), } -impl ToEncode for Fungible { - fn to_encode<'a>( +impl Fungible { + pub fn to_manifest_bucket<'a>( &self, test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, caller: ComponentAddress, - ) -> ( - ManifestBuilder, - Box>>, - ) { + ) -> (ManifestBuilder, ManifestBucket) { match self { Fungible::FromAccount(resource, amount) => { let resource_address = resource.address(test_engine); @@ -112,7 +113,7 @@ impl ToEncode for Fungible { amount, }), ); - (manifest_builder, Box::new(bucket.new_bucket.unwrap())) + (manifest_builder, bucket.new_bucket.unwrap()) } Fungible::FromWorkTop(resource, amount) => { let resource_address = resource.address(test_engine); @@ -124,7 +125,7 @@ impl ToEncode for Fungible { amount, }), ); - (manifest_builder, Box::new(bucket.new_bucket.unwrap())) + (manifest_builder, bucket.new_bucket.unwrap()) } Fungible::AllFromAccount(resource) => { let amount_owned = test_engine.current_balance(resource.clone()); @@ -141,7 +142,7 @@ impl ToEncode for Fungible { amount: amount_owned, }), ); - (manifest_builder, Box::new(bucket.new_bucket.unwrap())) + (manifest_builder, bucket.new_bucket.unwrap()) } Fungible::AllFromWorktop(resource) => { let resource_address = resource.address(test_engine); @@ -149,23 +150,27 @@ impl ToEncode for Fungible { let (manifest_builder, bucket) = manifest_builder.add_instruction_advanced( InstructionV1::TakeAllFromWorktop(TakeAllFromWorktop { resource_address }), ); - (manifest_builder, Box::new(bucket.new_bucket.unwrap())) + (manifest_builder, bucket.new_bucket.unwrap()) } } } } -impl EnvironmentEncode for Fungible { - fn encode( +impl ToValue for Fungible { + fn to_value<'a>( &self, test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, - encoder: &mut ManifestEncoder, caller: ComponentAddress, - ) -> ManifestBuilder { - let (manifest_builder, encoded) = self.to_encode(test_engine, manifest_builder, caller); - encoder.encode(encoded.as_ref()).expect("Could not encode"); - manifest_builder + ) -> (ManifestBuilder, ManifestValue) { + let manifest_bucket = self.to_manifest_bucket(test_engine, manifest_builder, caller); + + ( + manifest_bucket.0, + Value::Custom { + value: ManifestCustomValue::Bucket(manifest_bucket.1), + }, + ) } } @@ -178,16 +183,13 @@ pub enum NonFungible { AllFromWorktop(R), } -impl ToEncode for NonFungible { - fn to_encode<'a>( +impl NonFungible { + fn to_manifest_bucket<'a>( &self, test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, caller: ComponentAddress, - ) -> ( - ManifestBuilder, - Box>>, - ) { + ) -> (ManifestBuilder, ManifestBucket) { match self { NonFungible::FromAccount(resource, ids) => { let resource_address = resource.address(test_engine); @@ -203,7 +205,7 @@ impl ToEncode for NonFungible { ids: ids.clone(), }), ); - (manifest_builder, Box::new(bucket.new_bucket.unwrap())) + (manifest_builder, bucket.new_bucket.unwrap()) } NonFungible::FromWorktop(resource, ids) => { let resource_address = resource.address(test_engine); @@ -213,7 +215,7 @@ impl ToEncode for NonFungible { ids: ids.clone(), }), ); - (manifest_builder, Box::new(bucket.new_bucket.unwrap())) + (manifest_builder, bucket.new_bucket.unwrap()) } NonFungible::AllFromAccount(resource) => { @@ -231,7 +233,7 @@ impl ToEncode for NonFungible { ids: ids_owned, }), ); - (manifest_builder, Box::new(bucket.new_bucket.unwrap())) + (manifest_builder, bucket.new_bucket.unwrap()) } NonFungible::AllFromWorktop(resource) => { let resource_address = resource.address(test_engine); @@ -239,23 +241,27 @@ impl ToEncode for NonFungible { let (manifest_builder, bucket) = manifest_builder.add_instruction_advanced( InstructionV1::TakeAllFromWorktop(TakeAllFromWorktop { resource_address }), ); - (manifest_builder, Box::new(bucket.new_bucket.unwrap())) + (manifest_builder, bucket.new_bucket.unwrap()) } } } } -impl EnvironmentEncode for NonFungible { - fn encode( +impl ToValue for NonFungible { + fn to_value<'a>( &self, test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, - encoder: &mut ManifestEncoder, caller: ComponentAddress, - ) -> ManifestBuilder { - let (manifest_builder, encoded) = self.to_encode(test_engine, manifest_builder, caller); - encoder.encode(encoded.as_ref()).expect("Could not encode"); - manifest_builder + ) -> (ManifestBuilder, ManifestValue) { + let manifest_bucket = self.to_manifest_bucket(test_engine, manifest_builder, caller); + + ( + manifest_bucket.0, + Value::Custom { + value: ManifestCustomValue::Bucket(manifest_bucket.1), + }, + ) } } @@ -268,17 +274,14 @@ pub enum ProofOf { NonFungibleFromAuthZone(R, Vec), } -impl ToEncode for ProofOf { - fn to_encode<'a>( +impl ToValue for ProofOf { + fn to_value<'a>( &self, test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, caller: ComponentAddress, - ) -> ( - ManifestBuilder, - Box>>, - ) { - match self { + ) -> (ManifestBuilder, ManifestValue) { + let (manifest_builder, proof) = match self { ProofOf::FungibleFromAccount(resource, amount) => { let resource_address = resource.address(test_engine); let amount = *amount; @@ -289,24 +292,22 @@ impl ToEncode for ProofOf { manifest_args!(resource_address, amount), ); - let (manifest_builder, proof) = manifest_builder - .add_instruction_advanced(InstructionV1::PopFromAuthZone(PopFromAuthZone)); - - (manifest_builder, Box::new(proof.new_proof.unwrap())) + manifest_builder + .add_instruction_advanced(InstructionV1::PopFromAuthZone(PopFromAuthZone)) } + ProofOf::FungibleFromAuthZone(resource, amount) => { let resource_address = resource.address(test_engine); let amount = *amount; - let (manifest_builder, proof) = manifest_builder.add_instruction_advanced( + manifest_builder.add_instruction_advanced( InstructionV1::CreateProofFromAuthZoneOfAmount( CreateProofFromAuthZoneOfAmount { resource_address, amount, }, ), - ); - (manifest_builder, Box::new(proof.new_proof.unwrap())) + ) } ProofOf::NonFungibleFromAccount(resource, ids) => { let resource_address = resource.address(test_engine); @@ -316,153 +317,270 @@ impl ToEncode for ProofOf { manifest_args!(resource_address, ids.clone()), ); - let (manifest_builder, proof) = manifest_builder - .add_instruction_advanced(InstructionV1::PopFromAuthZone(PopFromAuthZone)); - - (manifest_builder, Box::new(proof.new_proof.unwrap())) + manifest_builder + .add_instruction_advanced(InstructionV1::PopFromAuthZone(PopFromAuthZone)) } ProofOf::NonFungibleFromAuthZone(resource, ids) => { let resource_address = resource.address(test_engine); - let (manifest_builder, proof) = manifest_builder.add_instruction_advanced( + manifest_builder.add_instruction_advanced( InstructionV1::CreateProofFromAuthZoneOfNonFungibles( CreateProofFromAuthZoneOfNonFungibles { resource_address, ids: ids.clone(), }, ), - ); - (manifest_builder, Box::new(proof.new_proof.unwrap())) + ) } - } - } -} - -impl EnvironmentEncode for ProofOf { - fn encode( - &self, - test_engine: &mut TestEngine, - manifest_builder: ManifestBuilder, - encoder: &mut ManifestEncoder, - caller: ComponentAddress, - ) -> ManifestBuilder { - let (manifest_builder, encoded) = self.to_encode(test_engine, manifest_builder, caller); - encoder.encode(encoded.as_ref()).expect("Could not encode"); - manifest_builder + }; + + ( + manifest_builder, + Value::Custom { + value: ManifestCustomValue::Proof(proof.new_proof.unwrap()), + }, + ) } } // Env Vec pub struct EnvVec { - elements: Vec>, + value_kind: ManifestValueKind, + elements: Vec>, } impl EnvVec { - pub fn from_vec(elements: Vec>) -> Self { - Self { elements } + pub fn from_vec(elements: Vec>, value_kind: ManifestValueKind) -> Self { + Self { + elements, + value_kind, + } } - pub fn new() -> Self { + pub fn new(value_kind: ManifestValueKind) -> Self { Self { elements: Vec::new(), + value_kind, } } pub fn extend(&mut self, elements: EnvVec) { self.elements.extend(elements.elements); } + + pub fn push(&mut self, element: Box) { + self.elements.push(element); + } + + pub fn pop(&mut self) -> Option> { + self.elements.pop() + } } impl Iterator for EnvVec { - type Item = Box; + type Item = Box; fn next(&mut self) -> Option { self.elements.pop() } } -impl EnvironmentEncode for EnvVec { - fn encode( +impl ToValue for EnvVec { + fn to_value<'a>( &self, test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, - encoder: &mut ManifestEncoder, caller: ComponentAddress, - ) -> ManifestBuilder { - let mut manifest_builder = manifest_builder; - - encoder.write_value_kind(ValueKind::Array).expect(""); - let size = self.elements.len(); - let mut encoded = Vec::new(); - for elem in &self.elements { - let (mb, encode) = elem.to_encode(test_engine, manifest_builder, caller); - manifest_builder = mb; - encoded.push(encode); - } - - let mut encoded = encoded.iter(); - match encoded.next() { - None => { - encoder - .write_value_kind(ManifestCustomValueKind::Bucket.into()) - .unwrap(); - encoder.write_size(size).expect(""); + ) -> (ManifestBuilder, ManifestValue) { + let (manifest_builder, vec) = self.elements.iter().fold( + (manifest_builder, Vec::new()), + |(manifest_builder, mut vec), element| { + let (manifest_builder, element_value) = + element.to_value(test_engine, manifest_builder, caller); + vec.push(element_value); + (manifest_builder, vec) + }, + ); + + let value_kind = if let Some(first_value) = vec.first() { + match first_value { + Value::Bool { .. } => ValueKind::Bool, + Value::I8 { .. } => ValueKind::I8, + Value::I16 { .. } => ValueKind::I16, + Value::I32 { .. } => ValueKind::I32, + Value::I64 { .. } => ValueKind::I64, + Value::I128 { .. } => ValueKind::I128, + Value::U8 { .. } => ValueKind::U8, + Value::U16 { .. } => ValueKind::U16, + Value::U32 { .. } => ValueKind::U32, + Value::U64 { .. } => ValueKind::U64, + Value::U128 { .. } => ValueKind::U128, + Value::String { .. } => ValueKind::String, + Value::Enum { .. } => ValueKind::Enum, + Value::Array { .. } => ValueKind::Array, + Value::Tuple { .. } => ValueKind::Tuple, + Value::Map { .. } => ValueKind::Map, + Value::Custom { value } => ValueKind::Custom(value.get_custom_value_kind()), } - Some(elem) => { - let encode = elem.as_ref(); - encode.encode_value_kind(encoder).expect("Error"); - encoder.write_size(size).expect(""); - encoder.encode_deeper_body(encode).expect(""); - } - } + } else { + self.value_kind + }; + + let value = Value::Array { + element_value_kind: value_kind, + elements: vec, + }; + + (manifest_builder, value) + } +} + +// Env Tuple + +pub struct EnvTuple { + elements: Vec>, +} + +impl EnvTuple { + pub fn from_vec(elements: Vec>) -> Self { + Self { elements } + } - for elem in encoded { - encoder.encode_deeper_body(elem.as_ref()).expect("OK"); + pub fn new() -> Self { + Self { + elements: Vec::new(), } - manifest_builder + } + + pub fn extend(&mut self, elements: EnvVec) { + self.elements.extend(elements.elements); } } -pub struct EnvSome { - element: Box, +// Env map + +// Env Tuple + +pub struct EnvMap { + key_kind: ManifestValueKind, + value_kind: ManifestValueKind, + elements: Vec<(Box, Box)>, } -impl EnvSome { - pub fn new(element: Box) -> Self { - Self { element } +impl EnvMap { + pub fn from_vec( + key_kind: ManifestValueKind, + value_kind: ManifestValueKind, + elements: Vec<(Box, Box)>, + ) -> Self { + Self { + key_kind, + value_kind, + elements, + } + } + + pub fn new(key_kind: ManifestValueKind, value_kind: ManifestValueKind) -> Self { + Self { + key_kind, + value_kind, + elements: Vec::new(), + } + } + + pub fn extend(&mut self, elements: EnvMap) { + self.elements.extend(elements.elements); } } -impl EnvironmentEncode for EnvSome { - fn encode( +impl ToValue for EnvMap { + fn to_value( &self, test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, - encoder: &mut ManifestEncoder, caller: ComponentAddress, - ) -> ManifestBuilder { - let (mb, encode) = self - .element - .to_encode(test_engine, manifest_builder, caller); + ) -> (ManifestBuilder, ManifestValue) { + let (manifest_builder, entries) = self.elements.iter().fold( + (manifest_builder, Vec::new()), + |(manifest_builder, mut entries), (key, value)| { + let (manifest_builder, key_value) = + key.to_value(test_engine, manifest_builder, caller); + let (manifest_builder, value_value) = + value.to_value(test_engine, manifest_builder, caller); + entries.push((key_value, value_value)); + (manifest_builder, entries) + }, + ); + + let value = Value::Map { + key_value_kind: self.key_kind, + value_value_kind: self.value_kind, + entries, + }; + + (manifest_builder, value) + } +} - encoder.write_value_kind(ValueKind::Enum).expect(""); - encoder.write_discriminator(OPTION_VARIANT_SOME).expect(""); - encoder.write_size(1).expect(""); - encoder.encode(encode.as_ref()).expect(""); +// Env Option - mb +pub enum EnvOption { + None, + Some(Box), +} + +impl ToValue for EnvOption { + fn to_value( + &self, + test_engine: &mut TestEngine, + manifest_builder: ManifestBuilder, + caller: ComponentAddress, + ) -> (ManifestBuilder, ManifestValue) { + let (manifest_builder, value) = match self { + EnvOption::Some(element) => { + let (manifest_builder, inner_value) = + element.to_value(test_engine, manifest_builder, caller); + + ( + manifest_builder, + Value::Enum { + discriminator: 1, + fields: vec![inner_value], + }, + ) + } + EnvOption::None => ( + manifest_builder, + Value::Enum { + discriminator: 0, + fields: vec![], + }, + ), + }; + + (manifest_builder, value) } } -impl Encode>> EnvironmentEncode for T { - fn encode( +// Other encoding types + +impl Encode> + ?Sized> ToValue for T { + fn to_value( &self, _test_engine: &mut TestEngine, manifest_builder: ManifestBuilder, - encoder: &mut ManifestEncoder, _caller: ComponentAddress, - ) -> ManifestBuilder { + ) -> (ManifestBuilder, ManifestValue) { + let mut buf = sbor::rust::vec::Vec::new(); + let mut encoder = ManifestEncoder::new(&mut buf, MANIFEST_SBOR_V1_MAX_DEPTH); + encoder + .write_payload_prefix(MANIFEST_SBOR_V1_PAYLOAD_PREFIX) + .unwrap(); + encoder.encode(&self).unwrap(); - manifest_builder + + let value = manifest_decode(&buf).unwrap(); + + (manifest_builder, value) } } diff --git a/test-engine/src/from_instruction.rs b/test-engine/src/from_instruction.rs deleted file mode 100644 index 8b607de..0000000 --- a/test-engine/src/from_instruction.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::internal_prelude::*; - -pub trait FromInstruction { - fn from(instructions: Vec) -> Self; -} - -impl FromInstruction for T { - fn from(mut instructions: Vec) -> Self { - instructions.pop(); - let bytes = match instructions.pop().unwrap() { - InstructionOutput::None => { - panic!("The method does not return anything") - } - InstructionOutput::CallReturn(bytes) => bytes, - }; - scrypto_decode::(&bytes).expect("Could not parse method return into given type 2") - } -} diff --git a/test-engine/src/lib.rs b/test-engine/src/lib.rs index 35de8dc..eadf94f 100644 --- a/test-engine/src/lib.rs +++ b/test-engine/src/lib.rs @@ -1,6 +1,5 @@ mod account; mod engine_interface; -mod from_instruction; mod references; mod call_builder; @@ -9,7 +8,7 @@ mod internal_prelude; mod macros; mod method_call; pub mod prelude; -pub(crate) mod receipt_traits; +pub mod receipt_traits; mod test_engine; mod to_id; mod utils; diff --git a/test-engine/src/macros.rs b/test-engine/src/macros.rs index 7127a9a..104a7b7 100644 --- a/test-engine/src/macros.rs +++ b/test-engine/src/macros.rs @@ -7,12 +7,13 @@ macro_rules! env_args { ($( $x:expr ),*) => {{ use test_engine::prelude::*; - let mut temp_vec: Vec> = vec![]; + let mut temp_vec: Vec> = vec![]; $( temp_vec.push(Box::new($x)); )* temp_vec }}; + } #[macro_export] @@ -21,6 +22,23 @@ macro_rules! env_vec { vec![] ); + ($( $x:expr ),*) => {{ + use test_engine::prelude::*; + + let mut temp_vec: Vec> = vec![]; + $( + temp_vec.push(Box::new($x)); + )* + EnvVec::from_vec(temp_vec,ManifestCustomValueKind::Bucket.into()) + }}; +} + +#[macro_export] +macro_rules! env_tuple{ + () => ( + vec![] + ); + ($( $x:expr ),*) => {{ use test_engine::prelude::*; @@ -28,7 +46,7 @@ macro_rules! env_vec { $( temp_vec.push(Box::new($x)); )* - EnvVec::from_vec(temp_vec) + EnvTuple::from_vec(temp_vec) }}; } @@ -65,14 +83,14 @@ macro_rules! nf_ids { macro_rules! some { ($x:expr) => {{ use test_engine::prelude::*; - EnvSome::new(Box::new($x)) + EnvOption::Some(Box::new($x)) }}; } #[macro_export] macro_rules! none { () => { - None:: + EnvOption::None }; } diff --git a/test-engine/src/method_call.rs b/test-engine/src/method_call.rs index bdd7334..a75a81c 100644 --- a/test-engine/src/method_call.rs +++ b/test-engine/src/method_call.rs @@ -1,6 +1,6 @@ use crate::call_builder::CallBuilder; -use crate::environment::EnvironmentEncode; use crate::internal_prelude::*; +use crate::prelude::ToValue; use crate::references::{GlobalReference, ResourceReference}; pub trait SimpleMethodCaller { @@ -9,11 +9,7 @@ pub trait SimpleMethodCaller { /// # Arguments /// * `method_name`: name of the method. /// * `args`: environment arguments to call the method. - fn call_method( - self, - method_name: &str, - args: Vec>, - ) -> TransactionReceipt; + fn call_method(self, method_name: &str, args: Vec>) -> TransactionReceipt; /// Makes a simple call to a method of a given entity. /// @@ -25,7 +21,7 @@ pub trait SimpleMethodCaller { self, global_address: G, method_name: &str, - args: Vec>, + args: Vec>, ) -> TransactionReceipt; /// Calls a method of the current component with a given admin badge. @@ -38,7 +34,7 @@ pub trait SimpleMethodCaller { self, method_name: &str, admin_badge: R, - args: Vec>, + args: Vec>, ) -> TransactionReceipt; } @@ -51,7 +47,7 @@ pub trait ComplexMethodCaller { /// # Arguments /// * `method_name`: name of the method. /// * `args`: environment arguments to call the method. - fn call(&mut self, method_name: &str, args: Vec>) -> CallBuilder; + fn call(&mut self, method_name: &str, args: Vec>) -> CallBuilder; /// Returns a call builder with an initial method call with a given admin badge. /// @@ -63,7 +59,7 @@ pub trait ComplexMethodCaller { &mut self, method_name: &str, admin_badge: R, - args: Vec>, + args: Vec>, ) -> CallBuilder; /// Returns a call builder with an initial method call to a given entity. @@ -76,7 +72,7 @@ pub trait ComplexMethodCaller { &mut self, global_address: G, method_name: &str, - args: Vec>, + args: Vec>, ) -> CallBuilder; fn with_manifest_builder(&mut self, f: F) -> CallBuilder diff --git a/test-engine/src/prelude.rs b/test-engine/src/prelude.rs index c5f7110..426ed30 100644 --- a/test-engine/src/prelude.rs +++ b/test-engine/src/prelude.rs @@ -9,6 +9,7 @@ pub use crate::call_builder::*; pub use crate::environment::*; pub use crate::method_call::*; pub use crate::receipt_traits::*; +pub use crate::references::*; pub use crate::test_engine::*; pub use crate::to_id::ToId; pub use crate::utils::*; diff --git a/test-engine/src/receipt_traits.rs b/test-engine/src/receipt_traits.rs index 60dca83..a7b6e5d 100644 --- a/test-engine/src/receipt_traits.rs +++ b/test-engine/src/receipt_traits.rs @@ -1,8 +1,8 @@ -use crate::from_instruction::FromInstruction; use crate::internal_prelude::*; pub trait Outcome { fn assert_is_success(self) -> Self; + fn assert_failed(self) -> Self; fn assert_failed_with(self, error: &str) -> Self; } @@ -26,6 +26,23 @@ impl Outcome for TransactionReceipt { } } + fn assert_failed(self) -> Self { + match &self.result { + TransactionResult::Commit(commit) => match &commit.outcome { + TransactionOutcome::Success(_) => { + panic!("Transaction succeeded !"); + } + TransactionOutcome::Failure(_) => self, + }, + TransactionResult::Reject(reject) => { + panic!("Transaction rejected with: {:?}", reject.reason); + } + TransactionResult::Abort(abort) => { + panic!("Transaction aborted with: {}", abort.reason); + } + } + } + /// Asserts that the transaction failed with a given message. /// Panics if the transaction succeeded or was rejected/aborted. /// @@ -60,19 +77,22 @@ impl Outcome for TransactionReceipt { } } -pub trait GetReturn { - fn get_return(&self) -> T; +pub trait GetReturn { + fn get_return(&self, index: usize) -> T; } -impl GetReturn for TransactionReceipt -where - T: FromInstruction, -{ +impl GetReturn for TransactionReceipt { /// Returns the method's return from a receipt. - fn get_return(&self) -> T { + fn get_return(&self, index: usize) -> T { match &self.result { TransactionResult::Commit(commit) => match &commit.outcome { - TransactionOutcome::Success(output) => T::from(output.clone()), + TransactionOutcome::Success(output) => T::from( + output + .get(index) + .expect(&format!("No return at index {}", index)) + .clone(), + ), + TransactionOutcome::Failure(failure) => { panic!("Transaction failed with: {:?}", failure); } @@ -86,3 +106,19 @@ where } } } + +pub trait FromInstruction { + fn from(instructions: InstructionOutput) -> Self; +} + +impl FromInstruction for T { + fn from(instructions: InstructionOutput) -> Self { + let bytes = match instructions { + InstructionOutput::None => { + panic!("The method does not return anything") + } + InstructionOutput::CallReturn(bytes) => bytes, + }; + scrypto_decode::(&bytes).expect("Could not parse method return into given type 2") + } +} diff --git a/test-engine/src/test_engine.rs b/test-engine/src/test_engine.rs index 4302d9b..5ecb768 100644 --- a/test-engine/src/test_engine.rs +++ b/test-engine/src/test_engine.rs @@ -1,10 +1,10 @@ use crate::account::Account; use crate::call_builder::CallBuilder; use crate::engine_interface::EngineInterface; -use crate::environment::EnvironmentEncode; use crate::method_call::{ComplexMethodCaller, SimpleMethodCaller}; +use crate::prelude::{ComponentReference, ToValue}; use crate::receipt_traits::Outcome; -use crate::references::{ComponentReference, GlobalReference, ReferenceName, ResourceReference}; +use crate::references::{GlobalReference, ReferenceName, ResourceReference}; use crate::to_id::ToId; use scrypto_test::prelude::*; use std::collections::hash_map::Entry; @@ -158,7 +158,7 @@ impl TestEngine { component_name: N, blueprint_name: &str, instantiation_function: &str, - args: Vec>, + args: Vec>, ) -> TransactionReceipt { self.create_component( component_name, @@ -183,7 +183,7 @@ impl TestEngine { blueprint_name: &str, instantiation_function: &str, badge: R, - args: Vec>, + args: Vec>, ) -> TransactionReceipt { self.create_component( component_name, @@ -207,7 +207,7 @@ impl TestEngine { component_name: N, blueprint_name: &str, instantiation_function: &str, - args: Vec>, + args: Vec>, callback: impl FnOnce(CallBuilder) -> CallBuilder, ) -> TransactionReceipt { self.create_component( @@ -612,11 +612,11 @@ impl TestEngine { resource: R1, id: T, field_name: &str, - mut data: Vec>, + mut data: Vec>, badge: R2, ) -> TransactionReceipt { let resource = resource.address(self); - let mut args: Vec> = + let mut args: Vec> = vec![Box::new(id.to_id()), Box::new(field_name.to_string())]; args.append(&mut data); CallBuilder::new(self) @@ -821,7 +821,7 @@ impl TestEngine { component_name: N, blueprint_name: &str, instantiation_function: &str, - args: Vec>, + args: Vec>, callback: impl FnOnce(CallBuilder) -> CallBuilder, ) -> TransactionReceipt { // let caller = self.current_account().clone(); @@ -940,11 +940,7 @@ impl Default for TestEngine { } impl<'a> SimpleMethodCaller for &'a mut TestEngine { - fn call_method( - self, - method_name: &str, - args: Vec>, - ) -> TransactionReceipt { + fn call_method(self, method_name: &str, args: Vec>) -> TransactionReceipt { let component = *self.current_component(); self.call_method_from(component, method_name, args) } @@ -953,7 +949,7 @@ impl<'a> SimpleMethodCaller for &'a mut TestEngine { self, global_address: G, method_name: &str, - args: Vec>, + args: Vec>, ) -> TransactionReceipt { self.call_from(global_address, method_name, args).execute() } @@ -962,7 +958,7 @@ impl<'a> SimpleMethodCaller for &'a mut TestEngine { self, method_name: &str, admin_badge: R, - args: Vec>, + args: Vec>, ) -> TransactionReceipt { self.call(method_name, args) .with_badge(admin_badge) @@ -975,7 +971,7 @@ impl ComplexMethodCaller for TestEngine { CallBuilder::new(self) } - fn call(&mut self, method_name: &str, args: Vec>) -> CallBuilder { + fn call(&mut self, method_name: &str, args: Vec>) -> CallBuilder { let component = *self.current_component(); self.call_from(component, method_name, args) } @@ -983,7 +979,7 @@ impl ComplexMethodCaller for TestEngine { &mut self, method_name: &str, admin_badge: R, - args: Vec>, + args: Vec>, ) -> CallBuilder { let component = *self.current_component(); self.call_from(component, method_name, args) @@ -994,7 +990,7 @@ impl ComplexMethodCaller for TestEngine { &mut self, global_address: G, method_name: &str, - args: Vec>, + args: Vec>, ) -> CallBuilder { let address = global_address.address(self); CallBuilder::new(self).call_method_internal(address, method_name, args) diff --git a/test-engine/tests/general/mod.rs b/test-engine/tests/general/mod.rs index ce3ffff..ac9b4ad 100644 --- a/test-engine/tests/general/mod.rs +++ b/test-engine/tests/general/mod.rs @@ -32,16 +32,18 @@ fn test_transfer() { test_engine .transfer("Recipient", "Test token", dec!(10)) .assert_is_success(); + assert_eq!(test_engine.balance_of("Recipient", "Test token"), dec!(10)); } #[test] fn test_bug() { let mut simulator = LedgerSimulatorBuilder::new() - .with_custom_genesis(BabylonSettings::test_default( - // Epoch::of(1), - // BabylonSettings::default_consensus_manager_config(), - )) + // .with_custom_genesis(BabylonSettings::test_default( + // Epoch::of(1), + // BabylonSettings::default_consensus_manager_config(), + // )) + .with_custom_protocol(|builder| builder.only_babylon()) .without_kernel_trace() .build(); diff --git a/test-engine/tests/gumball_machine/unit_tests.rs b/test-engine/tests/gumball_machine/unit_tests.rs index 9d20dd6..adfe495 100644 --- a/test-engine/tests/gumball_machine/unit_tests.rs +++ b/test-engine/tests/gumball_machine/unit_tests.rs @@ -43,7 +43,7 @@ mod gumball_machine_tests { fn test_get_price() { let mut test_engine = instantiate_gumball(); let receipt = test_engine.call_method("get_price", env_args!()); - let price: Decimal = receipt.get_return(); + let price: Decimal = receipt.get_return(1); assert_eq!(price, dec!(5)); } } From 68ad39e7848d0146494feafb25cae65c3437da1b Mon Sep 17 00:00:00 2001 From: atoumbre Date: Mon, 21 Apr 2025 12:02:47 +0000 Subject: [PATCH 5/7] env_vec macro update --- test-engine/src/call_builder.rs | 6 +-- test-engine/src/environment.rs | 74 +++++++++++++++++++++------------ test-engine/src/lib.rs | 5 ++- test-engine/src/macros.rs | 53 +++++++++++------------ test-engine/src/method_call.rs | 18 ++++---- test-engine/src/test_engine.rs | 4 +- 6 files changed, 91 insertions(+), 69 deletions(-) diff --git a/test-engine/src/call_builder.rs b/test-engine/src/call_builder.rs index 9b9452c..49aa919 100644 --- a/test-engine/src/call_builder.rs +++ b/test-engine/src/call_builder.rs @@ -1,9 +1,9 @@ use crate::account::Account; -use crate::environment::{Fungible, NonFungible}; +use crate::environment::{Fungible, NonFungible, ToValue}; use crate::internal_prelude::*; use crate::method_call::SimpleMethodCaller; -use crate::prelude::{ComponentReference, Outcome, ToValue}; -use crate::references::{GlobalReference, ReferenceName, ResourceReference}; +use crate::receipt_traits::Outcome; +use crate::references::{ComponentReference, GlobalReference, ReferenceName, ResourceReference}; use crate::test_engine::TestEngine; use crate::to_id::ToId; use std::collections::BTreeSet; diff --git a/test-engine/src/environment.rs b/test-engine/src/environment.rs index a85acbd..cf23c8c 100644 --- a/test-engine/src/environment.rs +++ b/test-engine/src/environment.rs @@ -1,6 +1,6 @@ use crate::internal_prelude::*; -use crate::prelude::{ComponentReference, TestEngine}; use crate::references::{ReferenceName, ResourceReference}; +use crate::test_engine::TestEngine; use std::vec::Vec; pub trait ToValue { @@ -12,6 +12,9 @@ pub trait ToValue { ) -> (ManifestBuilder, ManifestValue); } +// ! Refs + +// macro to implement ToValue of env reference types macro_rules! env_to_value_impl { ($name:ident, $getter:ident) => { impl ToValue for $name { @@ -42,7 +45,7 @@ pub struct EnvAccount(pub N); env_to_value_impl!(EnvAccount, get_account); #[derive(Clone, Debug)] -pub struct EnvComponent(pub N); +pub struct EnvComponent(pub N); env_to_value_impl!(EnvComponent, get_component); pub struct EnvPackage(pub N); @@ -81,7 +84,8 @@ impl ToValue for Environment { } } -// Fungible +// ! Fungible + #[derive(Clone, Debug)] pub enum Fungible { FromAccount(R, Decimal), @@ -119,13 +123,14 @@ impl Fungible { let resource_address = resource.address(test_engine); let amount = *amount; - let (manifest_builder, bucket) = manifest_builder.add_instruction_advanced( + let (manifest_builder, symbols) = manifest_builder.add_instruction_advanced( InstructionV1::TakeFromWorktop(TakeFromWorktop { resource_address, amount, }), ); - (manifest_builder, bucket.new_bucket.unwrap()) + + (manifest_builder, symbols.new_bucket.unwrap()) } Fungible::AllFromAccount(resource) => { let amount_owned = test_engine.current_balance(resource.clone()); @@ -174,7 +179,7 @@ impl ToValue for Fungible { } } -// Non Fungible +// ! Non Fungible pub enum NonFungible { FromAccount(R, Vec), @@ -265,7 +270,7 @@ impl ToValue for NonFungible { } } -// Proofs +// ! Proofs pub enum ProofOf { FungibleFromAccount(R, Decimal), @@ -342,7 +347,7 @@ impl ToValue for ProofOf { } } -// Env Vec +// ! Env Vec pub struct EnvVec { value_kind: ManifestValueKind, @@ -350,17 +355,17 @@ pub struct EnvVec { } impl EnvVec { - pub fn from_vec(elements: Vec>, value_kind: ManifestValueKind) -> Self { + pub fn from_vec(value_kind: ManifestValueKind, elements: Vec>) -> Self { Self { - elements, value_kind, + elements, } } pub fn new(value_kind: ManifestValueKind) -> Self { Self { - elements: Vec::new(), value_kind, + elements: Vec::new(), } } @@ -397,13 +402,15 @@ impl ToValue for EnvVec { |(manifest_builder, mut vec), element| { let (manifest_builder, element_value) = element.to_value(test_engine, manifest_builder, caller); + vec.push(element_value); + (manifest_builder, vec) }, ); - let value_kind = if let Some(first_value) = vec.first() { - match first_value { + let value_kind = if let Some(first) = vec.first() { + match first { Value::Bool { .. } => ValueKind::Bool, Value::I8 { .. } => ValueKind::I8, Value::I16 { .. } => ValueKind::I16, @@ -435,7 +442,7 @@ impl ToValue for EnvVec { } } -// Env Tuple +// ! Env Tuple pub struct EnvTuple { elements: Vec>, @@ -451,27 +458,44 @@ impl EnvTuple { elements: Vec::new(), } } +} - pub fn extend(&mut self, elements: EnvVec) { - self.elements.extend(elements.elements); +impl ToValue for EnvTuple { + fn to_value<'a>( + &self, + test_engine: &mut TestEngine, + manifest_builder: ManifestBuilder, + caller: ComponentAddress, + ) -> (ManifestBuilder, ManifestValue) { + let (manifest_builder, tuple) = self.elements.iter().fold( + (manifest_builder, Vec::new()), + |(manifest_builder, mut tuple), element| { + let (manifest_builder, element_value) = + element.to_value(test_engine, manifest_builder, caller); + tuple.push(element_value); + (manifest_builder, tuple) + }, + ); + + let value = Value::Tuple { fields: tuple }; + + (manifest_builder, value) } } -// Env map - -// Env Tuple +// ! Env map pub struct EnvMap { key_kind: ManifestValueKind, value_kind: ManifestValueKind, - elements: Vec<(Box, Box)>, + elements: IndexMap, Box>, } impl EnvMap { pub fn from_vec( key_kind: ManifestValueKind, value_kind: ManifestValueKind, - elements: Vec<(Box, Box)>, + elements: IndexMap, Box>, ) -> Self { Self { key_kind, @@ -484,13 +508,9 @@ impl EnvMap { Self { key_kind, value_kind, - elements: Vec::new(), + elements: IndexMap::new(), } } - - pub fn extend(&mut self, elements: EnvMap) { - self.elements.extend(elements.elements); - } } impl ToValue for EnvMap { @@ -522,7 +542,7 @@ impl ToValue for EnvMap { } } -// Env Option +// ! Env Option pub enum EnvOption { None, diff --git a/test-engine/src/lib.rs b/test-engine/src/lib.rs index eadf94f..d38bb62 100644 --- a/test-engine/src/lib.rs +++ b/test-engine/src/lib.rs @@ -7,8 +7,9 @@ mod environment; mod internal_prelude; mod macros; mod method_call; -pub mod prelude; -pub mod receipt_traits; +mod receipt_traits; mod test_engine; mod to_id; mod utils; + +pub mod prelude; diff --git a/test-engine/src/macros.rs b/test-engine/src/macros.rs index 104a7b7..3b90b8f 100644 --- a/test-engine/src/macros.rs +++ b/test-engine/src/macros.rs @@ -17,48 +17,52 @@ macro_rules! env_args { } #[macro_export] -macro_rules! env_vec { +macro_rules! env_tuple{ () => ( - vec![] + EnvTuple::new() ); ($( $x:expr ),*) => {{ use test_engine::prelude::*; - let mut temp_vec: Vec> = vec![]; + let mut temp_vec: Vec> = vec![]; $( temp_vec.push(Box::new($x)); )* - EnvVec::from_vec(temp_vec,ManifestCustomValueKind::Bucket.into()) + EnvTuple::from_vec(temp_vec) }}; } #[macro_export] -macro_rules! env_tuple{ - () => ( - vec![] - ); +macro_rules! env_vec { + (@empty $kind:expr) => {{ + use test_engine::prelude::*; + EnvVec::from_vec($kind,vec![]) + }}; - ($( $x:expr ),*) => {{ + ($x0:expr $(, $x:expr)* $(,)?) => {{ use test_engine::prelude::*; - let mut temp_vec: Vec> = vec![]; + let mut temp_vec: Vec> = vec![Box::new($x0)]; $( temp_vec.push(Box::new($x)); )* - EnvTuple::from_vec(temp_vec) + EnvVec::from_vec(ManifestValueKind::Bool, temp_vec) }}; } #[macro_export] -macro_rules! global_package { - ($name:ident, $path:expr) => { +macro_rules! some { + ($x:expr) => {{ use test_engine::prelude::*; + EnvOption::Some(Box::new($x)) + }}; +} - lazy_static! { - static ref $name: (Vec, PackageDefinition) = - { PackagePublishingSource::from($path).code_and_definition() }; - } +#[macro_export] +macro_rules! none { + () => { + EnvOption::None }; } @@ -80,17 +84,14 @@ macro_rules! nf_ids { } #[macro_export] -macro_rules! some { - ($x:expr) => {{ +macro_rules! global_package { + ($name:ident, $path:expr) => { use test_engine::prelude::*; - EnvOption::Some(Box::new($x)) - }}; -} -#[macro_export] -macro_rules! none { - () => { - EnvOption::None + lazy_static! { + static ref $name: (Vec, PackageDefinition) = + { PackagePublishingSource::from($path).code_and_definition() }; + } }; } diff --git a/test-engine/src/method_call.rs b/test-engine/src/method_call.rs index a75a81c..2fa7711 100644 --- a/test-engine/src/method_call.rs +++ b/test-engine/src/method_call.rs @@ -1,6 +1,6 @@ use crate::call_builder::CallBuilder; +use crate::environment::ToValue; use crate::internal_prelude::*; -use crate::prelude::ToValue; use crate::references::{GlobalReference, ResourceReference}; pub trait SimpleMethodCaller { @@ -49,29 +49,29 @@ pub trait ComplexMethodCaller { /// * `args`: environment arguments to call the method. fn call(&mut self, method_name: &str, args: Vec>) -> CallBuilder; - /// Returns a call builder with an initial method call with a given admin badge. + /// Returns a call builder with an initial method call to a given entity. /// /// # Arguments + /// * `global_address`: reference or address of the entity to call. /// * `method_name`: name of the method. - /// * `admin_badge`: reference name or address of the resource to use as an admin badge. /// * `args`: environment arguments to call the method. - fn call_with_badge( + fn call_from( &mut self, + global_address: G, method_name: &str, - admin_badge: R, args: Vec>, ) -> CallBuilder; - /// Returns a call builder with an initial method call to a given entity. + /// Returns a call builder with an initial method call with a given admin badge. /// /// # Arguments - /// * `global_address`: reference or address of the entity to call. /// * `method_name`: name of the method. + /// * `admin_badge`: reference name or address of the resource to use as an admin badge. /// * `args`: environment arguments to call the method. - fn call_from( + fn call_with_badge( &mut self, - global_address: G, method_name: &str, + admin_badge: R, args: Vec>, ) -> CallBuilder; diff --git a/test-engine/src/test_engine.rs b/test-engine/src/test_engine.rs index 5ecb768..eea1ee1 100644 --- a/test-engine/src/test_engine.rs +++ b/test-engine/src/test_engine.rs @@ -1,10 +1,10 @@ use crate::account::Account; use crate::call_builder::CallBuilder; use crate::engine_interface::EngineInterface; +use crate::environment::ToValue; use crate::method_call::{ComplexMethodCaller, SimpleMethodCaller}; -use crate::prelude::{ComponentReference, ToValue}; use crate::receipt_traits::Outcome; -use crate::references::{GlobalReference, ReferenceName, ResourceReference}; +use crate::references::{ComponentReference, GlobalReference, ReferenceName, ResourceReference}; use crate::to_id::ToId; use scrypto_test::prelude::*; use std::collections::hash_map::Entry; From ea9ed7dee35772c9a0b6764290e0c109b12dd4a8 Mon Sep 17 00:00:00 2001 From: atoumbre Date: Thu, 24 Apr 2025 16:32:39 +0000 Subject: [PATCH 6/7] adding env_map and env_tuple macros --- test-engine/src/environment.rs | 58 ++++++++++++++++++++-------------- test-engine/src/macros.rs | 23 +++++++++++++- test-engine/src/prelude.rs | 4 +-- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/test-engine/src/environment.rs b/test-engine/src/environment.rs index cf23c8c..090ef6f 100644 --- a/test-engine/src/environment.rs +++ b/test-engine/src/environment.rs @@ -410,25 +410,7 @@ impl ToValue for EnvVec { ); let value_kind = if let Some(first) = vec.first() { - match first { - Value::Bool { .. } => ValueKind::Bool, - Value::I8 { .. } => ValueKind::I8, - Value::I16 { .. } => ValueKind::I16, - Value::I32 { .. } => ValueKind::I32, - Value::I64 { .. } => ValueKind::I64, - Value::I128 { .. } => ValueKind::I128, - Value::U8 { .. } => ValueKind::U8, - Value::U16 { .. } => ValueKind::U16, - Value::U32 { .. } => ValueKind::U32, - Value::U64 { .. } => ValueKind::U64, - Value::U128 { .. } => ValueKind::U128, - Value::String { .. } => ValueKind::String, - Value::Enum { .. } => ValueKind::Enum, - Value::Array { .. } => ValueKind::Array, - Value::Tuple { .. } => ValueKind::Tuple, - Value::Map { .. } => ValueKind::Map, - Value::Custom { value } => ValueKind::Custom(value.get_custom_value_kind()), - } + get_value_kind(first) } else { self.value_kind }; @@ -488,14 +470,14 @@ impl ToValue for EnvTuple { pub struct EnvMap { key_kind: ManifestValueKind, value_kind: ManifestValueKind, - elements: IndexMap, Box>, + elements: Vec<(Box, Box)>, } impl EnvMap { pub fn from_vec( key_kind: ManifestValueKind, value_kind: ManifestValueKind, - elements: IndexMap, Box>, + elements: Vec<(Box, Box)>, ) -> Self { Self { key_kind, @@ -508,7 +490,7 @@ impl EnvMap { Self { key_kind, value_kind, - elements: IndexMap::new(), + elements: Vec::new(), } } } @@ -532,9 +514,15 @@ impl ToValue for EnvMap { }, ); + let (key_kind, value_kind) = if let Some(first) = entries.first() { + (get_value_kind(&first.0), get_value_kind(&first.1)) + } else { + (self.key_kind, self.value_kind) + }; + let value = Value::Map { - key_value_kind: self.key_kind, - value_value_kind: self.value_kind, + key_value_kind: key_kind, + value_value_kind: value_kind, entries, }; @@ -604,3 +592,25 @@ impl Encode> + ?Sized> T (manifest_builder, value) } } + +fn get_value_kind(value: &ManifestValue) -> ManifestValueKind { + match value { + Value::Bool { .. } => ValueKind::Bool, + Value::I8 { .. } => ValueKind::I8, + Value::I16 { .. } => ValueKind::I16, + Value::I32 { .. } => ValueKind::I32, + Value::I64 { .. } => ValueKind::I64, + Value::I128 { .. } => ValueKind::I128, + Value::U8 { .. } => ValueKind::U8, + Value::U16 { .. } => ValueKind::U16, + Value::U32 { .. } => ValueKind::U32, + Value::U64 { .. } => ValueKind::U64, + Value::U128 { .. } => ValueKind::U128, + Value::String { .. } => ValueKind::String, + Value::Enum { .. } => ValueKind::Enum, + Value::Array { .. } => ValueKind::Array, + Value::Tuple { .. } => ValueKind::Tuple, + Value::Map { .. } => ValueKind::Map, + Value::Custom { value } => ValueKind::Custom(value.get_custom_value_kind()), + } +} diff --git a/test-engine/src/macros.rs b/test-engine/src/macros.rs index 3b90b8f..cdf69f0 100644 --- a/test-engine/src/macros.rs +++ b/test-engine/src/macros.rs @@ -25,7 +25,7 @@ macro_rules! env_tuple{ ($( $x:expr ),*) => {{ use test_engine::prelude::*; - let mut temp_vec: Vec> = vec![]; + let mut temp_vec: Vec> = vec![]; $( temp_vec.push(Box::new($x)); )* @@ -37,6 +37,7 @@ macro_rules! env_tuple{ macro_rules! env_vec { (@empty $kind:expr) => {{ use test_engine::prelude::*; + EnvVec::from_vec($kind,vec![]) }}; @@ -55,6 +56,7 @@ macro_rules! env_vec { macro_rules! some { ($x:expr) => {{ use test_engine::prelude::*; + EnvOption::Some(Box::new($x)) }}; } @@ -66,6 +68,25 @@ macro_rules! none { }; } +#[macro_export] +macro_rules! env_map { + (@empty $key_kind:expr , $value_kind:expr) => {{ + use test_engine::prelude::*; + + EnvMap::new($key_kind, $value_kind) + }}; + + ($($key:expr => $value:expr),*) => {{ + use test_engine::prelude::*; + + let mut temp_vec:Vec<(Box, Box)> = vec![]; + $( + temp_vec.push((Box::new($key), Box::new($value))); + )* + EnvMap::from_vec(ManifestValueKind::Bool, ManifestValueKind::Bool, temp_vec) + }}; +} + #[macro_export] macro_rules! nf_ids { () => ( diff --git a/test-engine/src/prelude.rs b/test-engine/src/prelude.rs index 426ed30..d307d0a 100644 --- a/test-engine/src/prelude.rs +++ b/test-engine/src/prelude.rs @@ -14,6 +14,6 @@ pub use crate::test_engine::*; pub use crate::to_id::ToId; pub use crate::utils::*; pub use crate::{ - env_args, env_vec, global_package, global_package_advanced, global_package_from_binary, nf_ids, - none, some, + env_args, env_map, env_tuple, env_vec, global_package, global_package_advanced, + global_package_from_binary, nf_ids, none, some, }; From 03258e49beb1ca9362023050e2c3fe361ebdd3fb Mon Sep 17 00:00:00 2001 From: atoumbre Date: Tue, 8 Jul 2025 13:40:11 +0000 Subject: [PATCH 7/7] fix new_with_custom_genesis --- test-engine/src/engine_interface.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test-engine/src/engine_interface.rs b/test-engine/src/engine_interface.rs index 0683380..0f0e099 100644 --- a/test-engine/src/engine_interface.rs +++ b/test-engine/src/engine_interface.rs @@ -21,11 +21,13 @@ impl EngineInterface { } } - pub fn new_with_custom_genesis(_genesis: BabylonSettings) -> Self { + pub fn new_with_custom_genesis(genesis: BabylonSettings) -> Self { let test_runner_builder = LedgerSimulatorBuilder::new() - // .with_custom_genesis(genesis) - // .with_custom_protocol(|builder| builder.only_babylon()) - //.without_kernel_trace() + .with_custom_protocol(|builder| { + builder + .configure_babylon(|_| genesis) + .from_bootstrap_to_latest() + }) .build(); Self { simulator: test_runner_builder,