]> git.lizzy.rs Git - rust.git/blob - library/core/tests/hash/mod.rs
Rollup merge of #100188 - chenyukang:fix-issue-100165, r=estebank
[rust.git] / library / core / tests / hash / mod.rs
1 mod sip;
2
3 use std::default::Default;
4 use std::hash::{BuildHasher, Hash, Hasher};
5 use std::ptr;
6 use std::rc::Rc;
7
8 struct MyHasher {
9     hash: u64,
10 }
11
12 impl Default for MyHasher {
13     fn default() -> MyHasher {
14         MyHasher { hash: 0 }
15     }
16 }
17
18 impl Hasher for MyHasher {
19     fn write(&mut self, buf: &[u8]) {
20         for byte in buf {
21             self.hash += *byte as u64;
22         }
23     }
24     fn write_str(&mut self, s: &str) {
25         self.write(s.as_bytes());
26         self.write_u8(0xFF);
27     }
28     fn finish(&self) -> u64 {
29         self.hash
30     }
31 }
32
33 #[test]
34 fn test_writer_hasher() {
35     fn hash<T: Hash>(t: &T) -> u64 {
36         let mut s = MyHasher { hash: 0 };
37         t.hash(&mut s);
38         s.finish()
39     }
40
41     assert_eq!(hash(&()), 0);
42
43     assert_eq!(hash(&5_u8), 5);
44     assert_eq!(hash(&5_u16), 5);
45     assert_eq!(hash(&5_u32), 5);
46     assert_eq!(hash(&5_u64), 5);
47     assert_eq!(hash(&5_usize), 5);
48
49     assert_eq!(hash(&5_i8), 5);
50     assert_eq!(hash(&5_i16), 5);
51     assert_eq!(hash(&5_i32), 5);
52     assert_eq!(hash(&5_i64), 5);
53     assert_eq!(hash(&5_isize), 5);
54
55     assert_eq!(hash(&false), 0);
56     assert_eq!(hash(&true), 1);
57
58     assert_eq!(hash(&'a'), 97);
59
60     let s: &str = "a";
61     assert_eq!(hash(&s), 97 + 0xFF);
62     let s: Box<str> = String::from("a").into_boxed_str();
63     assert_eq!(hash(&s), 97 + 0xFF);
64     let s: Rc<&str> = Rc::new("a");
65     assert_eq!(hash(&s), 97 + 0xFF);
66     let cs: &[u8] = &[1, 2, 3];
67     assert_eq!(hash(&cs), 9);
68     let cs: Box<[u8]> = Box::new([1, 2, 3]);
69     assert_eq!(hash(&cs), 9);
70     let cs: Rc<[u8]> = Rc::new([1, 2, 3]);
71     assert_eq!(hash(&cs), 9);
72
73     let ptr = ptr::invalid::<i32>(5_usize);
74     assert_eq!(hash(&ptr), 5);
75
76     let ptr = ptr::invalid_mut::<i32>(5_usize);
77     assert_eq!(hash(&ptr), 5);
78
79     if cfg!(miri) {
80         // Miri cannot hash pointers
81         return;
82     }
83
84     let cs: &mut [u8] = &mut [1, 2, 3];
85     let ptr = cs.as_ptr();
86     let slice_ptr = cs as *const [u8];
87     assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64);
88
89     let slice_ptr = cs as *mut [u8];
90     assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64);
91 }
92
93 struct Custom {
94     hash: u64,
95 }
96 struct CustomHasher {
97     output: u64,
98 }
99
100 impl Hasher for CustomHasher {
101     fn finish(&self) -> u64 {
102         self.output
103     }
104     fn write(&mut self, _: &[u8]) {
105         panic!()
106     }
107     fn write_u64(&mut self, data: u64) {
108         self.output = data;
109     }
110 }
111
112 impl Default for CustomHasher {
113     fn default() -> CustomHasher {
114         CustomHasher { output: 0 }
115     }
116 }
117
118 impl Hash for Custom {
119     fn hash<H: Hasher>(&self, state: &mut H) {
120         state.write_u64(self.hash);
121     }
122 }
123
124 #[test]
125 fn test_custom_state() {
126     fn hash<T: Hash>(t: &T) -> u64 {
127         let mut c = CustomHasher { output: 0 };
128         t.hash(&mut c);
129         c.finish()
130     }
131
132     assert_eq!(hash(&Custom { hash: 5 }), 5);
133 }
134
135 // FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten.
136 // See https://github.com/kripken/emscripten-fastcomp/issues/169
137 #[cfg(not(target_os = "emscripten"))]
138 #[test]
139 fn test_indirect_hasher() {
140     let mut hasher = MyHasher { hash: 0 };
141     {
142         let mut indirect_hasher: &mut dyn Hasher = &mut hasher;
143         5u32.hash(&mut indirect_hasher);
144     }
145     assert_eq!(hasher.hash, 5);
146 }
147
148 #[test]
149 fn test_build_hasher_object_safe() {
150     use std::collections::hash_map::{DefaultHasher, RandomState};
151
152     let _: &dyn BuildHasher<Hasher = DefaultHasher> = &RandomState::new();
153 }
154
155 // just tests by whether or not this compiles
156 fn _build_hasher_default_impl_all_auto_traits<T>() {
157     use std::panic::{RefUnwindSafe, UnwindSafe};
158     fn all_auto_traits<T: Send + Sync + Unpin + UnwindSafe + RefUnwindSafe>() {}
159
160     all_auto_traits::<std::hash::BuildHasherDefault<T>>();
161 }