cw_multi_test/
module.rs

1use crate::app::CosmosRouter;
2use crate::error::std_error_bail;
3use crate::AppResponse;
4use cosmwasm_std::{
5    Addr, Api, Binary, BlockInfo, CustomMsg, CustomQuery, Querier, StdError, StdResult, Storage,
6};
7use serde::de::DeserializeOwned;
8use std::fmt::Debug;
9use std::marker::PhantomData;
10
11/// # General module
12///
13/// Provides a generic interface for modules within the test environment.
14/// It is essential for creating modular and extensible testing setups,
15/// allowing developers to integrate custom functionalities
16/// or test specific scenarios.
17pub trait Module {
18    /// Type of messages processed by the module instance.
19    type ExecT;
20    /// Type of queries processed by the module instance.
21    type QueryT;
22    /// Type of privileged messages used by the module instance.
23    type SudoT;
24
25    /// Runs any [ExecT](Self::ExecT) message,
26    /// which can be called by any external actor or smart contract.
27    fn execute<ExecC, QueryC>(
28        &self,
29        api: &dyn Api,
30        storage: &mut dyn Storage,
31        router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
32        block: &BlockInfo,
33        sender: Addr,
34        msg: Self::ExecT,
35    ) -> StdResult<AppResponse>
36    where
37        ExecC: CustomMsg + DeserializeOwned + 'static,
38        QueryC: CustomQuery + DeserializeOwned + 'static;
39
40    /// Runs any [QueryT](Self::QueryT) message,
41    /// which can be called by any external actor or smart contract.
42    fn query(
43        &self,
44        api: &dyn Api,
45        storage: &dyn Storage,
46        querier: &dyn Querier,
47        block: &BlockInfo,
48        request: Self::QueryT,
49    ) -> StdResult<Binary>;
50
51    /// Runs privileged actions, like minting tokens, or governance proposals.
52    /// This allows modules to have full access to these privileged actions,
53    /// that cannot be triggered by smart contracts.
54    ///
55    /// There is no sender, as this must be previously authorized before calling.
56    fn sudo<ExecC, QueryC>(
57        &self,
58        api: &dyn Api,
59        storage: &mut dyn Storage,
60        router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
61        block: &BlockInfo,
62        msg: Self::SudoT,
63    ) -> StdResult<AppResponse>
64    where
65        ExecC: CustomMsg + DeserializeOwned + 'static,
66        QueryC: CustomQuery + DeserializeOwned + 'static;
67}
68/// # Always failing module
69///
70/// This could be a diagnostic or testing tool within the Cosmos ecosystem,
71/// designed to intentionally fail during processing any message, query or privileged action.
72pub struct FailingModule<ExecT, QueryT, SudoT>(PhantomData<(ExecT, QueryT, SudoT)>);
73
74impl<ExecT, QueryT, SudoT> FailingModule<ExecT, QueryT, SudoT> {
75    /// Creates an instance of a failing module.
76    pub fn new() -> Self {
77        Self(PhantomData)
78    }
79}
80
81impl<ExecT, QueryT, SudoT> Default for FailingModule<ExecT, QueryT, SudoT> {
82    /// Creates a default instance of a failing module.
83    fn default() -> Self {
84        Self::new()
85    }
86}
87
88impl<ExecT, QueryT, SudoT> Module for FailingModule<ExecT, QueryT, SudoT>
89where
90    ExecT: Debug,
91    QueryT: Debug,
92    SudoT: Debug,
93{
94    type ExecT = ExecT;
95    type QueryT = QueryT;
96    type SudoT = SudoT;
97
98    /// Runs any [ExecT](Self::ExecT) message, always returns an error.
99    fn execute<ExecC, QueryC>(
100        &self,
101        _api: &dyn Api,
102        _storage: &mut dyn Storage,
103        _router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
104        _block: &BlockInfo,
105        sender: Addr,
106        msg: Self::ExecT,
107    ) -> StdResult<AppResponse> {
108        std_error_bail!("Unexpected exec msg {:?} from {:?}", msg, sender)
109    }
110
111    /// Runs any [QueryT](Self::QueryT) message, always returns an error.
112    fn query(
113        &self,
114        _api: &dyn Api,
115        _storage: &dyn Storage,
116        _querier: &dyn Querier,
117        _block: &BlockInfo,
118        request: Self::QueryT,
119    ) -> StdResult<Binary> {
120        std_error_bail!("Unexpected custom query {:?}", request)
121    }
122
123    /// Runs any [SudoT](Self::SudoT) privileged action, always returns an error.
124    fn sudo<ExecC, QueryC>(
125        &self,
126        _api: &dyn Api,
127        _storage: &mut dyn Storage,
128        _router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
129        _block: &BlockInfo,
130        msg: Self::SudoT,
131    ) -> StdResult<AppResponse> {
132        std_error_bail!("Unexpected sudo msg {:?}", msg)
133    }
134}
135/// # Always accepting module
136///
137/// This struct represents a module in the Cosmos ecosystem designed to
138/// always accept all processed messages, queries and privileged actions.
139pub struct AcceptingModule<ExecT, QueryT, SudoT>(PhantomData<(ExecT, QueryT, SudoT)>);
140
141impl<ExecT, QueryT, SudoT> AcceptingModule<ExecT, QueryT, SudoT> {
142    /// Creates an instance of an accepting module.
143    pub fn new() -> Self {
144        Self(PhantomData)
145    }
146}
147
148impl<ExecT, QueryT, SudoT> Default for AcceptingModule<ExecT, QueryT, SudoT> {
149    /// Creates an instance of an accepting module with default settings.
150    fn default() -> Self {
151        Self::new()
152    }
153}
154
155impl<ExecT, QueryT, SudoT> Module for AcceptingModule<ExecT, QueryT, SudoT>
156where
157    ExecT: Debug,
158    QueryT: Debug,
159    SudoT: Debug,
160{
161    type ExecT = ExecT;
162    type QueryT = QueryT;
163    type SudoT = SudoT;
164
165    /// Runs any [ExecT](Self::ExecT) message, always returns a default response.
166    fn execute<ExecC, QueryC>(
167        &self,
168        _api: &dyn Api,
169        _storage: &mut dyn Storage,
170        _router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
171        _block: &BlockInfo,
172        _sender: Addr,
173        _msg: Self::ExecT,
174    ) -> StdResult<AppResponse> {
175        Ok(AppResponse::default())
176    }
177
178    /// Runs any [QueryT](Self::QueryT) message, always returns a default (empty) binary.
179    fn query(
180        &self,
181        _api: &dyn Api,
182        _storage: &dyn Storage,
183        _querier: &dyn Querier,
184        _block: &BlockInfo,
185        _request: Self::QueryT,
186    ) -> StdResult<Binary> {
187        Ok(Binary::default())
188    }
189
190    /// Runs any [SudoT](Self::SudoT) privileged action, always returns a default response.
191    fn sudo<ExecC, QueryC>(
192        &self,
193        _api: &dyn Api,
194        _storage: &mut dyn Storage,
195        _router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
196        _block: &BlockInfo,
197        _msg: Self::SudoT,
198    ) -> StdResult<AppResponse> {
199        Ok(AppResponse::default())
200    }
201}