Skip to main content

spideroak_crypto/test_util/
hash.rs

1//! [`Hash`] tests.
2
3use crate::hash::Hash;
4
5/// Invokes `callback` for each hash test.
6///
7/// # Example
8///
9/// ```
10/// use spideroak_crypto::rust::Sha256;
11///
12/// macro_rules! run_test {
13///     ($test:ident) => {
14///         spideroak_crypto::test_util::hash::$test::<Sha256>();
15///     };
16/// }
17/// spideroak_crypto::for_each_hash_test!(run_test);
18/// ```
19#[macro_export]
20macro_rules! for_each_hash_test {
21    ($callback:ident) => {
22        $crate::__apply! {
23            $callback,
24            test_basic,
25        }
26    };
27}
28pub use for_each_hash_test;
29
30/// Performs all of the tests in this module.
31///
32/// This macro expands into a bunch of individual `#[test]`
33/// functions.
34///
35/// # Example
36///
37/// ```
38/// use spideroak_crypto::{test_hash, rust::Sha256};
39///
40/// test_hash!(sha256, Sha256);
41/// ```
42#[macro_export]
43macro_rules! test_hash {
44    ($name:ident, $hash:ty) => {
45        mod $name {
46            #[allow(unused_imports)]
47            use super::*;
48
49            $crate::test_hash!($hash);
50        }
51    };
52    ($hash:ty) => {
53        macro_rules! __hash_test {
54            ($test:ident) => {
55                #[test]
56                fn $test() {
57                    $crate::test_util::hash::$test::<$hash>()
58                }
59            };
60        }
61        $crate::for_each_hash_test!(__hash_test);
62    };
63}
64pub use test_hash;
65
66/// A basic test for a `Hash`.
67pub fn test_basic<T: Hash>() {
68    const INPUT: &[u8] = r#"
69Sir, in my heart there was a kind of fighting
70That would not let me sleep. Methought I lay
71Worse than the mutines in the bilboes. Rashly—
72And prais'd be rashness for it—let us know
73Our indiscretion sometimes serves us well ...
74"#
75    .as_bytes();
76
77    let want = T::hash(INPUT);
78
79    let got = {
80        // Repeated calls to `update` should be the same as
81        // calling `hash` directly.
82        let mut h = T::new();
83        for c in INPUT {
84            h.update(&[*c]);
85        }
86        h.digest()
87    };
88    assert_eq!(want, got);
89
90    // Hashing the same input should result in the same
91    // output.
92    assert_eq!(want, T::hash(INPUT));
93
94    // A modified input should have a different hash, though.
95    let mut modified = INPUT.to_vec();
96    modified[0] += 1;
97    assert_ne!(want, T::hash(&modified[..]));
98}