#include #include "fgc/Hash.h" #include #include #include #include using namespace fgc; namespace fs = std::filesystem; TEST_CASE("fnv1a64 matches the reference vectors") { // The published FNV-1a 64 test vectors: if these drift, a stored digest from // an older build would silently stop matching. CHECK(fnv1a64("") == 0xcbf29ce484222325ULL); CHECK(fnv1a64("a") == 0xaf63dc4c8601ec8cULL); CHECK(fnv1a64("foobar") == 0x85944171f73967e8ULL); } TEST_CASE("fnv1a64 separates inputs that differ by one bit") { CHECK(fnv1a64("standard") != fnv1a64("standarD")); CHECK(fnv1a64("AcquisitionFrameRate = 10") != fnv1a64("AcquisitionFrameRate = 11")); // Order matters: two files with the same bytes rearranged are different files. CHECK(fnv1a64("ab") != fnv1a64("ba")); } TEST_CASE("hashLabel is prefixed and fixed width") { // The prefix exists so a digest can never be misread if the algorithm changes. CHECK(hashLabel(0) == "fnv1a64:0000000000000000"); CHECK(hashLabel(0xcbf29ce484222325ULL) == "fnv1a64:cbf29ce484222325"); CHECK(hashLabel(fnv1a64("")).size() == 8 + 16); } TEST_CASE("fnv1a64File hashes contents and throws on a missing file") { const fs::path p = fs::temp_directory_path() / ("fgc_hash_" + std::to_string(::getpid()) + ".bin"); { std::ofstream f(p, std::ios::binary); f << "foobar"; } CHECK(fnv1a64File(p.string()) == fnv1a64("foobar")); // A missing file must NOT read as an unchanged one - the caller uses this to // decide whether to regenerate. fs::remove(p); CHECK_THROWS(fnv1a64File(p.string())); }