Skip to content

Commit

Permalink
added deref and derefmut to improve DAO testing suite API
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahSaso committed Oct 17, 2024
1 parent 7d6ffb2 commit 4633cbe
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 205 deletions.
105 changes: 44 additions & 61 deletions contracts/delegation/dao-vote-delegation/src/testing/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use cosmwasm_std::{Addr, Decimal, Empty, Uint128};
use cw_multi_test::{Contract, ContractWrapper};
use dao_testing::{DaoTestingSuite, DaoTestingSuiteBase, Executor, ADDR0, ADDR1, ADDR2};
use dao_testing::{DaoTestingSuite, DaoTestingSuiteBase, ADDR0, ADDR1, ADDR2};
use dao_voting::delegation::{DelegationResponse, DelegationsResponse};

pub fn dao_vote_delegation_contract() -> Box<dyn Contract<Empty>> {
Expand All @@ -19,55 +19,43 @@ fn test_setup() {
let mut suite = base.cw4();
let dao = suite.dao();

let code_id = suite.base.app.store_code(dao_vote_delegation_contract());
let delegation_addr = suite
.base
.app
.instantiate_contract(
code_id,
dao.core_addr.clone(),
&crate::msg::InstantiateMsg {
dao: None,
vp_hook_callers: Some(vec![dao.x.group_addr.to_string()]),
no_sync_proposal_modules: None,
vp_cap_percent: Some(Decimal::percent(50)),
delegation_validity_blocks: Some(100),
},
&[],
"delegation",
None,
)
.unwrap();
let code_id = suite.store(dao_vote_delegation_contract);
let delegation_addr = suite.instantiate(
code_id,
&dao.core_addr,
&crate::msg::InstantiateMsg {
dao: None,
vp_hook_callers: Some(vec![dao.x.group_addr.to_string()]),
no_sync_proposal_modules: None,
vp_cap_percent: Some(Decimal::percent(50)),
delegation_validity_blocks: Some(100),
},
&[],
"delegation",
None,
);

// register addr0 as a delegate
suite
.base
.app
.execute_contract(
Addr::unchecked(ADDR0),
delegation_addr.clone(),
&crate::msg::ExecuteMsg::Register {},
&[],
)
.unwrap();
suite.execute_smart(
ADDR0,
&delegation_addr,
&crate::msg::ExecuteMsg::Register {},
&[],
);

// delegate 100% of addr1's voting power to addr0
suite
.base
.app
.execute_contract(
Addr::unchecked(ADDR1),
delegation_addr.clone(),
&crate::msg::ExecuteMsg::Delegate {
delegate: ADDR0.to_string(),
percent: Decimal::percent(100),
},
&[],
)
.unwrap();
suite.execute_smart(
ADDR1,
&delegation_addr,
&crate::msg::ExecuteMsg::Delegate {
delegate: ADDR0.to_string(),
percent: Decimal::percent(100),
},
&[],
);

// delegations take effect on the next block
suite.base.advance_block();
suite.advance_block();

let delegations: DelegationsResponse = suite
.querier()
Expand All @@ -94,7 +82,7 @@ fn test_setup() {

// propose a proposal
let (proposal_module, id1, p1) =
dao.propose_single_choice(&mut suite.base.app, ADDR0, "test proposal 1", vec![]);
dao.propose_single_choice(&mut suite, ADDR0, "test proposal 1", vec![]);

// ensure delegation is correctly applied to proposal
let udvp: dao_voting::delegation::UnvotedDelegatedVotingPowerResponse = suite
Expand All @@ -115,26 +103,21 @@ fn test_setup() {
);

// set delegation to 50%
suite
.base
.app
.execute_contract(
Addr::unchecked(ADDR1),
delegation_addr.clone(),
&crate::msg::ExecuteMsg::Delegate {
delegate: ADDR0.to_string(),
percent: Decimal::percent(50),
},
&[],
)
.unwrap();
suite.execute_smart(
ADDR1,
&delegation_addr,
&crate::msg::ExecuteMsg::Delegate {
delegate: ADDR0.to_string(),
percent: Decimal::percent(50),
},
&[],
);

// delegations take effect on the next block
suite.base.advance_block();
suite.advance_block();

// propose a proposal
let (_, id2, p2) =
dao.propose_single_choice(&mut suite.base.app, ADDR2, "test proposal 2", vec![]);
let (_, id2, p2) = dao.propose_single_choice(&mut suite, ADDR2, "test proposal 2", vec![]);

// ensure delegation is correctly applied to new proposal
let udvp: dao_voting::delegation::UnvotedDelegatedVotingPowerResponse = suite
Expand Down
169 changes: 119 additions & 50 deletions packages/dao-testing/src/suite/base.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
use cosmwasm_std::{to_json_binary, Addr, CosmosMsg, Empty, QuerierWrapper, Timestamp};
use std::{
fmt::{Debug, Display},
ops::{Deref, DerefMut},
};

use cosmwasm_std::{to_json_binary, Addr, Coin, CosmosMsg, Empty, QuerierWrapper, Timestamp};
use cw20::Cw20Coin;
use cw_multi_test::{App, Executor};
use cw_multi_test::{App, AppResponse, Contract, Executor};
use cw_utils::Duration;
use serde::Serialize;

use super::*;
use crate::contracts::*;
Expand All @@ -21,7 +27,7 @@ impl<T> TestDao<T> {
/// proposal ID, and proposal
pub fn propose_single_choice(
&self,
app: &mut App,
base: &mut DaoTestingSuiteBase,
proposer: impl Into<String>,
title: impl Into<String>,
msgs: Vec<CosmosMsg>,
Expand All @@ -41,24 +47,23 @@ impl<T> TestDao<T> {

let (pre_propose_module, proposal_module) = &self.proposal_modules[0];

app.execute_contract(
Addr::unchecked(proposer.into()),
pre_propose_module.as_ref().unwrap().clone(),
base.execute_smart(
proposer,
pre_propose_module.as_ref().unwrap(),
&pre_propose_msg,
&[],
)
.unwrap();
);

let proposal_id: u64 = app
.wrap()
let proposal_id: u64 = base
.querier()
.query_wasm_smart(
proposal_module.clone(),
&dao_proposal_single::msg::QueryMsg::ProposalCount {},
)
.unwrap();

let res: dao_proposal_single::query::ProposalResponse = app
.wrap()
let res: dao_proposal_single::query::ProposalResponse = base
.querier()
.query_wasm_smart(
proposal_module.clone(),
&dao_proposal_single::msg::QueryMsg::Proposal { proposal_id },
Expand Down Expand Up @@ -99,7 +104,7 @@ pub struct DaoTestingSuiteBase {
pub admin_factory_addr: Addr,
}

pub trait DaoTestingSuite<Extra = Empty> {
pub trait DaoTestingSuite<Extra = Empty>: Deref + DerefMut {
/// get the testing suite base
fn base(&self) -> &DaoTestingSuiteBase;

Expand Down Expand Up @@ -218,11 +223,6 @@ pub trait DaoTestingSuite<Extra = Empty> {

dao
}

/// get the app querier
fn querier(&self) -> QuerierWrapper<'_> {
self.base().app.wrap()
}
}

// CONSTRUCTOR
Expand Down Expand Up @@ -296,24 +296,20 @@ impl DaoTestingSuiteBase {
}
}

pub fn instantiate_cw20(&mut self, name: &str, initial_balances: Vec<Cw20Coin>) -> Addr {
self.app
.instantiate_contract(
self.cw20_base_id,
Addr::unchecked(OWNER),
&cw20_base::msg::InstantiateMsg {
name: name.to_string(),
symbol: name.to_string(),
decimals: 6,
initial_balances,
mint: None,
marketing: None,
},
&[],
"cw20",
None,
)
.unwrap()
pub fn cw4(&mut self) -> DaoTestingSuiteCw4 {
DaoTestingSuiteCw4::new(self)
}

pub fn cw20(&mut self) -> DaoTestingSuiteCw20 {
DaoTestingSuiteCw20::new(self)
}

pub fn cw721(&mut self) -> DaoTestingSuiteCw721 {
DaoTestingSuiteCw721::new(self)
}

pub fn token(&mut self) -> DaoTestingSuiteToken {
DaoTestingSuiteToken::new(self)
}
}

Expand Down Expand Up @@ -404,28 +400,101 @@ impl DaoTestingSuiteBase {
x: Empty::default(),
}
}
}

pub fn cw4(&mut self) -> DaoTestingSuiteCw4 {
DaoTestingSuiteCw4::new(self)
// UTILITIES
impl DaoTestingSuiteBase {
/// get the app querier
pub fn querier(&self) -> QuerierWrapper<'_> {
self.app.wrap()
}

pub fn cw20(&mut self) -> DaoTestingSuiteCw20 {
DaoTestingSuiteCw20::new(self)
/// advance the block height by one
pub fn advance_block(&mut self) {
self.app.update_block(|b| b.height += 1);
}

pub fn cw721(&mut self) -> DaoTestingSuiteCw721 {
DaoTestingSuiteCw721::new(self)
/// store a contract given its maker function and return its code ID
pub fn store(&mut self, contract_maker: impl FnOnce() -> Box<dyn Contract<Empty>>) -> u64 {
self.app.store_code(contract_maker())
}

pub fn token(&mut self) -> DaoTestingSuiteToken {
DaoTestingSuiteToken::new(self)
/// instantiate a smart contract and return its address
pub fn instantiate<T: Serialize + Debug>(
&mut self,
code_id: u64,
sender: impl Into<String>,
init_msg: &T,
send_funds: &[Coin],
label: impl Into<String>,
admin: Option<String>,
) -> Addr {
self.app
.instantiate_contract(
code_id,
Addr::unchecked(sender),
init_msg,
send_funds,
label.into(),
admin.map(|a| a.into()),

Check failure on line 439 in packages/dao-testing/src/suite/base.rs

View workflow job for this annotation

GitHub Actions / Lints

useless conversion to the same type: `std::string::String`

Check failure on line 439 in packages/dao-testing/src/suite/base.rs

View workflow job for this annotation

GitHub Actions / Lints

useless conversion to the same type: `std::string::String`
)
.unwrap()
}
}

// UTILITIES
impl DaoTestingSuiteBase {
/// advance the block height by one
pub fn advance_block(&mut self) {
self.app.update_block(|b| b.height += 1);
/// execute a smart contract and expect it to succeed
pub fn execute_smart<T: Serialize + Debug>(
&mut self,
sender: impl Into<String>,
contract_addr: impl Into<String>,
msg: &T,
send_funds: &[Coin],
) -> AppResponse {
self.app
.execute_contract(
Addr::unchecked(sender.into()),
Addr::unchecked(contract_addr.into()),
msg,
send_funds,
)
.unwrap()
}

/// execute a smart contract and return the error
pub fn execute_smart_err<T: Serialize + Debug, E: Display + Debug + Send + Sync + 'static>(
&mut self,
sender: impl Into<String>,
contract_addr: impl Into<String>,
msg: &T,
send_funds: &[Coin],
) -> E {
self.app
.execute_contract(
Addr::unchecked(sender.into()),
Addr::unchecked(contract_addr.into()),
msg,
send_funds,
)
.unwrap_err()
.downcast()
.unwrap()
}

/// instantiate a cw20 contract and return its address
pub fn instantiate_cw20(&mut self, name: &str, initial_balances: Vec<Cw20Coin>) -> Addr {
self.instantiate(
self.cw20_base_id,
OWNER,
&cw20_base::msg::InstantiateMsg {
name: name.to_string(),
symbol: name.to_string(),
decimals: 6,
initial_balances,
mint: None,
marketing: None,
},
&[],
"cw20",
None,
)
}
}
Loading

0 comments on commit 4633cbe

Please sign in to comment.