test(checksum): add checksum tests

This commit is contained in:
Marcus Holland-Moritz 2024-01-12 16:43:02 +01:00
parent e4f1fdfcc6
commit de5ec99eca
4 changed files with 187 additions and 6 deletions

View File

@ -610,6 +610,7 @@ if(WITH_TESTS)
badfs_test
block_cache_test
block_merger_test
checksum_test
chmod_transformer_test
compat_test
dwarfs_test

View File

@ -22,6 +22,7 @@
#pragma once
#include <cstddef>
#include <iosfwd>
#include <memory>
#include <stdexcept>
#include <string>
@ -44,6 +45,8 @@ class checksum {
static bool verify(algorithm alg, void const* data, size_t size,
void const* digest, size_t digest_size);
static bool verify(std::string const& alg, void const* data, size_t size,
void const* digest, size_t digest_size);
checksum(algorithm alg);
checksum(std::string const& alg);
@ -70,4 +73,6 @@ class checksum {
std::unique_ptr<impl> impl_;
};
std::ostream& operator<<(std::ostream& os, checksum::algorithm alg);
} // namespace dwarfs

View File

@ -23,6 +23,7 @@
#include <array>
#include <cstring>
#include <functional>
#include <ostream>
#include <unordered_set>
#include <openssl/evp.h>
@ -165,6 +166,17 @@ class checksum_xxh3_128 : public checksum::impl {
XXH3_state_t* state_;
};
template <typename T>
bool verify_impl(T&& alg, void const* data, size_t size, const void* digest,
size_t digest_size) {
std::array<char, EVP_MAX_MD_SIZE> tmp;
checksum cs(std::forward<T>(alg));
DWARFS_CHECK(digest_size == cs.digest_size(), "digest size mismatch");
cs.update(data, size);
return cs.finalize(tmp.data()) &&
::memcmp(digest, tmp.data(), digest_size) == 0;
}
} // namespace
bool checksum::is_available(std::string const& algo) {
@ -183,12 +195,12 @@ std::vector<std::string> checksum::available_algorithms() {
bool checksum::verify(algorithm alg, void const* data, size_t size,
const void* digest, size_t digest_size) {
std::array<char, EVP_MAX_MD_SIZE> tmp;
checksum cs(alg);
DWARFS_CHECK(digest_size == cs.digest_size(), "digest size mismatch");
cs.update(data, size);
return cs.finalize(tmp.data()) &&
::memcmp(digest, tmp.data(), digest_size) == 0;
return verify_impl(alg, data, size, digest, digest_size);
}
bool checksum::verify(std::string const& alg, void const* data, size_t size,
const void* digest, size_t digest_size) {
return verify_impl(alg, data, size, digest, digest_size);
}
checksum::checksum(algorithm alg) {
@ -220,4 +232,22 @@ checksum::checksum(std::string const& alg) {
}
}
std::ostream& operator<<(std::ostream& os, checksum::algorithm alg) {
switch (alg) {
case checksum::algorithm::SHA2_512_256:
os << "SHA2_512_256";
break;
case checksum::algorithm::XXH3_64:
os << "XXH3_64";
break;
case checksum::algorithm::XXH3_128:
os << "XXH3_128";
break;
default:
os << "<unknown>";
break;
}
return os;
}
} // namespace dwarfs

145
test/checksum_test.cpp Normal file
View File

@ -0,0 +1,145 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <string>
#include <string_view>
#include <unordered_map>
#include <boost/algorithm/hex.hpp>
#include "dwarfs/checksum.h"
using namespace dwarfs;
namespace {
constexpr std::string_view const payload{"Hello, World!"};
std::unordered_map<checksum::algorithm, std::string> ref_digests_enum{
{checksum::algorithm::SHA2_512_256,
"0686F0A605973DC1BF035D1E2B9BAD1985A0BFF712DDD88ABD8D2593E5F99030"},
{checksum::algorithm::XXH3_64, "AA0266615F5D4160"},
{checksum::algorithm::XXH3_128, "9553D72C8403DB7750DD474484F21D53"},
};
std::unordered_map<std::string, std::string> ref_digests_str{
{"blake2b512",
"7DFDB888AF71EAE0E6A6B751E8E3413D767EF4FA52A7993DAA9EF097F7AA3D949199C113C"
"AA37C94F80CF3B22F7D9D6E4F5DEF4FF927830CFFE4857C34BE3D89"},
{"blake2s256",
"EC9DB904D636EF61F1421B2BA47112A4FA6B8964FD4A0A514834455C21DF7812"},
{"md5", "65A8E27D8879283831B664BD8B7F0AD4"},
{"md5-sha1", "65A8E27D8879283831B664BD8B7F0AD40A0A9F2A6772942557AB5355D76AF"
"442F8F65E01"},
{"ripemd160", "527A6A4B9A6DA75607546842E0E00105350B1AAF"},
{"sha1", "0A0A9F2A6772942557AB5355D76AF442F8F65E01"},
{"sha224", "72A23DFA411BA6FDE01DBFABF3B00A709C93EBF273DC29E2D8B261FF"},
{"sha256",
"DFFD6021BB2BD5B0AF676290809EC3A53191DD81C7F70A4B28688A362182986F"},
{"sha3-224", "853048FB8B11462B6100385633C0CC8DCDC6E2B8E376C28102BC84F2"},
{"sha3-256",
"1AF17A664E3FA8E419B8BA05C2A173169DF76162A5A286E0C405B460D478F7EF"},
{"sha3-384", "AA9AD8A49F31D2DDCABBB7010A1566417CFF803FEF50EBA239558826F872E"
"468C5743E7F026B0A8E5B2D7A1CC465CDBE"},
{"sha3-512",
"38E05C33D7B067127F217D8C856E554FCFF09C9320B8A5979CE2FF5D95DD27BA35D1FBA50"
"C562DFD1D6CC48BC9C5BAA4390894418CC942D968F97BCB659419ED"},
{"sha384", "5485CC9B3365B4305DFB4E8337E0A598A574F8242BF17289E0DD6C20A3CD44A"
"089DE16AB4AB308F63E44B1170EB5F515"},
{"sha512",
"374D794A95CDCFD8B35993185FEF9BA368F160D8DAF432D08BA9F1ED1E5ABE6CC69291E0F"
"A2FE0006A52570EF18C19DEF4E617C33CE52EF0A6E5FBE318CB0387"},
{"sha512-224", "766745F058E8A0438F19DE48AE56EA5F123FE738AF39BCA050A7547A"},
{"sha512-256",
"0686F0A605973DC1BF035D1E2B9BAD1985A0BFF712DDD88ABD8D2593E5F99030"},
{"shake128", "2BF5E6DEE6079FAD604F573194BA8426"},
{"shake256",
"B3BE97BFD978833A65588CEAE8A34CF59E95585AF62063E6B89D0789F372424E"},
{"sm3", "7ED26CBF0BEE4CA7D55C1E64714C4AA7D1F163089EF5CEB603CD102C81FBCBC5"},
{"xxh3-128", "9553D72C8403DB7750DD474484F21D53"},
{"xxh3-64", "AA0266615F5D4160"},
};
} // namespace
class checksum_test_str : public ::testing::TestWithParam<std::string> {};
TEST_P(checksum_test_str, end_to_end) {
auto alg = GetParam();
std::vector<uint8_t> digest;
{
checksum cs(alg);
cs.update(payload.data(), payload.size());
digest.resize(cs.digest_size());
cs.finalize(digest.data());
}
auto hexdigest =
boost::algorithm::hex(std::string(digest.begin(), digest.end()));
EXPECT_TRUE(checksum::verify(alg, payload.data(), payload.size(),
digest.data(), digest.size()));
if (auto it = ref_digests_str.find(alg); it != ref_digests_str.end()) {
EXPECT_EQ(it->second, hexdigest) << alg;
}
}
INSTANTIATE_TEST_SUITE_P(checksum_test, checksum_test_str,
::testing::ValuesIn(checksum::available_algorithms()));
class checksum_test_enum
: public ::testing::TestWithParam<checksum::algorithm> {};
TEST_P(checksum_test_enum, end_to_end) {
auto alg = GetParam();
std::vector<uint8_t> digest;
{
checksum cs(alg);
cs.update(payload.data(), payload.size());
digest.resize(cs.digest_size());
cs.finalize(digest.data());
}
auto hexdigest =
boost::algorithm::hex(std::string(digest.begin(), digest.end()));
auto it = ref_digests_enum.find(alg);
ASSERT_FALSE(it == ref_digests_enum.end());
EXPECT_TRUE(checksum::verify(alg, payload.data(), payload.size(),
digest.data(), digest.size()));
EXPECT_EQ(it->second, hexdigest) << alg;
}
INSTANTIATE_TEST_SUITE_P(checksum_test, checksum_test_enum,
::testing::ValuesIn({checksum::algorithm::SHA2_512_256,
checksum::algorithm::XXH3_64,
checksum::algorithm::XXH3_128}));