From f96a7bae7c5bdda843fb4a327feeb8a37c06ea3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Kuras?= Date: Wed, 1 Sep 2021 18:12:57 +0200 Subject: [PATCH] Test for handling custom execution messages --- packages/multi-test/src/app.rs | 72 +++++++++++++++++-- .../src/test_helpers/contracts/echo.rs | 47 +++++++----- 2 files changed, 96 insertions(+), 23 deletions(-) diff --git a/packages/multi-test/src/app.rs b/packages/multi-test/src/app.rs index ca039b316..8c15dfa94 100644 --- a/packages/multi-test/src/app.rs +++ b/packages/multi-test/src/app.rs @@ -122,6 +122,14 @@ where self } + /// Overwrites default custom messages handler + #[track_caller] + pub fn with_custom(mut self, custom: impl CustomHandler + 'static) -> Self { + assert!(self.custom.is_none(), "Custom handler already overwritten"); + self.custom = Some(Box::new(custom)); + self + } + /// Overwrites default initial block #[track_caller] pub fn with_block(mut self, block: BlockInfo) -> Self { @@ -1077,7 +1085,7 @@ mod test { .execute_contract( owner, contract, - &echo::Message { + &echo::Message:: { data: Some("Data".to_owned()), ..echo::Message::default() }, @@ -1225,7 +1233,7 @@ mod test { // reflect will call echo // echo will set the data // top-level app will not display the data - let echo_msg = echo::Message { + let echo_msg = echo::Message:: { data: Some("my echo".into()), events: vec![Event::new("echo").add_attribute("called", "true")], ..echo::Message::default() @@ -1408,7 +1416,7 @@ mod test { .execute_contract( owner, contract, - &echo::Message { + &echo::Message:: { data: None, attributes: vec![ Attribute::new(" ", "value"), @@ -1438,7 +1446,7 @@ mod test { .execute_contract( owner, contract, - &echo::Message { + &echo::Message:: { data: None, attributes: vec![ Attribute::new("key", " "), @@ -1468,7 +1476,7 @@ mod test { .execute_contract( owner, contract, - &echo::Message { + &echo::Message:: { data: None, events: vec![Event::new("event") .add_attribute(" ", "value") @@ -1497,7 +1505,7 @@ mod test { .execute_contract( owner, contract, - &echo::Message { + &echo::Message:: { data: None, events: vec![Event::new("event") .add_attribute("key", " ") @@ -1526,7 +1534,7 @@ mod test { .execute_contract( owner, contract, - &echo::Message { + &echo::Message:: { data: None, events: vec![Event::new(" e "), Event::new("event")], ..echo::Message::default() @@ -1538,4 +1546,54 @@ mod test { assert_eq!(Error::event_type_too_short("e"), err.downcast().unwrap()); } } + + mod custom_messages { + use super::*; + use mockall as ma; + + #[test] + fn triggering_custom_msg() { + let api = MockApi::default(); + let sender = api.addr_validate("sender").unwrap(); + let owner = api.addr_validate("owner").unwrap(); + + let mut custom_handler = MockSimpleCustomHandler::::new(); + custom_handler + .expect_execute() + .with( + ma::predicate::always(), + ma::predicate::always(), + ma::predicate::eq(CustomMsg::SetAge { age: 20 }), + ) + .returning(|_, _, _| { + Ok(AppResponse { + data: None, + events: vec![], + }) + }); + + let mut app = AppBuilder::new() + .with_api(api) + .with_custom(custom_handler) + .build(); + + let contract_id = app.store_code(echo::custom_contract()); + let contract = app + .instantiate_contract(contract_id, owner.clone(), &EmptyMsg {}, &[], "Echo", None) + .unwrap(); + + app.execute_contract( + sender, + contract, + &echo::Message { + sub_msg: vec![SubMsg::new(CosmosMsg::Custom(CustomMsg::SetAge { + age: 20, + }))], + ..Default::default() + }, + &[], + ) + .unwrap(); + } + } } diff --git a/packages/multi-test/src/test_helpers/contracts/echo.rs b/packages/multi-test/src/test_helpers/contracts/echo.rs index 8f2a33bca..21e08fc96 100644 --- a/packages/multi-test/src/test_helpers/contracts/echo.rs +++ b/packages/multi-test/src/test_helpers/contracts/echo.rs @@ -7,37 +7,49 @@ use cosmwasm_std::{ to_binary, Attribute, Binary, ContractResult, Deps, DepsMut, Empty, Env, Event, MessageInfo, Reply, Response, StdError, SubMsg, SubMsgExecutionResponse, }; -use serde::{Deserialize, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use crate::{test_helpers::EmptyMsg, Contract, ContractWrapper}; use schemars::JsonSchema; -use std::fmt; +use std::fmt::Debug; -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct Message { +use derivative::Derivative; + +#[derive(Debug, Clone, Serialize, Deserialize, Derivative)] +#[derivative(Default(bound = "", new = "true"))] +pub struct Message +where + ExecC: Debug + PartialEq + Clone + JsonSchema + 'static, +{ pub data: Option, - pub sub_msg: Vec, + pub sub_msg: Vec>, pub attributes: Vec, pub events: Vec, } #[allow(clippy::unnecessary_wraps)] -fn instantiate( +fn instantiate( _deps: DepsMut, _env: Env, _info: MessageInfo, _msg: EmptyMsg, -) -> Result { +) -> Result, StdError> +where + ExecC: Debug + PartialEq + Clone + JsonSchema + 'static, +{ Ok(Response::default()) } #[allow(clippy::unnecessary_wraps)] -fn execute( +fn execute( _deps: DepsMut, _env: Env, _info: MessageInfo, - msg: Message, -) -> Result { + msg: Message, +) -> Result, StdError> +where + ExecC: Debug + PartialEq + Clone + JsonSchema + 'static, +{ let mut resp = Response::new(); if let Some(data) = msg.data { @@ -55,7 +67,10 @@ fn query(_deps: Deps, _env: Env, msg: EmptyMsg) -> Result { } #[allow(clippy::unnecessary_wraps)] -fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> Result { +fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> Result, StdError> +where + ExecC: Debug + PartialEq + Clone + JsonSchema + 'static, +{ if let Reply { result: ContractResult::Ok(SubMsgExecutionResponse { @@ -71,16 +86,16 @@ fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> Result { } pub fn contract() -> Box> { - let contract = ContractWrapper::new(execute, instantiate, query).with_reply(reply); + let contract = ContractWrapper::new(execute::, instantiate::, query) + .with_reply(reply::); Box::new(contract) } -#[allow(dead_code)] pub fn custom_contract() -> Box> where - C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, + C: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, { - let contract = ContractWrapper::new_with_empty(execute, instantiate, query); - let contract = contract.with_reply_empty(reply); + let contract = + ContractWrapper::new(execute::, instantiate::, query).with_reply(reply::); Box::new(contract) }