diff --git a/libwasmvm/src/cache.rs b/libwasmvm/src/cache.rs index e94b4bd3a..932361142 100644 --- a/libwasmvm/src/cache.rs +++ b/libwasmvm/src/cache.rs @@ -328,6 +328,8 @@ pub extern "C" fn release_cache(cache: *mut cache_t) { #[cfg(test)] mod tests { + use crate::assert_approx_eq; + use super::*; use std::iter::FromIterator; use tempfile::TempDir; @@ -711,13 +713,10 @@ mod tests { assert_eq!(misses, 0); assert_eq!(elements_pinned_memory_cache, 1); assert_eq!(elements_memory_cache, 0); - let expected = 5602873; // +/- 20% - assert!( - size_pinned_memory_cache > expected * 80 / 100, - "size_pinned_memory_cache: {size_pinned_memory_cache}" - ); - assert!( - size_pinned_memory_cache < expected * 120 / 100, + assert_approx_eq!( + size_pinned_memory_cache, + 5602873, + "0.2", "size_pinned_memory_cache: {size_pinned_memory_cache}" ); assert_eq!(size_memory_cache, 0); diff --git a/libwasmvm/src/lib.rs b/libwasmvm/src/lib.rs index a4608c9b8..8cf1a0a17 100644 --- a/libwasmvm/src/lib.rs +++ b/libwasmvm/src/lib.rs @@ -12,6 +12,7 @@ mod iterator; mod memory; mod querier; mod storage; +mod test_utils; mod tests; mod version; diff --git a/libwasmvm/src/test_utils.rs b/libwasmvm/src/test_utils.rs new file mode 100644 index 000000000..d6e5f515a --- /dev/null +++ b/libwasmvm/src/test_utils.rs @@ -0,0 +1,102 @@ +#![cfg(test)] + +use cosmwasm_std::{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::test_utils::assert_approx_eq_impl($left, $right, $max_rel_diff, None); + }}; + ($left:expr, $right:expr, $max_rel_diff:expr, $($args:tt)+) => {{ + $crate::test_utils::assert_approx_eq_impl($left, $right, $max_rel_diff, Some(format!($($args)*))); + }}; +} + +#[track_caller] +pub fn assert_approx_eq_impl>( + left: U, + right: U, + max_rel_diff: &str, + panic_msg: Option, +) { + 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 + ), + } + } +} + +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" + )] + fn assert_approx_with_custom_panic_msg() { + assert_approx_eq!( + 17_u32, + 20_u32, + "0.12", + "some extra {} about the error", + "info" + ); + } +}