|
| 1 | +// SPDX-License-Identifier: CC0-1.0 |
| 2 | + |
| 3 | +//! Test the API surface of `units`. |
| 4 | +//! |
| 5 | +//! The point of these tests are to check the API surface as opposed to test the API functionality. |
| 6 | +//! |
| 7 | +//! ref: <https://rust-lang.github.io/api-guidelines/about.html> |
| 8 | +
|
| 9 | +#![allow(dead_code)] |
| 10 | +#![allow(unused_imports)] |
| 11 | + |
| 12 | +// Import using module style e.g., `sha256::Hash`. |
| 13 | +use bitcoin_hashes::{ |
| 14 | + hash160, hash_newtype, hkdf, hmac, ripemd160, sha1, sha256, sha256d, sha256t, sha256t_tag, |
| 15 | + sha384, sha512, sha512_256, siphash24, FromSliceError, Hash, HashEngine, |
| 16 | +}; |
| 17 | +// Import using type alias style e.g., `Sha256`. |
| 18 | +use bitcoin_hashes::{ |
| 19 | + Hash160, Hkdf, Hmac, HmacEngine, Ripemd160, Sha1, Sha256, Sha256d, Sha256t, Sha384, Sha512, |
| 20 | + Sha512_256, Siphash24, |
| 21 | +}; |
| 22 | + |
| 23 | +// Arbitrary midstate value; taken from as sha256t unit tests. |
| 24 | +const TEST_MIDSTATE: [u8; 32] = [ |
| 25 | + 156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, 147, 108, |
| 26 | + 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201, |
| 27 | +]; |
| 28 | + |
| 29 | +sha256t_tag! { |
| 30 | + /// Test tag so we don't have to use generics. |
| 31 | + #[derive(Debug)] |
| 32 | + struct Tag = raw(TEST_MIDSTATE, 64); |
| 33 | +} |
| 34 | +hash_newtype! { |
| 35 | + /// A concrete sha256t hash type so we don't have to use generics. |
| 36 | + #[derive(Debug)] |
| 37 | + struct TaggedHash(sha256t::Hash<Tag>); |
| 38 | +} |
| 39 | + |
| 40 | +/// All the hash types excluding `Hkdf`. |
| 41 | +// `Hkdf` only implements `Copy` and `Clone` ATM - by design. |
| 42 | +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] // C-COMMON-TRAITS |
| 43 | +// We check `Hkdf` implements `Debug` in the non-empty debug test below. |
| 44 | +#[derive(Debug)] // All public types implement Debug (C-DEBUG). |
| 45 | +struct Hashes<T: Hash> { |
| 46 | + a: hash160::Hash, |
| 47 | + c: Hmac<T>, |
| 48 | + d: ripemd160::Hash, |
| 49 | + e: sha1::Hash, |
| 50 | + f: sha256::Hash, |
| 51 | + g: sha256d::Hash, |
| 52 | + h: TaggedHash, |
| 53 | + i: sha384::Hash, |
| 54 | + j: sha512::Hash, |
| 55 | + k: sha512_256::Hash, |
| 56 | + l: siphash24::Hash, |
| 57 | +} |
| 58 | + |
| 59 | +impl Hashes<Sha256> { |
| 60 | + fn new_sha256() -> Self { |
| 61 | + let hmac = HmacEngine::<sha256::HashEngine>::new(&[]).finalize(); |
| 62 | + // `TaggedHash` is not a general hash but `Sha256<Tag>` is. |
| 63 | + let tagged = TaggedHash::from_byte_array(Sha256t::<Tag>::hash(&[]).to_byte_array()); |
| 64 | + let siphash = Siphash24::from_engine(siphash24::HashEngine::with_keys(0, 0)); |
| 65 | + |
| 66 | + Hashes { |
| 67 | + a: Hash160::hash(&[]), |
| 68 | + // b: hkdf, |
| 69 | + c: hmac, |
| 70 | + d: Ripemd160::hash(&[]), |
| 71 | + e: Sha1::hash(&[]), |
| 72 | + f: Sha256::hash(&[]), |
| 73 | + g: Sha256d::hash(&[]), |
| 74 | + h: tagged, |
| 75 | + i: Sha384::hash(&[]), |
| 76 | + j: Sha512::hash(&[]), |
| 77 | + k: Sha512_256::hash(&[]), |
| 78 | + l: siphash, |
| 79 | + } |
| 80 | + } |
| 81 | +} |
| 82 | + |
| 83 | +/// All the hash engines. |
| 84 | +#[derive(Clone)] // C-COMMON-TRAITS |
| 85 | +#[derive(Debug)] // All public types implement Debug (C-DEBUG). |
| 86 | +struct Engines { |
| 87 | + a: hash160::HashEngine, |
| 88 | + // We cannot derive `Debug` on a generic `HmacEngine<T>` engine. |
| 89 | + b: hmac::HmacEngine<sha256::HashEngine>, |
| 90 | + c: ripemd160::HashEngine, |
| 91 | + d: sha1::HashEngine, |
| 92 | + e: sha256::HashEngine, |
| 93 | + f: sha256d::HashEngine, |
| 94 | + g: sha256t::HashEngine<Tag>, |
| 95 | + h: sha384::HashEngine, |
| 96 | + i: sha512::HashEngine, |
| 97 | + j: sha512_256::HashEngine, |
| 98 | + k: siphash24::HashEngine, |
| 99 | +} |
| 100 | + |
| 101 | +impl Engines { |
| 102 | + fn new_sha256() -> Self { |
| 103 | + Engines { |
| 104 | + a: hash160::HashEngine::new(), |
| 105 | + b: hmac::HmacEngine::<sha256::HashEngine>::new(&[]), |
| 106 | + c: ripemd160::HashEngine::new(), |
| 107 | + d: sha1::HashEngine::new(), |
| 108 | + e: sha256::HashEngine::new(), |
| 109 | + f: sha256d::HashEngine::new(), |
| 110 | + g: sha256t::Hash::<Tag>::engine(), |
| 111 | + h: sha384::HashEngine::new(), |
| 112 | + i: sha512::HashEngine::new(), |
| 113 | + j: sha512_256::HashEngine::new(), |
| 114 | + k: siphash24::HashEngine::with_keys(0, 0), |
| 115 | + } |
| 116 | + } |
| 117 | +} |
| 118 | + |
| 119 | +/// Public structs that are not hashes, engines, or errors. |
| 120 | +#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] // C-COMMON-TRAITS |
| 121 | +#[derive(Debug)] // All public types implement Debug (C-DEBUG). |
| 122 | +struct OtherStructs { |
| 123 | + a: sha256::Midstate, |
| 124 | + // There is no way to construct a `siphash24::State` so we cannot directly |
| 125 | + // test it but `siphash24::HashEngine` includes one so `Engines` implicitly |
| 126 | + // tests it (e.g. `Debug` and `Clone`). |
| 127 | + // |
| 128 | + // b: siphash24::State, |
| 129 | + |
| 130 | + // Don't worry about including a tag because its tested in `primitives`. |
| 131 | +} |
| 132 | + |
| 133 | +impl OtherStructs { |
| 134 | + fn new() -> Self { Self { a: sha256::Midstate::new(TEST_MIDSTATE, 0) } } |
| 135 | +} |
| 136 | + |
| 137 | +/// All hash engine types that implement `Default`. |
| 138 | +#[derive(Default)] |
| 139 | +struct Default { |
| 140 | + a: hash160::HashEngine, |
| 141 | + b: ripemd160::HashEngine, |
| 142 | + c: sha1::HashEngine, |
| 143 | + d: sha256::HashEngine, |
| 144 | + e: sha256d::HashEngine, |
| 145 | + f: sha256t::HashEngine<Tag>, |
| 146 | + g: sha384::HashEngine, |
| 147 | + h: sha512::HashEngine, |
| 148 | + i: sha512_256::HashEngine, |
| 149 | +} |
| 150 | + |
| 151 | +/// Hash types that require a key. |
| 152 | +struct Keyed<T: Hash> { |
| 153 | + a: Hmac<T>, |
| 154 | + l: siphash24::Hash, |
| 155 | +} |
| 156 | + |
| 157 | +/// A struct that includes all public error types. |
| 158 | +// These derives are the policy of `rust-bitcoin` not Rust API guidelines. |
| 159 | +#[derive(Debug, Clone, PartialEq, Eq)] // All public types implement Debug (C-DEBUG). |
| 160 | +struct Errors { |
| 161 | + a: FromSliceError, |
| 162 | + b: hkdf::MaxLengthError, |
| 163 | + c: sha256::MidstateError, |
| 164 | +} |
| 165 | + |
| 166 | +#[test] |
| 167 | +fn api_can_use_modules_from_crate_root() { |
| 168 | + use bitcoin_hashes::{ |
| 169 | + hash160, hkdf, hmac, ripemd160, sha1, sha256, sha256d, sha256t, sha384, sha512, sha512_256, |
| 170 | + siphash24, |
| 171 | + }; |
| 172 | +} |
| 173 | + |
| 174 | +#[test] |
| 175 | +fn api_can_use_alias_from_crate_root() { |
| 176 | + use bitcoin_hashes::{ |
| 177 | + Hash160, Hkdf, Hmac, Ripemd160, Sha1, Sha256, Sha256d, Sha256t, Sha384, Sha512, Sha512_256, |
| 178 | + Siphash24, |
| 179 | + }; |
| 180 | +} |
| 181 | + |
| 182 | +// `Debug` representation is never empty (C-DEBUG-NONEMPTY). |
| 183 | +#[test] |
| 184 | +fn api_all_non_error_types_have_non_empty_debug() { |
| 185 | + macro_rules! check_debug { |
| 186 | + ($t:tt; $($field:tt),* $(,)?) => { |
| 187 | + $( |
| 188 | + let debug = format!("{:?}", $t.$field); |
| 189 | + assert!(!debug.is_empty()); |
| 190 | + )* |
| 191 | + } |
| 192 | + } |
| 193 | + |
| 194 | + let t = Hashes::<Sha256>::new_sha256(); |
| 195 | + check_debug!(t; a, c, d, e, f, g, h, i, j, k, l); |
| 196 | + |
| 197 | + // This tests `Debug` on `Hkdf` but not for all `T: GeneralHash`. |
| 198 | + let t = Hkdf::<sha256::HashEngine>::new(&[], &[]); |
| 199 | + let debug = format!("{:?}", t); |
| 200 | + assert!(!debug.is_empty()); |
| 201 | + |
| 202 | + let t = Engines::new_sha256(); |
| 203 | + check_debug!(t; a, c, d, e, f, g, h, i, j, k); |
| 204 | + |
| 205 | + let t = OtherStructs::new(); |
| 206 | + check_debug!(t; a); |
| 207 | +} |
| 208 | + |
| 209 | +#[test] |
| 210 | +fn all_types_implement_send_sync() { |
| 211 | + fn assert_send<T: Send>() {} |
| 212 | + fn assert_sync<T: Sync>() {} |
| 213 | + |
| 214 | + // Types are `Send` and `Sync` where possible (C-SEND-SYNC). |
| 215 | + assert_send::<Hashes<Sha256>>(); |
| 216 | + assert_sync::<Hashes<Sha256>>(); |
| 217 | + assert_send::<Engines>(); |
| 218 | + assert_sync::<Engines>(); |
| 219 | + assert_send::<OtherStructs>(); |
| 220 | + assert_sync::<OtherStructs>(); |
| 221 | + |
| 222 | + // Error types should implement the Send and Sync traits (C-GOOD-ERR). |
| 223 | + assert_send::<Errors>(); |
| 224 | + assert_sync::<Errors>(); |
| 225 | +} |
0 commit comments