]>
Commit | Line | Data |
---|---|---|
ba9703b0 | 1 | use super::{Input, VariableOutput, ExtendableOutput, Reset, XofReader}; |
9fa01778 XL |
2 | use core::fmt::Debug; |
3 | ||
9fa01778 | 4 | #[macro_export] |
ba9703b0 XL |
5 | macro_rules! new_test { |
6 | ($name:ident, $test_name:expr, $hasher:ty, $test_func:ident) => { | |
7 | #[test] | |
8 | fn $name() { | |
9 | use digest::blobby::Blob2Iterator; | |
10 | let data = include_bytes!(concat!("data/", $test_name, ".blb")); | |
11 | ||
12 | for (i, row) in Blob2Iterator::new(data).unwrap().enumerate() { | |
13 | let input = row[0]; | |
14 | let output = row[1]; | |
15 | if let Some(desc) = $test_func::<$hasher>(input, output) { | |
16 | panic!("\n\ | |
17 | Failed test №{}: {}\n\ | |
18 | input:\t{:?}\n\ | |
19 | output:\t{:?}\n", | |
20 | i, desc, input, output, | |
21 | ); | |
22 | } | |
23 | } | |
24 | } | |
25 | } | |
9fa01778 XL |
26 | } |
27 | ||
ba9703b0 XL |
28 | // module to separate Digest from other traits |
29 | mod foo { | |
30 | use super::super::Digest; | |
31 | use core::fmt::Debug; | |
32 | ||
33 | pub fn digest_test<D>(input: &[u8], output: &[u8]) -> Option<&'static str> | |
34 | where D: Digest + Debug + Clone | |
35 | { | |
36 | let mut hasher = D::new(); | |
37 | // Test that it works when accepting the message all at once | |
38 | hasher.input(input); | |
39 | let mut hasher2 = hasher.clone(); | |
40 | if hasher.result().as_slice() != output { | |
41 | return Some("whole message"); | |
42 | } | |
9fa01778 | 43 | |
ba9703b0 XL |
44 | // Test if reset works correctly |
45 | hasher2.reset(); | |
46 | hasher2.input(input); | |
47 | if hasher2.result().as_slice() != output { | |
48 | return Some("whole message after reset"); | |
49 | } | |
9fa01778 | 50 | |
ba9703b0 XL |
51 | // Test that it works when accepting the message in pieces |
52 | let mut hasher = D::new(); | |
53 | let len = input.len(); | |
9fa01778 XL |
54 | let mut left = len; |
55 | while left > 0 { | |
56 | let take = (left + 1) / 2; | |
ba9703b0 | 57 | hasher.input(&input[len - left..take + len - left]); |
9fa01778 XL |
58 | left = left - take; |
59 | } | |
ba9703b0 XL |
60 | if hasher.result().as_slice() != output { |
61 | return Some("message in pieces"); | |
62 | } | |
63 | ||
64 | // Test processing byte-by-byte | |
65 | let mut hasher = D::new(); | |
66 | for chunk in input.chunks(1) { | |
67 | hasher.input(chunk) | |
68 | } | |
69 | if hasher.result().as_slice() != output { | |
70 | return Some("message byte-by-byte"); | |
71 | } | |
72 | None | |
73 | } | |
9fa01778 | 74 | |
9fa01778 | 75 | |
ba9703b0 XL |
76 | pub fn one_million_a<D>(expected: &[u8]) |
77 | where D: Digest + Debug + Clone | |
78 | { | |
79 | let mut sh = D::new(); | |
80 | for _ in 0..50_000 { | |
81 | sh.input(&[b'a'; 10]); | |
82 | } | |
83 | sh.input(&[b'a'; 500_000][..]); | |
84 | let out = sh.result(); | |
85 | assert_eq!(out[..], expected[..]); | |
9fa01778 XL |
86 | } |
87 | } | |
88 | ||
ba9703b0 XL |
89 | pub use self::foo::{digest_test, one_million_a}; |
90 | ||
91 | pub fn xof_test<D>(input: &[u8], output: &[u8]) | |
92 | -> Option<&'static str> | |
93 | where D: Input + ExtendableOutput + Default + Debug + Reset + Clone | |
9fa01778 | 94 | { |
ba9703b0 | 95 | let mut hasher = D::default(); |
9fa01778 XL |
96 | let mut buf = [0u8; 1024]; |
97 | // Test that it works when accepting the message all at once | |
ba9703b0 | 98 | hasher.input(input); |
9fa01778 | 99 | |
ba9703b0 XL |
100 | let mut hasher2 = hasher.clone(); |
101 | { | |
102 | let out = &mut buf[..output.len()]; | |
103 | hasher.xof_result().read(out); | |
9fa01778 | 104 | |
ba9703b0 | 105 | if out != output { return Some("whole message"); } |
9fa01778 XL |
106 | } |
107 | ||
ba9703b0 XL |
108 | // Test if hasher resets correctly |
109 | hasher2.reset(); | |
110 | hasher2.input(input); | |
9fa01778 | 111 | |
ba9703b0 XL |
112 | { |
113 | let out = &mut buf[..output.len()]; | |
114 | hasher2.xof_result().read(out); | |
9fa01778 | 115 | |
ba9703b0 | 116 | if out != output { return Some("whole message after reset"); } |
9fa01778 | 117 | } |
9fa01778 | 118 | |
ba9703b0 XL |
119 | // Test if hasher accepts message in pieces correctly |
120 | let mut hasher = D::default(); | |
121 | let len = input.len(); | |
122 | let mut left = len; | |
123 | while left > 0 { | |
124 | let take = (left + 1) / 2; | |
125 | hasher.input(&input[len - left..take + len - left]); | |
126 | left = left - take; | |
9fa01778 XL |
127 | } |
128 | ||
ba9703b0 XL |
129 | { |
130 | let out = &mut buf[..output.len()]; | |
131 | hasher.xof_result().read(out); | |
132 | if out != output { return Some("message in pieces"); } | |
133 | } | |
9fa01778 | 134 | |
ba9703b0 XL |
135 | // Test reading from reader byte by byte |
136 | let mut hasher = D::default(); | |
137 | hasher.input(input); | |
9fa01778 | 138 | |
ba9703b0 XL |
139 | let mut reader = hasher.xof_result(); |
140 | let out = &mut buf[..output.len()]; | |
141 | for chunk in out.chunks_mut(1) { | |
142 | reader.read(chunk); | |
9fa01778 XL |
143 | } |
144 | ||
ba9703b0 XL |
145 | if out != output { return Some("message in pieces"); } |
146 | None | |
147 | } | |
148 | ||
149 | pub fn variable_test<D>(input: &[u8], output: &[u8]) | |
150 | -> Option<&'static str> | |
151 | where D: Input + VariableOutput + Reset + Debug + Clone | |
152 | { | |
153 | let mut hasher = D::new(output.len()).unwrap(); | |
154 | let mut buf = [0u8; 128]; | |
155 | let buf = &mut buf[..output.len()]; | |
156 | // Test that it works when accepting the message all at once | |
157 | hasher.input(input); | |
158 | let mut hasher2 = hasher.clone(); | |
159 | hasher.variable_result(|res| buf.copy_from_slice(res)); | |
160 | if buf != output { return Some("whole message"); } | |
9fa01778 | 161 | |
ba9703b0 XL |
162 | // Test if reset works correctly |
163 | hasher2.reset(); | |
164 | hasher2.input(input); | |
165 | hasher2.variable_result(|res| buf.copy_from_slice(res)); | |
166 | if buf != output { return Some("whole message after reset"); } | |
9fa01778 | 167 | |
ba9703b0 XL |
168 | // Test that it works when accepting the message in pieces |
169 | let mut hasher = D::new(output.len()).unwrap(); | |
170 | let len = input.len(); | |
171 | let mut left = len; | |
172 | while left > 0 { | |
173 | let take = (left + 1) / 2; | |
174 | hasher.input(&input[len - left..take + len - left]); | |
175 | left = left - take; | |
9fa01778 | 176 | } |
ba9703b0 XL |
177 | hasher.variable_result(|res| buf.copy_from_slice(res)); |
178 | if buf != output { return Some("message in pieces"); } | |
9fa01778 | 179 | |
ba9703b0 XL |
180 | // Test processing byte-by-byte |
181 | let mut hasher = D::new(output.len()).unwrap(); | |
182 | for chunk in input.chunks(1) { | |
183 | hasher.input(chunk) | |
9fa01778 | 184 | } |
ba9703b0 XL |
185 | hasher.variable_result(|res| buf.copy_from_slice(res)); |
186 | if buf != output { return Some("message byte-by-byte"); } | |
187 | None | |
9fa01778 XL |
188 | } |
189 | ||
190 | ||
191 | #[macro_export] | |
ba9703b0 | 192 | macro_rules! bench { |
9fa01778 XL |
193 | ($name:ident, $engine:path, $bs:expr) => { |
194 | #[bench] | |
195 | fn $name(b: &mut Bencher) { | |
196 | let mut d = <$engine>::default(); | |
197 | let data = [0; $bs]; | |
198 | ||
199 | b.iter(|| { | |
ba9703b0 | 200 | d.input(&data[..]); |
9fa01778 XL |
201 | }); |
202 | ||
203 | b.bytes = $bs; | |
204 | } | |
205 | }; | |
206 | ||
207 | ($engine:path) => { | |
208 | extern crate test; | |
209 | ||
210 | use test::Bencher; | |
211 | use digest::Digest; | |
212 | ||
ba9703b0 XL |
213 | bench!(bench1_10, $engine, 10); |
214 | bench!(bench2_100, $engine, 100); | |
215 | bench!(bench3_1000, $engine, 1000); | |
216 | bench!(bench4_10000, $engine, 10000); | |
9fa01778 XL |
217 | } |
218 | } |