Skip to content

Commit

Permalink
Merge pull request #1777 from mina86/b
Browse files Browse the repository at this point in the history
cosmwasm_std: remove dependency on DefaultHasher in tests
  • Loading branch information
webmaster128 committed Jul 15, 2023
2 parents 0dae968 + a3c9597 commit aca2de1
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 104 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,6 @@ cosmwasm-crypto = { path = "../crypto", version = "1.3.0-rc.0" }
cosmwasm-schema = { path = "../schema" }
# The chrono dependency is only used in an example, which Rust compiles for us. If this causes trouble, remove it.
chrono = { version = "0.4", default-features = false, features = ["alloc", "std"] }
crc32fast = "1.3.2"
hex-literal = "0.3.1"
serde_json = "1.0.81"
22 changes: 3 additions & 19 deletions packages/std/src/addresses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,11 +399,9 @@ fn hash(ty: &str, key: &[u8]) -> Vec<u8> {
#[cfg(test)]
mod tests {
use super::*;
use crate::HexBinary;
use crate::{assert_hash_works, HexBinary};
use hex_literal::hex;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashSet;
use std::hash::{Hash, Hasher};

#[test]
fn addr_unchecked_works() {
Expand Down Expand Up @@ -651,23 +649,9 @@ mod tests {

#[test]
fn canonical_addr_implements_hash() {
let alice1 = CanonicalAddr::from([0, 187, 61, 11, 250, 0]);
let mut hasher = DefaultHasher::new();
alice1.hash(&mut hasher);
let alice1_hash = hasher.finish();

let alice2 = CanonicalAddr::from([0, 187, 61, 11, 250, 0]);
let mut hasher = DefaultHasher::new();
alice2.hash(&mut hasher);
let alice2_hash = hasher.finish();

let alice = CanonicalAddr::from([0, 187, 61, 11, 250, 0]);
let bob = CanonicalAddr::from([16, 21, 33, 0, 255, 9]);
let mut hasher = DefaultHasher::new();
bob.hash(&mut hasher);
let bob_hash = hasher.finish();

assert_eq!(alice1_hash, alice2_hash);
assert_ne!(alice1_hash, bob_hash);
assert_hash_works!(alice, bob);
}

/// This requires Hash and Eq to be implemented
Expand Down
49 changes: 7 additions & 42 deletions packages/std/src/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,10 @@ impl<'de> de::Visitor<'de> for Base64Visitor {
#[cfg(test)]
mod tests {
use super::*;
use crate::assert_hash_works;
use crate::errors::StdError;
use crate::serde::{from_slice, to_vec};
use std::collections::hash_map::DefaultHasher;
use std::collections::HashSet;
use std::hash::{Hash, Hasher};

#[test]
fn encode_decode() {
Expand Down Expand Up @@ -505,51 +504,17 @@ mod tests {

#[test]
fn binary_implements_as_ref() {
// Can use as_ref (this we already get via the Deref implementation)
let data = Binary(vec![7u8, 35, 49, 101, 0, 255]);
assert_eq!(data.as_ref(), &[7u8, 35, 49, 101, 0, 255]);

let data = Binary(vec![7u8, 35, 49, 101, 0, 255]);
let data_ref = &data;
assert_eq!(data_ref.as_ref(), &[7u8, 35, 49, 101, 0, 255]);

// Implements as ref

// This is a dummy function to mimic the signature of
// https://docs.rs/sha2/0.10.6/sha2/trait.Digest.html#tymethod.digest
fn hash(data: impl AsRef<[u8]>) -> u64 {
let mut hasher = DefaultHasher::new();
data.as_ref().hash(&mut hasher);
hasher.finish()
}

let data = Binary(vec![7u8, 35, 49, 101, 0, 255]);
hash(data);

let data = Binary(vec![7u8, 35, 49, 101, 0, 255]);
let data_ref = &data;
hash(data_ref);
let want = &[7u8, 35, 49, 101, 0, 255];
let data = Binary(want.to_vec());
assert_eq!(want, AsRef::<[u8]>::as_ref(&data));
assert_eq!(want, AsRef::<[u8]>::as_ref(&&data));
}

#[test]
fn binary_implements_hash() {
let a1 = Binary::from([0, 187, 61, 11, 250, 0]);
let mut hasher = DefaultHasher::new();
a1.hash(&mut hasher);
let a1_hash = hasher.finish();

let a2 = Binary::from([0, 187, 61, 11, 250, 0]);
let mut hasher = DefaultHasher::new();
a2.hash(&mut hasher);
let a2_hash = hasher.finish();

let a = Binary::from([0, 187, 61, 11, 250, 0]);
let b = Binary::from([16, 21, 33, 0, 255, 9]);
let mut hasher = DefaultHasher::new();
b.hash(&mut hasher);
let b_hash = hasher.finish();

assert_eq!(a1_hash, a2_hash);
assert_ne!(a1_hash, b_hash);
assert_hash_works!(a, b);
}

/// This requires Hash and Eq to be implemented
Expand Down
50 changes: 7 additions & 43 deletions packages/std/src/hex_binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,8 @@ impl<'de> de::Visitor<'de> for HexVisitor {
mod tests {
use super::*;

use crate::{from_slice, to_vec, StdError};
use std::collections::hash_map::DefaultHasher;
use crate::{assert_hash_works, from_slice, to_vec, StdError};
use std::collections::HashSet;
use std::hash::{Hash, Hasher};

#[test]
fn from_hex_works() {
Expand Down Expand Up @@ -569,51 +567,17 @@ mod tests {

#[test]
fn hex_binary_implements_as_ref() {
// Can use as_ref (this we already get via the Deref implementation)
let data = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
assert_eq!(data.as_ref(), &[7u8, 35, 49, 101, 0, 255]);

let data = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
let data_ref = &data;
assert_eq!(data_ref.as_ref(), &[7u8, 35, 49, 101, 0, 255]);

// Implements as ref

// This is a dummy function to mimic the signature of
// https://docs.rs/sha2/0.10.6/sha2/trait.Digest.html#tymethod.digest
fn hash(data: impl AsRef<[u8]>) -> u64 {
let mut hasher = DefaultHasher::new();
data.as_ref().hash(&mut hasher);
hasher.finish()
}

let data = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
hash(data);

let data = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
let data_ref = &data;
hash(data_ref);
let want = &[7u8, 35, 49, 101, 0, 255];
let data = HexBinary(want.to_vec());
assert_eq!(want, AsRef::<[u8]>::as_ref(&data));
assert_eq!(want, AsRef::<[u8]>::as_ref(&&data));
}

#[test]
fn hex_binary_implements_hash() {
let a1 = HexBinary::from([0, 187, 61, 11, 250, 0]);
let mut hasher = DefaultHasher::new();
a1.hash(&mut hasher);
let a1_hash = hasher.finish();

let a2 = HexBinary::from([0, 187, 61, 11, 250, 0]);
let mut hasher = DefaultHasher::new();
a2.hash(&mut hasher);
let a2_hash = hasher.finish();

let a = HexBinary::from([0, 187, 61, 11, 250, 0]);
let b = HexBinary::from([16, 21, 33, 0, 255, 9]);
let mut hasher = DefaultHasher::new();
b.hash(&mut hasher);
let b_hash = hasher.finish();

assert_eq!(a1_hash, a2_hash);
assert_ne!(a1_hash, b_hash);
assert_hash_works!(a, b);
}

/// This requires Hash and Eq to be implemented
Expand Down
60 changes: 60 additions & 0 deletions packages/std/src/testing/assertions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::{Decimal, Uint128};
#[cfg(test)]
use core::hash::{Hash, Hasher};
use std::str::FromStr as _;

/// Asserts that two expressions are approximately equal to each other.
Expand All @@ -21,6 +23,25 @@ macro_rules! assert_approx_eq {
}};
}

/// Asserts that type `T` implements `Hash` trait correctly.
///
/// `left` and `right` must be unequal objects.
///
/// Some object pairs may produce the same hash causing test failure.
/// In those cases try different objects. The test uses stable hasher
/// so once working pair is identified, the test’s going to continue
/// passing.
#[macro_export]
#[cfg(test)]
macro_rules! assert_hash_works {
($left:expr, $right:expr $(,)?) => {{
$crate::testing::assert_hash_works_impl($left, $right, None);
}};
($left:expr, $right:expr, $($args:tt)+) => {{
$crate::testing::assert_hash_works_impl($left, $right, 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]
Expand Down Expand Up @@ -50,6 +71,45 @@ pub fn assert_approx_eq_impl<U: Into<Uint128>>(
}
}

/// Tests that type `T` implements `Hash` trait correctly.
///
/// `left` and `right` must be unequal objects.
///
/// Some object pairs may produce the same hash causing test failure.
/// In those cases try different objects. The test uses stable hasher
/// so once working pair is identified, the test’s going to continue
/// passing.
#[track_caller]
#[doc(hidden)]
#[cfg(test)]
pub fn assert_hash_works_impl<T: Clone + Hash>(left: T, right: T, panic_msg: Option<String>) {
fn hash(value: &impl Hash) -> u64 {
let mut hasher = crc32fast::Hasher::default();
value.hash(&mut hasher);
hasher.finish()
}

// Check clone
if hash(&left) != hash(&left.clone()) {
match panic_msg {
Some(panic_msg) => {
panic!("assertion failed: `hash(left) == hash(left.clone())`\n: {panic_msg}")
}
None => panic!("assertion failed: `hash(left) == hash(left.clone())`"),
}
}

// Check different object
if hash(&left) == hash(&right) {
match panic_msg {
Some(panic_msg) => {
panic!("assertion failed: `hash(left) != hash(right)`\n: {panic_msg}")
}
None => panic!("assertion failed: `hash(left) != hash(right)`"),
}
}
}

#[cfg(test)]
mod tests {
#[test]
Expand Down
2 changes: 2 additions & 0 deletions packages/std/src/testing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ mod mock;
mod shuffle;

pub use assertions::assert_approx_eq_impl;
#[cfg(test)]
pub use assertions::assert_hash_works_impl;

#[cfg(feature = "cosmwasm_1_3")]
pub use mock::DistributionQuerier;
Expand Down

0 comments on commit aca2de1

Please sign in to comment.