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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::nixhash::{HashAlgo, NixHash};
|
||||||
nixbase32,
|
|
||||||
nixhash::{HashAlgo, NixHash},
|
|
||||||
};
|
|
||||||
use data_encoding::{BASE64, BASE64_NOPAD, HEXLOWER};
|
|
||||||
use hex_literal::hex;
|
use hex_literal::hex;
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
const DIGEST_SHA1: [u8; 20] = hex!("6016777997c30ab02413cf5095622cd7924283ac");
|
const NIXHASH_SHA1: NixHash = NixHash::Sha1(hex!("6016777997c30ab02413cf5095622cd7924283ac"));
|
||||||
const DIGEST_SHA256: [u8; 32] =
|
const NIXHASH_SHA256: NixHash = NixHash::Sha256(hex!(
|
||||||
hex!("a5ce9c155ed09397614646c9717fc7cd94b1023d7b76b618d409e4fefd6e9d39");
|
"a5ce9c155ed09397614646c9717fc7cd94b1023d7b76b618d409e4fefd6e9d39"
|
||||||
const DIGEST_SHA512: [u8; 64] = hex!("ab40d0be3541f0774bba7815d13d10b03252e96e95f7dbb4ee99a3b431c21662fd6971a020160e39848aa5f305b9be0f78727b2b0789e39f124d21e92b8f39ef");
|
));
|
||||||
const DIGEST_MD5: [u8; 16] = hex!("c4874a8897440b393d862d8fd459073f");
|
static NIXHASH_SHA512: LazyLock<NixHash> = LazyLock::new(|| {
|
||||||
|
NixHash::Sha512(Box::new(hex!("ab40d0be3541f0774bba7815d13d10b03252e96e95f7dbb4ee99a3b431c21662fd6971a020160e39848aa5f305b9be0f78727b2b0789e39f124d21e92b8f39ef"))
|
||||||
fn to_base16(digest: &[u8]) -> String {
|
)
|
||||||
HEXLOWER.encode(digest)
|
});
|
||||||
}
|
const NIXHASH_MD5: NixHash = NixHash::Md5(hex!("c4874a8897440b393d862d8fd459073f"));
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Test parsing a hash string in various formats, and also when/how the out-of-band algo is needed.
|
/// Test parsing a hash string in various formats, and also when/how the out-of-band algo is needed.
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case::sha1(NixHash::Sha1(DIGEST_SHA1))]
|
// regular SRI hashes. We test some funny encoding edge cases in a separate test.
|
||||||
#[case::sha256(NixHash::Sha256(DIGEST_SHA256))]
|
#[case::sri_sha1("sha1-YBZ3eZfDCrAkE89QlWIs15JCg6w=", HashAlgo::Sha1, NIXHASH_SHA1)]
|
||||||
#[case::sha512(NixHash::Sha512(Box::new(DIGEST_SHA512)))]
|
#[case::sri_sha256(
|
||||||
#[case::md5(NixHash::Md5(DIGEST_MD5))]
|
"sha256-pc6cFV7Qk5dhRkbJcX/HzZSxAj17drYY1Ank/v1unTk=",
|
||||||
fn from_str(#[case] expected_hash: NixHash) {
|
HashAlgo::Sha256,
|
||||||
let algo = expected_hash.algo();
|
NIXHASH_SHA256
|
||||||
let digest = expected_hash.digest_as_bytes();
|
)]
|
||||||
// parse SRI
|
#[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,
|
||||||
|
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,
|
||||||
|
NixHash::from_str(s, None).expect("must parse without algo too"),
|
||||||
|
"should parse"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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:"))
|
||||||
{
|
{
|
||||||
// base64 without out-of-band algo
|
assert_eq!(
|
||||||
let s = make_sri_string(algo, to_base64(digest));
|
expected,
|
||||||
let h = NixHash::from_str(&s, None).expect("must succeed");
|
NixHash::from_str(digest_str, Some(algo))
|
||||||
assert_eq!(expected_hash, h);
|
.expect("must parse digest-only if algo specified")
|
||||||
|
);
|
||||||
// base64 with out-of-band-algo
|
NixHash::from_str(digest_str, None)
|
||||||
let s = make_sri_string(algo, to_base64(digest));
|
.expect_err("must fail parsing digest-only if algo not specified");
|
||||||
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.
|
// Test parsing a hash specifying another algo than what's passed externally fails.
|
||||||
{
|
#[test]
|
||||||
let s = to_base16(digest);
|
fn test_want_algo() {
|
||||||
NixHash::from_str(&s, None).expect_err("must fail");
|
NixHash::from_str("sha1-YBZ3eZfDCrAkE89QlWIs15JCg6w=", Some(HashAlgo::Md5))
|
||||||
let h = NixHash::from_str(&s, Some(algo)).expect("must succeed");
|
.expect_err("parsing with conflicting want_algo should fail");
|
||||||
assert_eq!(expected_hash, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse plain nixbase32. should succeed with algo out-of-band, but fail without.
|
NixHash::from_str("sha1:YBZ3eZfDCrAkE89QlWIs15JCg6w=", Some(HashAlgo::Md5))
|
||||||
{
|
.expect_err("parsing with conflicting want_algo should fail");
|
||||||
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));
|
|
||||||
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")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// nixbase32. should succeed with both algo out-of-band and in-band.
|
|
||||||
{
|
|
||||||
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")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test parsing an SRI hash via the [nixhash::from_sri_str] method.
|
/// Test parsing an SRI hash via the [nixhash::from_sri_str] method.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue