From c9d172e06e3b813d842ea7e21348a9c285adf213 Mon Sep 17 00:00:00 2001 From: Noah Saso Date: Fri, 18 Oct 2024 12:01:04 -0400 Subject: [PATCH] mooooore tests --- .../dao-vote-delegation/src/contract.rs | 15 +- .../dao-vote-delegation/src/error.rs | 11 +- .../dao-vote-delegation/src/testing/suite.rs | 2 +- .../dao-vote-delegation/src/testing/tests.rs | 256 +++++++++++++++++- packages/dao-testing/src/suite/base.rs | 41 +++ 5 files changed, 306 insertions(+), 19 deletions(-) diff --git a/contracts/delegation/dao-vote-delegation/src/contract.rs b/contracts/delegation/dao-vote-delegation/src/contract.rs index 037ebea14..de4705051 100644 --- a/contracts/delegation/dao-vote-delegation/src/contract.rs +++ b/contracts/delegation/dao-vote-delegation/src/contract.rs @@ -35,7 +35,7 @@ use crate::state::{ }; use crate::ContractError; -pub(crate) const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); +pub(crate) const CONTRACT_NAME: &str = "crates.io:dao-vote-delegation"; pub(crate) const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub const DEFAULT_LIMIT: u32 = 10; @@ -149,7 +149,7 @@ fn execute_register(deps: DepsMut, env: Env, info: MessageInfo) -> Result Decimal::one() { return Err(ContractError::CannotDelegateMoreThan100Percent { current: current_percent_delegated - .checked_mul(Decimal::new(100u128.into()))? + .checked_mul(Decimal::from_atomics(100u128, 0).unwrap())? .to_string(), attempt: new_total_percent_delegated - .checked_mul(Decimal::new(100u128.into()))? + .checked_mul(Decimal::from_atomics(100u128, 0).unwrap())? .to_string(), }); } diff --git a/contracts/delegation/dao-vote-delegation/src/error.rs b/contracts/delegation/dao-vote-delegation/src/error.rs index 6e614f1d0..e46814f2c 100644 --- a/contracts/delegation/dao-vote-delegation/src/error.rs +++ b/contracts/delegation/dao-vote-delegation/src/error.rs @@ -40,15 +40,12 @@ pub enum ContractError { #[error("delegates cannot delegate to others")] DelegatesCannotDelegate {}, - #[error("undelegate before registering as a delegate")] - UndelegateBeforeRegistering {}, + #[error("cannot register as a delegate with existing delegations")] + CannotRegisterWithDelegations {}, - #[error("no voting power to delegate")] + #[error("no voting power")] NoVotingPower {}, - #[error("cannot delegate to self")] - CannotDelegateToSelf {}, - #[error("delegation does not exist")] DelegationDoesNotExist {}, @@ -58,7 +55,7 @@ pub enum ContractError { #[error("invalid voting power percent")] InvalidVotingPowerPercent {}, - #[error("migration error: incorrect contract: expected {expected}, actual {actual}")] + #[error("migration error: incorrect contract: expected \"{expected}\", actual \"{actual}\"")] MigrationErrorIncorrectContract { expected: String, actual: String }, #[error("migration error: invalid version: new {new}, current {current}")] diff --git a/contracts/delegation/dao-vote-delegation/src/testing/suite.rs b/contracts/delegation/dao-vote-delegation/src/testing/suite.rs index 72e91b953..bbf14657e 100644 --- a/contracts/delegation/dao-vote-delegation/src/testing/suite.rs +++ b/contracts/delegation/dao-vote-delegation/src/testing/suite.rs @@ -95,7 +95,7 @@ impl DaoVoteDelegationTestingSuite { }, &[], "delegation", - None, + Some(core_addr.to_string()), ); self.setup_delegation_module(); diff --git a/contracts/delegation/dao-vote-delegation/src/testing/tests.rs b/contracts/delegation/dao-vote-delegation/src/testing/tests.rs index 9f41e3df5..3d5b04de4 100644 --- a/contracts/delegation/dao-vote-delegation/src/testing/tests.rs +++ b/contracts/delegation/dao-vote-delegation/src/testing/tests.rs @@ -1,7 +1,13 @@ -use cosmwasm_std::{to_json_binary, Addr, Decimal, Empty, Uint128}; +use cosmwasm_std::{ + testing::{mock_dependencies, mock_env}, + to_json_binary, Addr, Decimal, Empty, Uint128, +}; use cw_multi_test::{Contract, ContractWrapper}; +use dao_interface::helpers::OptionalUpdate; use dao_testing::{ADDR0, ADDR1, ADDR2, ADDR3, ADDR4}; +use crate::contract::{CONTRACT_NAME, CONTRACT_VERSION}; + use super::*; pub fn dao_vote_delegation_contract() -> Box> { @@ -607,3 +613,251 @@ fn test_vote_with_override() { suite.members[0].weight + suite.members[2].weight, ); } + +#[test] +fn test_allow_register_after_unregister_same_block() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.unregister(ADDR0); + suite.register(ADDR0); +} + +#[test] +fn test_allow_register_after_unregister_next_block() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.advance_block(); + suite.unregister(ADDR0); + suite.advance_block(); + suite.register(ADDR0); +} + +#[test] +#[should_panic(expected = "invalid delegation validity blocks: provided 1, minimum 2")] +fn test_validate_delegation_validity_blocks() { + DaoVoteDelegationTestingSuite::new() + .with_delegation_validity_blocks(1) + .build(); +} + +#[test] +#[should_panic(expected = "invalid delegation validity blocks: provided 1, minimum 2")] +fn test_validate_delegation_validity_blocks_update() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.update_delegation_validity_blocks(Some(1)); +} + +#[test] +#[should_panic(expected = "delegate already registered")] +fn test_no_double_register() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.register(ADDR0); +} + +#[test] +#[should_panic(expected = "no voting power")] +fn test_no_vp_register() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register("non_member"); +} + +#[test] +#[should_panic(expected = "cannot register as a delegate with existing delegations")] +fn test_cannot_register_with_delegations_same_block() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.delegate(ADDR1, ADDR0, Decimal::percent(100)); + suite.register(ADDR1); +} + +#[test] +#[should_panic(expected = "cannot register as a delegate with existing delegations")] +fn test_cannot_register_with_delegations_next_block() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.delegate(ADDR1, ADDR0, Decimal::percent(100)); + suite.advance_block(); + suite.register(ADDR1); +} + +#[test] +#[should_panic(expected = "delegate not registered")] +fn test_cannot_unregister_unregistered() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.unregister(ADDR0); +} + +#[test] +#[should_panic(expected = "invalid voting power percent")] +fn test_cannot_delegate_zero_percent() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.delegate(ADDR1, ADDR0, Decimal::zero()); +} + +#[test] +#[should_panic(expected = "invalid voting power percent")] +fn test_cannot_delegate_more_than_100_percent() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.delegate(ADDR1, ADDR0, Decimal::percent(101)); +} + +#[test] +#[should_panic(expected = "delegates cannot delegate to others")] +fn test_delegates_cannot_delegate() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.register(ADDR1); + suite.delegate(ADDR0, ADDR1, Decimal::percent(100)); +} + +#[test] +#[should_panic(expected = "delegate not registered")] +fn test_cannot_delegate_unregistered() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.delegate(ADDR0, ADDR1, Decimal::percent(100)); +} + +#[test] +#[should_panic(expected = "no voting power")] +fn test_cannot_delegate_no_vp() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.delegate("not_member", ADDR0, Decimal::percent(100)); +} + +#[test] +#[should_panic(expected = "cannot delegate more than 100% (current: 50%, attempt: 101%)")] +fn test_cannot_delegate_more_than_100() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.register(ADDR1); + suite.delegate(ADDR2, ADDR0, Decimal::percent(50)); + suite.delegate(ADDR2, ADDR1, Decimal::percent(51)); +} + +#[test] +#[should_panic(expected = "delegation does not exist")] +fn test_cannot_undelegate_nonexistent() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.undelegate(ADDR0, ADDR1); +} + +#[test] +fn test_delegate_undelegate_same_block() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.delegate(ADDR1, ADDR0, Decimal::percent(100)); + suite.undelegate(ADDR1, ADDR0); +} + +#[test] +#[should_panic(expected = "delegation does not exist")] +fn test_cannot_undelegate_twice() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + + suite.register(ADDR0); + suite.delegate(ADDR1, ADDR0, Decimal::percent(100)); + suite.undelegate(ADDR1, ADDR0); + suite.undelegate(ADDR1, ADDR0); +} + +#[test] +#[should_panic(expected = "unauthorized")] +fn test_unauthorized_update_voting_power_hook_callers() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + let delegation_addr = suite.delegation_addr.clone(); + + suite.execute_smart_ok( + "no_one", + &delegation_addr, + &crate::msg::ExecuteMsg::UpdateVotingPowerHookCallers { + add: None, + remove: None, + }, + &[], + ); +} + +#[test] +#[should_panic(expected = "unauthorized")] +fn test_unauthorized_config_update() { + let mut suite = DaoVoteDelegationTestingSuite::new().build(); + let delegation_addr = suite.delegation_addr.clone(); + + suite.execute_smart_ok( + "no_one", + &delegation_addr, + &crate::msg::ExecuteMsg::UpdateConfig { + vp_cap_percent: OptionalUpdate(None), + delegation_validity_blocks: OptionalUpdate(None), + }, + &[], + ); +} + +#[test] +fn test_migration_incorrect_contract() { + let mut deps = mock_dependencies(); + + cw2::set_contract_version(&mut deps.storage, "different_contract", "0.1.0").unwrap(); + + let err = + crate::contract::migrate(deps.as_mut(), mock_env(), crate::msg::MigrateMsg {}).unwrap_err(); + assert_eq!( + err, + crate::ContractError::MigrationErrorIncorrectContract { + expected: "crates.io:dao-vote-delegation".to_string(), + actual: "different_contract".to_string(), + } + ); +} + +#[test] +fn test_cannot_migrate_to_same_version() { + let mut deps = mock_dependencies(); + + cw2::set_contract_version(&mut deps.storage, CONTRACT_NAME, CONTRACT_VERSION).unwrap(); + + let err = + crate::contract::migrate(deps.as_mut(), mock_env(), crate::msg::MigrateMsg {}).unwrap_err(); + assert_eq!( + err, + crate::ContractError::MigrationErrorInvalidVersion { + new: CONTRACT_VERSION.to_string(), + current: CONTRACT_VERSION.to_string() + } + ); +} + +#[test] +fn test_migrate() { + let mut deps = mock_dependencies(); + + cw2::set_contract_version(&mut deps.storage, CONTRACT_NAME, "2.4.0").unwrap(); + + crate::contract::migrate(deps.as_mut(), mock_env(), crate::msg::MigrateMsg {}).unwrap(); + + let version = cw2::get_contract_version(&deps.storage).unwrap(); + + assert_eq!(version.contract, CONTRACT_NAME); + assert_eq!(version.version, CONTRACT_VERSION); +} diff --git a/packages/dao-testing/src/suite/base.rs b/packages/dao-testing/src/suite/base.rs index 3db977430..94d731fa4 100644 --- a/packages/dao-testing/src/suite/base.rs +++ b/packages/dao-testing/src/suite/base.rs @@ -431,6 +431,47 @@ impl DaoTestingSuiteBase { .unwrap() } + /// migrate a smart contract and return the result + pub fn migrate( + &mut self, + sender: impl Into, + contract_addr: impl Into, + msg: &T, + code_id: u64, + ) -> AnyResult { + self.app.migrate_contract( + Addr::unchecked(sender), + Addr::unchecked(contract_addr), + msg, + code_id, + ) + } + + /// migrate a smart contract and expect it to succeed + pub fn migrate_ok( + &mut self, + sender: impl Into, + contract_addr: impl Into, + msg: &T, + code_id: u64, + ) -> AppResponse { + self.migrate(sender, contract_addr, msg, code_id).unwrap() + } + + /// migrate a smart contract and return the error + pub fn migrate_err( + &mut self, + sender: impl Into, + contract_addr: impl Into, + msg: &T, + code_id: u64, + ) -> E { + self.migrate(sender, contract_addr, msg, code_id) + .unwrap_err() + .downcast() + .unwrap() + } + /// instantiate a cw20 contract and return its address pub fn instantiate_cw20(&mut self, name: &str, initial_balances: Vec) -> Addr { self.instantiate(