ps_hash_core/hash/implementations/
hash_trait.rs1use super::super::Hash;
2
3impl std::hash::Hash for Hash {
4 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
5 state.write(&self.inner);
6 }
7}
8
9#[cfg(test)]
10#[allow(clippy::expect_used)]
11mod tests {
12 use std::collections::{HashMap, HashSet};
13 use std::hash::{DefaultHasher, Hash as StdHash, Hasher};
14
15 use crate::Hash;
16
17 fn compute_hash<T: StdHash>(t: &T) -> u64 {
18 let mut hasher = DefaultHasher::new();
19 t.hash(&mut hasher);
20 hasher.finish()
21 }
22
23 #[test]
24 fn hash_deterministic() {
25 let h = Hash::hash(b"deterministic").expect("hashing should succeed");
26 let hash1 = compute_hash(&h);
27 let hash2 = compute_hash(&h);
28 assert_eq!(hash1, hash2);
29 }
30
31 #[test]
32 fn hash_same_for_equal_hashes() {
33 let h1 = Hash::hash(b"same").expect("hashing should succeed");
34 let h2 = Hash::hash(b"same").expect("hashing should succeed");
35 assert_eq!(compute_hash(&h1), compute_hash(&h2));
36 }
37
38 #[test]
39 fn hash_different_for_different_hashes() {
40 let h1 = Hash::hash(b"diff1").expect("hashing should succeed");
41 let h2 = Hash::hash(b"diff2").expect("hashing should succeed");
42 assert_ne!(compute_hash(&h1), compute_hash(&h2));
43 }
44
45 #[test]
46 fn hash_enables_hashset() {
47 let mut set = HashSet::new();
48 set.insert(Hash::hash(b"a").expect("hashing should succeed"));
49 set.insert(Hash::hash(b"b").expect("hashing should succeed"));
50 set.insert(Hash::hash(b"a").expect("hashing should succeed"));
51 assert_eq!(set.len(), 2);
52 }
53
54 #[test]
55 fn hash_enables_hashmap_key() {
56 let mut map = HashMap::new();
57 let h1 = Hash::hash(b"key1").expect("hashing should succeed");
58 let h2 = Hash::hash(b"key2").expect("hashing should succeed");
59 map.insert(h1, "value1");
60 map.insert(h2, "value2");
61 assert_eq!(map.get(&h1), Some(&"value1"));
62 assert_eq!(map.get(&h2), Some(&"value2"));
63 }
64
65 #[test]
66 fn hash_lookup_works() {
67 let mut set = HashSet::new();
68 let original = Hash::hash(b"lookup").expect("hashing should succeed");
69 set.insert(original);
70
71 let same = Hash::hash(b"lookup").expect("hashing should succeed");
72 assert!(set.contains(&same));
73 }
74
75 #[test]
76 fn hash_lookup_after_validation() {
77 let mut set = HashSet::new();
78 let original = Hash::hash(b"validated").expect("hashing should succeed");
79 set.insert(original);
80
81 let validated = Hash::validate(original.to_string())
82 .expect("validation of an uncorrupted hash should succeed");
83 assert!(set.contains(&validated));
84 }
85
86 #[test]
87 fn hash_consistent_with_eq() {
88 let h1 = Hash::hash(b"consistent").expect("hashing should succeed");
89 let h2 = Hash::hash(b"consistent").expect("hashing should succeed");
90
91 if h1 == h2 {
92 assert_eq!(compute_hash(&h1), compute_hash(&h2));
93 }
94 }
95
96 #[test]
97 fn hash_trait_bound() {
98 fn assert_hash<T: StdHash>() {}
99 assert_hash::<Hash>();
100 }
101
102 #[test]
103 fn hash_after_corruption_recovery() {
104 let mut set = HashSet::new();
105 let original = Hash::hash(b"recovery").expect("hashing should succeed");
106 set.insert(original);
107
108 let mut corrupted = original.to_string().into_bytes();
109 corrupted[5] = if corrupted[5] == b'A' { b'B' } else { b'A' };
112 let recovered = Hash::validate(
113 String::from_utf8(corrupted).expect("corrupted bytes should be valid UTF-8"),
114 )
115 .expect("single-character corruption should be recovered");
116 assert!(set.contains(&recovered));
117 }
118
119 #[test]
120 fn hash_many_insertions() {
121 let mut set = HashSet::new();
122
123 for i in 0u32..100 {
124 let h = Hash::hash(i.to_le_bytes()).expect("hashing should succeed");
125 set.insert(h);
126 }
127
128 assert_eq!(set.len(), 100);
129 }
130}