-
Notifications
You must be signed in to change notification settings - Fork 356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementing all messages handling in mutlitest App #398
Changes from 1 commit
c0e7522
f4ef0b1
c1ee67b
1f82b41
a3e574b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,14 @@ | ||
use cosmwasm_std::{Addr, Api, Binary, BlockInfo, Empty, Storage}; | ||
use mockall::automock; | ||
|
||
use anyhow::Result as AnyResult; | ||
use derivative::Derivative; | ||
use std::cell::{Ref, RefCell}; | ||
use std::ops::Deref; | ||
use std::rc::Rc; | ||
|
||
use crate::AppResponse; | ||
|
||
/// Custom message handler trait. Implementator of this trait is mocking environment behaviour on | ||
/// Custom message handler trait. Implementor of this trait is mocking environment behavior on | ||
/// given custom message. | ||
pub trait CustomHandler<ExecC = Empty, QueryC = Empty> { | ||
fn execute( | ||
|
@@ -27,11 +30,8 @@ pub trait CustomHandler<ExecC = Empty, QueryC = Empty> { | |
} | ||
|
||
/// Simplified version of `CustomHandler` having only arguments which are not app internals - they | ||
/// are just discarded. Usefull for simpler mocking. | ||
#[automock(type QueryResult = Binary;)] | ||
/// are just discarded. Useful for simpler mocking. | ||
pub trait SimpleCustomHandler<ExecC = Empty, QueryC = Empty> { | ||
type QueryResult; | ||
|
||
fn execute(&self, block: &BlockInfo, sender: Addr, msg: ExecC) -> AnyResult<AppResponse>; | ||
fn query(&self, block: &BlockInfo, msg: QueryC) -> AnyResult<Binary>; | ||
} | ||
|
@@ -58,3 +58,72 @@ impl<ExecC, QueryC, T: SimpleCustomHandler<ExecC, QueryC>> CustomHandler<ExecC, | |
self.query(block, msg) | ||
} | ||
} | ||
|
||
/// Custom handler implementation panicking on each call. Assuming, that unless specific behavior | ||
/// is implemented, custom messages should not be send. | ||
pub struct PanickingCustomHandler; | ||
|
||
impl<ExecC, QueryC> SimpleCustomHandler<ExecC, QueryC> for PanickingCustomHandler | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why even have the Also, I think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea, probably in contract we should not use in contracts tests. |
||
where | ||
ExecC: std::fmt::Debug, | ||
QueryC: std::fmt::Debug, | ||
{ | ||
fn execute(&self, _block: &BlockInfo, sender: Addr, msg: ExecC) -> AnyResult<AppResponse> { | ||
panic!("Unexpected custom exec msg {:?} from {:?}", msg, sender) | ||
} | ||
|
||
fn query(&self, _block: &BlockInfo, msg: QueryC) -> AnyResult<Binary> { | ||
panic!("Unexpected custom query {:?}", msg) | ||
} | ||
} | ||
|
||
/// Internal state of `CachingCustomHandler` wrapping internal mutability so it is not exposed to | ||
/// user. Those have to be shared internal state, as after mock is passed to app it is not | ||
/// possible to access mock internals which are not exposed by API. | ||
#[derive(Derivative)] | ||
#[derivative(Default(bound = "", new = "true"), Clone(bound = ""))] | ||
pub struct CachingCustomHandlerState<ExecC, QueryC> { | ||
execs: Rc<RefCell<Vec<ExecC>>>, | ||
queries: Rc<RefCell<Vec<QueryC>>>, | ||
} | ||
|
||
impl<ExecC, QueryC> CachingCustomHandlerState<ExecC, QueryC> { | ||
pub fn execs(&self) -> impl Deref<Target = [ExecC]> + '_ { | ||
Ref::map(self.execs.borrow(), Vec::as_slice) | ||
} | ||
|
||
pub fn queries(&self) -> impl Deref<Target = [QueryC]> + '_ { | ||
Ref::map(self.queries.borrow(), Vec::as_slice) | ||
} | ||
|
||
pub fn reset(&self) { | ||
self.execs.borrow_mut().clear(); | ||
self.queries.borrow_mut().clear(); | ||
} | ||
} | ||
|
||
/// Custom handler storing all the messages it received, so they can be later verified. State is | ||
/// thin shared state, so it can be hold after mock is passed to App to read state. | ||
#[derive(Clone, Derivative)] | ||
#[derivative(Default(bound = "", new = "true"))] | ||
pub struct CachingCustomHandler<ExecC, QueryC> { | ||
state: CachingCustomHandlerState<ExecC, QueryC>, | ||
} | ||
|
||
impl<ExecC, QueryC> CachingCustomHandler<ExecC, QueryC> { | ||
pub fn state(&self) -> CachingCustomHandlerState<ExecC, QueryC> { | ||
self.state.clone() | ||
} | ||
} | ||
|
||
impl<ExecC, QueryC> SimpleCustomHandler<ExecC, QueryC> for CachingCustomHandler<ExecC, QueryC> { | ||
fn execute(&self, _block: &BlockInfo, _sender: Addr, msg: ExecC) -> AnyResult<AppResponse> { | ||
self.state.execs.borrow_mut().push(msg); | ||
Ok(AppResponse::default()) | ||
} | ||
|
||
fn query(&self, _block: &BlockInfo, msg: QueryC) -> AnyResult<Binary> { | ||
self.state.queries.borrow_mut().push(msg); | ||
Ok(Binary::default()) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks nice.