test(nix-compat/nixhash): rework NixHash::from_str tests
The test code was way too complicated. We had testcases manually constructing different NixHash as an input, extracted digest and algo, then manually encoded them with various encodings, to then compare to itself. Instead, write out these different string inputs as explicit testcases. Change-Id: I2adeedcb9ddc8b3d50f8bdab09a1e95198cda402 Reviewed-on: https://cl.snix.dev/c/snix/+/30560 Reviewed-by: edef <edef@edef.eu> Tested-by: besadii Autosubmit: Florian Klink <flokli@flokli.de>
This commit is contained in:
parent
ea861bba67
commit
2dfbfebb47
1 changed files with 92 additions and 123 deletions
|
|
@ -313,139 +313,108 @@ fn decode_digest(s: &[u8], algo: HashAlgo) -> NixHashResult<NixHash> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
nixbase32,
|
||||
nixhash::{HashAlgo, NixHash},
|
||||
};
|
||||
use data_encoding::{BASE64, BASE64_NOPAD, HEXLOWER};
|
||||
use crate::nixhash::{HashAlgo, NixHash};
|
||||
use hex_literal::hex;
|
||||
use rstest::rstest;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
const DIGEST_SHA1: [u8; 20] = hex!("6016777997c30ab02413cf5095622cd7924283ac");
|
||||
const DIGEST_SHA256: [u8; 32] =
|
||||
hex!("a5ce9c155ed09397614646c9717fc7cd94b1023d7b76b618d409e4fefd6e9d39");
|
||||
const DIGEST_SHA512: [u8; 64] = hex!("ab40d0be3541f0774bba7815d13d10b03252e96e95f7dbb4ee99a3b431c21662fd6971a020160e39848aa5f305b9be0f78727b2b0789e39f124d21e92b8f39ef");
|
||||
const DIGEST_MD5: [u8; 16] = hex!("c4874a8897440b393d862d8fd459073f");
|
||||
|
||||
fn to_base16(digest: &[u8]) -> String {
|
||||
HEXLOWER.encode(digest)
|
||||
}
|
||||
|
||||
fn to_nixbase32(digest: &[u8]) -> String {
|
||||
nixbase32::encode(digest)
|
||||
}
|
||||
|
||||
fn to_base64(digest: &[u8]) -> String {
|
||||
BASE64.encode(digest)
|
||||
}
|
||||
|
||||
fn to_base64_nopad(digest: &[u8]) -> String {
|
||||
BASE64_NOPAD.encode(digest)
|
||||
}
|
||||
|
||||
// TODO
|
||||
fn make_nixhash(algo: HashAlgo, digest_encoded: String) -> String {
|
||||
format!("{}:{}", algo, digest_encoded)
|
||||
}
|
||||
fn make_sri_string(algo: HashAlgo, digest_encoded: String) -> String {
|
||||
format!("{}-{}", algo, digest_encoded)
|
||||
}
|
||||
const NIXHASH_SHA1: NixHash = NixHash::Sha1(hex!("6016777997c30ab02413cf5095622cd7924283ac"));
|
||||
const NIXHASH_SHA256: NixHash = NixHash::Sha256(hex!(
|
||||
"a5ce9c155ed09397614646c9717fc7cd94b1023d7b76b618d409e4fefd6e9d39"
|
||||
));
|
||||
static NIXHASH_SHA512: LazyLock<NixHash> = LazyLock::new(|| {
|
||||
NixHash::Sha512(Box::new(hex!("ab40d0be3541f0774bba7815d13d10b03252e96e95f7dbb4ee99a3b431c21662fd6971a020160e39848aa5f305b9be0f78727b2b0789e39f124d21e92b8f39ef"))
|
||||
)
|
||||
});
|
||||
const NIXHASH_MD5: NixHash = NixHash::Md5(hex!("c4874a8897440b393d862d8fd459073f"));
|
||||
|
||||
/// Test parsing a hash string in various formats, and also when/how the out-of-band algo is needed.
|
||||
#[rstest]
|
||||
#[case::sha1(NixHash::Sha1(DIGEST_SHA1))]
|
||||
#[case::sha256(NixHash::Sha256(DIGEST_SHA256))]
|
||||
#[case::sha512(NixHash::Sha512(Box::new(DIGEST_SHA512)))]
|
||||
#[case::md5(NixHash::Md5(DIGEST_MD5))]
|
||||
fn from_str(#[case] expected_hash: NixHash) {
|
||||
let algo = expected_hash.algo();
|
||||
let digest = expected_hash.digest_as_bytes();
|
||||
// parse SRI
|
||||
{
|
||||
// base64 without out-of-band algo
|
||||
let s = make_sri_string(algo, to_base64(digest));
|
||||
let h = NixHash::from_str(&s, None).expect("must succeed");
|
||||
assert_eq!(expected_hash, h);
|
||||
|
||||
// base64 with out-of-band-algo
|
||||
let s = make_sri_string(algo, to_base64(digest));
|
||||
let h = NixHash::from_str(&s, Some(expected_hash.algo())).expect("must succeed");
|
||||
assert_eq!(expected_hash, h);
|
||||
|
||||
// base64_nopad without out-of-band algo
|
||||
let s = make_sri_string(algo, to_base64_nopad(digest));
|
||||
let h = NixHash::from_str(&s, None).expect("must succeed");
|
||||
assert_eq!(expected_hash, h);
|
||||
|
||||
// base64_nopad with out-of-band-algo
|
||||
let s = make_sri_string(algo, to_base64_nopad(digest));
|
||||
let h = NixHash::from_str(&s, Some(algo)).expect("must succeed");
|
||||
assert_eq!(expected_hash, h);
|
||||
}
|
||||
|
||||
// parse plain base16. should succeed with algo out-of-band, but fail without.
|
||||
{
|
||||
let s = to_base16(digest);
|
||||
NixHash::from_str(&s, None).expect_err("must fail");
|
||||
let h = NixHash::from_str(&s, Some(algo)).expect("must succeed");
|
||||
assert_eq!(expected_hash, h);
|
||||
}
|
||||
|
||||
// parse plain nixbase32. should succeed with algo out-of-band, but fail without.
|
||||
{
|
||||
let s = to_nixbase32(digest);
|
||||
NixHash::from_str(&s, None).expect_err("must fail");
|
||||
let h = NixHash::from_str(&s, Some(algo)).expect("must succeed");
|
||||
assert_eq!(expected_hash, h);
|
||||
}
|
||||
|
||||
// parse plain base64. should succeed with algo out-of-band, but fail without.
|
||||
{
|
||||
let s = to_base64(digest);
|
||||
NixHash::from_str(&s, None).expect_err("must fail");
|
||||
let h = NixHash::from_str(&s, Some(algo)).expect("must succeed");
|
||||
assert_eq!(expected_hash, h);
|
||||
}
|
||||
|
||||
// parse Nix hash strings
|
||||
{
|
||||
// base16. should succeed with both algo out-of-band and in-band.
|
||||
{
|
||||
let s = make_nixhash(algo, to_base16(digest));
|
||||
// regular SRI hashes. We test some funny encoding edge cases in a separate test.
|
||||
#[case::sri_sha1("sha1-YBZ3eZfDCrAkE89QlWIs15JCg6w=", HashAlgo::Sha1, NIXHASH_SHA1)]
|
||||
#[case::sri_sha256(
|
||||
"sha256-pc6cFV7Qk5dhRkbJcX/HzZSxAj17drYY1Ank/v1unTk=",
|
||||
HashAlgo::Sha256,
|
||||
NIXHASH_SHA256
|
||||
)]
|
||||
#[case::sri_sha512(
|
||||
"sha512-q0DQvjVB8HdLungV0T0QsDJS6W6V99u07pmjtDHCFmL9aXGgIBYOOYSKpfMFub4PeHJ7KweJ458STSHpK4857w==",
|
||||
HashAlgo::Sha512,
|
||||
(*NIXHASH_SHA512).clone()
|
||||
)]
|
||||
// lowerhex
|
||||
#[case::lowerhex_sha1(
|
||||
"sha1:6016777997c30ab02413cf5095622cd7924283ac",
|
||||
HashAlgo::Sha1,
|
||||
NIXHASH_SHA1
|
||||
)]
|
||||
#[case::lowerhex_sha256(
|
||||
"sha256:a5ce9c155ed09397614646c9717fc7cd94b1023d7b76b618d409e4fefd6e9d39",
|
||||
HashAlgo::Sha256,
|
||||
NIXHASH_SHA256
|
||||
)]
|
||||
#[case::lowerhex_sha512("sha512:ab40d0be3541f0774bba7815d13d10b03252e96e95f7dbb4ee99a3b431c21662fd6971a020160e39848aa5f305b9be0f78727b2b0789e39f124d21e92b8f39ef", HashAlgo::Sha512, (*NIXHASH_SHA512).clone())]
|
||||
#[case::lowerhex_md5("md5:c4874a8897440b393d862d8fd459073f", HashAlgo::Md5, NIXHASH_MD5)]
|
||||
#[case::lowerhex_md5("md5-xIdKiJdECzk9hi2P1FkHPw==", HashAlgo::Md5, NIXHASH_MD5)]
|
||||
// base64
|
||||
#[case::base64_sha1("sha1:YBZ3eZfDCrAkE89QlWIs15JCg6w=", HashAlgo::Sha1, NIXHASH_SHA1)]
|
||||
#[case::base64_sha256(
|
||||
"sha256:pc6cFV7Qk5dhRkbJcX/HzZSxAj17drYY1Ank/v1unTk=",
|
||||
HashAlgo::Sha256,
|
||||
NIXHASH_SHA256
|
||||
)]
|
||||
#[case::base64_sha512("sha512:q0DQvjVB8HdLungV0T0QsDJS6W6V99u07pmjtDHCFmL9aXGgIBYOOYSKpfMFub4PeHJ7KweJ458STSHpK4857w==", HashAlgo::Sha512, (*NIXHASH_SHA512).clone())]
|
||||
#[case::base64_md5("md5:xIdKiJdECzk9hi2P1FkHPw==", HashAlgo::Md5, NIXHASH_MD5)]
|
||||
// nixbase32
|
||||
#[case::nixbase32_sha1("sha1:mj1l54np5ii9al6g2cjb02n3jxwpf5k0", HashAlgo::Sha1, NIXHASH_SHA1)]
|
||||
#[case::nixbase32_sha256(
|
||||
"sha256:0fcxdvyzxr09shcbcxkv7l1b356dqxzp3ja68rhrg4yhbqarrkm5",
|
||||
HashAlgo::Sha256,
|
||||
NIXHASH_SHA256
|
||||
)]
|
||||
#[case::nixbase32_sha512("sha512:3pkk3rbx4hls4lzwf4hfavvf9w0zgmr0prsb2l47471c850f5lzsqhnq8qv98wrxssdpxwmdvlm4cmh20yx25bqp95pgw216nzd0h5b", HashAlgo::Sha512, (*NIXHASH_SHA512).clone())]
|
||||
#[case::nixbase32_md5("md5:1z0xcx93rdhqykj2s4jy44m1y4", HashAlgo::Md5, NIXHASH_MD5)]
|
||||
fn from_str(#[case] s: &str, #[case] algo: HashAlgo, #[case] expected: NixHash) {
|
||||
assert_eq!(
|
||||
expected_hash,
|
||||
NixHash::from_str(&s, None).expect("must succeed")
|
||||
expected,
|
||||
NixHash::from_str(s, Some(algo)).expect("must parse"),
|
||||
"should parse"
|
||||
);
|
||||
|
||||
// We expect all s to contain an algo in-band, so expect it to parse without an algo too.
|
||||
assert_eq!(
|
||||
expected_hash,
|
||||
NixHash::from_str(&s, Some(algo)).expect("must succeed")
|
||||
expected,
|
||||
NixHash::from_str(s, None).expect("must parse without algo too"),
|
||||
"should parse"
|
||||
);
|
||||
}
|
||||
// nixbase32. should succeed with both algo out-of-band and in-band.
|
||||
|
||||
// Whenever we encounter a hash with a `$algo:` prefix, we pop that prefix
|
||||
// and test it parses without it if the algo is passed in externally, but fails if not.
|
||||
// We do this for a subset of inputs here in the testcase, rather than adding 12 new testcases (4 algos x 3 encodings)
|
||||
if let Some(digest_str) = s
|
||||
.strip_prefix("sha1:")
|
||||
.or(s.strip_prefix("sha256:"))
|
||||
.or(s.strip_prefix("sha512:"))
|
||||
.or(s.strip_prefix("sha512:"))
|
||||
{
|
||||
let s = make_nixhash(algo, to_nixbase32(digest));
|
||||
assert_eq!(
|
||||
expected_hash,
|
||||
NixHash::from_str(&s, None).expect("must succeed")
|
||||
);
|
||||
assert_eq!(
|
||||
expected_hash,
|
||||
NixHash::from_str(&s, Some(algo)).expect("must succeed")
|
||||
);
|
||||
}
|
||||
// base64. should succeed with both algo out-of-band and in-band.
|
||||
{
|
||||
let s = make_nixhash(algo, to_base64(digest));
|
||||
assert_eq!(
|
||||
expected_hash,
|
||||
NixHash::from_str(&s, None).expect("must succeed")
|
||||
);
|
||||
assert_eq!(
|
||||
expected_hash,
|
||||
NixHash::from_str(&s, Some(algo)).expect("must succeed")
|
||||
expected,
|
||||
NixHash::from_str(digest_str, Some(algo))
|
||||
.expect("must parse digest-only if algo specified")
|
||||
);
|
||||
NixHash::from_str(digest_str, None)
|
||||
.expect_err("must fail parsing digest-only if algo not specified");
|
||||
}
|
||||
}
|
||||
|
||||
// Test parsing a hash specifying another algo than what's passed externally fails.
|
||||
#[test]
|
||||
fn test_want_algo() {
|
||||
NixHash::from_str("sha1-YBZ3eZfDCrAkE89QlWIs15JCg6w=", Some(HashAlgo::Md5))
|
||||
.expect_err("parsing with conflicting want_algo should fail");
|
||||
|
||||
NixHash::from_str("sha1:YBZ3eZfDCrAkE89QlWIs15JCg6w=", Some(HashAlgo::Md5))
|
||||
.expect_err("parsing with conflicting want_algo should fail");
|
||||
}
|
||||
|
||||
/// Test parsing an SRI hash via the [nixhash::from_sri_str] method.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue