Skip to content

Commit

Permalink
Showing 8 changed files with 145 additions and 28 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -6,6 +6,13 @@ and this project adheres to

## [Unreleased]

### Added

- cosmwasm-std: Add testing macro `assert_approx_eq!` for comparing two integers
to be relatively close to each other ([#1417]).

[#1417]: https://github.com/CosmWasm/cosmwasm/issues/1417

## [1.1.1] - 2022-09-15

### Fixed
8 changes: 3 additions & 5 deletions contracts/hackatom/tests/integration.rs
Original file line number Diff line number Diff line change
@@ -18,8 +18,8 @@
//! 4. Anywhere you see query(&deps, ...) you must replace it with query(&mut deps, ...)
use cosmwasm_std::{
coins, from_binary, to_vec, Addr, AllBalanceResponse, BankMsg, Binary, ContractResult, Empty,
Response, SubMsg,
assert_approx_eq, coins, from_binary, to_vec, Addr, AllBalanceResponse, BankMsg, Binary,
ContractResult, Empty, Response, SubMsg,
};
use cosmwasm_vm::{
call_execute, from_slice,
@@ -405,9 +405,7 @@ fn execute_allocate_large_memory() {
// Gas consumption is relatively small
// Note: the exact gas usage depends on the Rust version used to compile Wasm,
// which we only fix when using rust-optimizer, not integration tests.
let expected = 4413600000; // +/- 20%
assert!(gas_used > expected * 80 / 100, "Gas used: {}", gas_used);
assert!(gas_used < expected * 120 / 100, "Gas used: {}", gas_used);
assert_approx_eq!(gas_used, 4413600000, "0.2");
let used = deps.memory_pages();
assert_eq!(used, pages_before + 48, "Memory used: {} pages", used);
pages_before += 48;
2 changes: 1 addition & 1 deletion packages/std/src/deps.rs
Original file line number Diff line number Diff line change
@@ -74,7 +74,7 @@ impl<'a, C: CustomQuery> DepsMut<'a, C> {
#[cfg(test)]
mod tests {
use super::*;
use crate::mock::{mock_dependencies, MockApi, MockQuerier, MockStorage};
use crate::testing::{mock_dependencies, MockApi, MockQuerier, MockStorage};
use serde::{Deserialize, Serialize};

// ensure we can call these many times, eg. as sub-calls
21 changes: 1 addition & 20 deletions packages/std/src/lib.rs
Original file line number Diff line number Diff line change
@@ -97,27 +97,8 @@ pub use crate::imports::{ExternalApi, ExternalQuerier, ExternalStorage};

// Exposed for testing only
// Both unit tests and integration tests are compiled to native code, so everything in here does not need to compile to Wasm.

#[cfg(not(target_arch = "wasm32"))]
mod mock;
#[cfg(not(target_arch = "wasm32"))]
pub mod testing {
#[cfg(feature = "staking")]
pub use crate::mock::StakingQuerier;
pub use crate::mock::{
digit_sum, mock_dependencies, mock_dependencies_with_balance,
mock_dependencies_with_balances, mock_env, mock_info, mock_wasmd_attr, riffle_shuffle,
BankQuerier, MockApi, MockQuerier, MockQuerierCustomHandlerResult, MockStorage,
MOCK_CONTRACT_ADDR,
};
#[cfg(feature = "stargate")]
pub use crate::mock::{
mock_ibc_channel, mock_ibc_channel_close_confirm, mock_ibc_channel_close_init,
mock_ibc_channel_connect_ack, mock_ibc_channel_connect_confirm, mock_ibc_channel_open_init,
mock_ibc_channel_open_try, mock_ibc_packet_ack, mock_ibc_packet_recv,
mock_ibc_packet_timeout,
};
}
pub mod testing;

// Re-exports

108 changes: 108 additions & 0 deletions packages/std/src/testing/assertions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use crate::{Decimal, Uint128};
use std::str::FromStr as _;

/// Asserts that two expressions are approximately equal to each other.
///
/// The `max_rel_diff` argument defines the maximum relative difference
/// of the `left` and `right` values.
///
/// On panic, this macro will print the values of the arguments and
/// the actual relative difference.
///
/// Like [`assert_eq!`], this macro has a second form, where a custom
/// panic message can be provided.
#[macro_export]
macro_rules! assert_approx_eq {
($left:expr, $right:expr, $max_rel_diff:expr $(,)?) => {{
$crate::testing::assert_approx_eq_impl($left, $right, $max_rel_diff, None);
}};
($left:expr, $right:expr, $max_rel_diff:expr, $($args:tt)+) => {{
$crate::testing::assert_approx_eq_impl($left, $right, $max_rel_diff, Some(format!($($args)*)));
}};
}

/// Implementation for the [`cosmwasm_std::assert_approx_eq`] macro. This does not provide any
/// stability guarantees and may change any time.
#[track_caller]
#[doc(hidden)]
pub fn assert_approx_eq_impl<U: Into<Uint128>>(
left: U,
right: U,
max_rel_diff: &str,
panic_msg: Option<String>,
) {
let left = left.into();
let right = right.into();
let max_rel_diff = Decimal::from_str(max_rel_diff).unwrap();

let largest = std::cmp::max(left, right);
let rel_diff = Decimal::from_ratio(left.abs_diff(right), largest);

if rel_diff > max_rel_diff {
match panic_msg {
Some(panic_msg) => panic!(
"assertion failed: `(left ≈ right)`\nleft: {}\nright: {}\nrelative difference: {}\nmax allowed relative difference: {}\n: {}",
left, right, rel_diff, max_rel_diff, panic_msg
),
None => panic!(
"assertion failed: `(left ≈ right)`\nleft: {}\nright: {}\nrelative difference: {}\nmax allowed relative difference: {}\n",
left, right, rel_diff, max_rel_diff
),
}
}
}

#[cfg(test)]
mod tests {
#[test]
fn assert_approx() {
assert_approx_eq!(9_u32, 10_u32, "0.12");
assert_approx_eq!(9_u64, 10_u64, "0.12");
assert_approx_eq!(
9_000_000_000_000_000_000_000_000_000_000_000_000_u128,
10_000_000_000_000_000_000_000_000_000_000_000_000_u128,
"0.10"
);
}

#[test]
fn assert_approx_with_vars() {
let a = 66_u32;
let b = 67_u32;
assert_approx_eq!(a, b, "0.02");

let a = 66_u64;
let b = 67_u64;
assert_approx_eq!(a, b, "0.02");

let a = 66_u128;
let b = 67_u128;
assert_approx_eq!(a, b, "0.02");
}

#[test]
#[should_panic(
expected = "assertion failed: `(left ≈ right)`\nleft: 8\nright: 10\nrelative difference: 0.2\nmax allowed relative difference: 0.12\n"
)]
fn assert_approx_fail() {
assert_approx_eq!(8_u32, 10_u32, "0.12");
}

#[test]
#[should_panic(
expected = "assertion failed: `(left ≈ right)`\nleft: 17\nright: 20\nrelative difference: 0.15\nmax allowed relative difference: 0.12\n: some extra info about the error: Foo(8)"
)]
fn assert_approx_with_custom_panic_msg() {
let adjective = "extra";
#[derive(Debug)]
struct Foo(u32);
assert_approx_eq!(
17_u32,
20_u32,
"0.12",
"some {adjective} {} about the error: {:?}",
"info",
Foo(8),
);
}
}
Original file line number Diff line number Diff line change
@@ -1550,7 +1550,7 @@ mod tests {
});
match result {
SystemResult::Ok(ContractResult::Err(err)) => {
assert_eq!(err, "Error parsing into type cosmwasm_std::mock::tests::wasm_querier_works::{{closure}}::MyMsg: Invalid type")
assert_eq!(err, "Error parsing into type cosmwasm_std::testing::mock::tests::wasm_querier_works::{{closure}}::MyMsg: Invalid type")
}
res => panic!("Unexpected result: {:?}", res),
}
23 changes: 23 additions & 0 deletions packages/std/src/testing/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#![cfg(not(target_arch = "wasm32"))]

// Exposed for testing only
// Both unit tests and integration tests are compiled to native code, so everything in here does not need to compile to Wasm.

mod assertions;
mod mock;

pub use assertions::assert_approx_eq_impl;

#[cfg(feature = "staking")]
pub use mock::StakingQuerier;
pub use mock::{
digit_sum, mock_dependencies, mock_dependencies_with_balance, mock_dependencies_with_balances,
mock_env, mock_info, mock_wasmd_attr, riffle_shuffle, BankQuerier, MockApi, MockQuerier,
MockQuerierCustomHandlerResult, MockStorage, MOCK_CONTRACT_ADDR,
};
#[cfg(feature = "stargate")]
pub use mock::{
mock_ibc_channel, mock_ibc_channel_close_confirm, mock_ibc_channel_close_init,
mock_ibc_channel_connect_ack, mock_ibc_channel_connect_confirm, mock_ibc_channel_open_init,
mock_ibc_channel_open_try, mock_ibc_packet_ack, mock_ibc_packet_recv, mock_ibc_packet_timeout,
};
2 changes: 1 addition & 1 deletion packages/std/src/traits.rs
Original file line number Diff line number Diff line change
@@ -356,7 +356,7 @@ impl<'a, C: CustomQuery> QuerierWrapper<'a, C> {
#[cfg(test)]
mod tests {
use super::*;
use crate::mock::MockQuerier;
use crate::testing::MockQuerier;
use crate::{coins, from_slice, Uint128};

// this is a simple demo helper to prove we can use it

0 comments on commit 8454942

Please sign in to comment.