extern "C" { #include #include } #include #include #include #include #include #define XXH_STATIC_LINKING_ONLY #include using namespace std; namespace { const std::array kTestInputs = { "", "0", "01234", "0123456789abcde", "0123456789abcdef", "0123456789abcdef0", "0123456789abcdef0123", "0123456789abcdef0123456789abcde", "0123456789abcdef0123456789abcdef", "0123456789abcdef0123456789abcdef0", "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", }; bool testXXH32(const void *input, const size_t length, uint32_t seed) { return XXH32(input, length, seed) == xxh32(input, length, seed); } bool testXXH64(const void *input, const size_t length, uint32_t seed) { return XXH64(input, length, seed) == xxh64(input, length, seed); } class XXH32State { struct xxh32_state kernelState; XXH32_state_t state; public: explicit XXH32State(const uint32_t seed) { reset(seed); } XXH32State(XXH32State const& other) noexcept { xxh32_copy_state(&kernelState, &other.kernelState); XXH32_copyState(&state, &other.state); } XXH32State& operator=(XXH32State const& other) noexcept { xxh32_copy_state(&kernelState, &other.kernelState); XXH32_copyState(&state, &other.state); return *this; } void reset(const uint32_t seed) { xxh32_reset(&kernelState, seed); EXPECT_EQ(0, XXH32_reset(&state, seed)); } void update(const void *input, const size_t length) { EXPECT_EQ(0, xxh32_update(&kernelState, input, length)); EXPECT_EQ(0, (int)XXH32_update(&state, input, length)); } bool testDigest() const { return xxh32_digest(&kernelState) == XXH32_digest(&state); } }; class XXH64State { struct xxh64_state kernelState; XXH64_state_t state; public: explicit XXH64State(const uint64_t seed) { reset(seed); } XXH64State(XXH64State const& other) noexcept { xxh64_copy_state(&kernelState, &other.kernelState); XXH64_copyState(&state, &other.state); } XXH64State& operator=(XXH64State const& other) noexcept { xxh64_copy_state(&kernelState, &other.kernelState); XXH64_copyState(&state, &other.state); return *this; } void reset(const uint64_t seed) { xxh64_reset(&kernelState, seed); EXPECT_EQ(0, XXH64_reset(&state, seed)); } void update(const void *input, const size_t length) { EXPECT_EQ(0, xxh64_update(&kernelState, input, length)); EXPECT_EQ(0, (int)XXH64_update(&state, input, length)); } bool testDigest() const { return xxh64_digest(&kernelState) == XXH64_digest(&state); } }; } TEST(Simple, Null) { EXPECT_TRUE(testXXH32(NULL, 0, 0)); EXPECT_TRUE(testXXH64(NULL, 0, 0)); } TEST(Stream, Null) { struct xxh32_state state32; xxh32_reset(&state32, 0); EXPECT_EQ(-EINVAL, xxh32_update(&state32, NULL, 0)); struct xxh64_state state64; xxh64_reset(&state64, 0); EXPECT_EQ(-EINVAL, xxh64_update(&state64, NULL, 0)); } TEST(Simple, TestInputs) { for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { for (auto const input : kTestInputs) { EXPECT_TRUE(testXXH32(input.data(), input.size(), seed)); EXPECT_TRUE(testXXH64(input.data(), input.size(), (uint64_t)seed)); } } } TEST(Stream, TestInputs) { for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { for (auto const input : kTestInputs) { XXH32State s32(seed); XXH64State s64(seed); s32.update(input.data(), input.size()); s64.update(input.data(), input.size()); EXPECT_TRUE(s32.testDigest()); EXPECT_TRUE(s64.testDigest()); } } } TEST(Stream, MultipleTestInputs) { for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { XXH32State s32(seed); XXH64State s64(seed); for (auto const input : kTestInputs) { s32.update(input.data(), input.size()); s64.update(input.data(), input.size()); } EXPECT_TRUE(s32.testDigest()); EXPECT_TRUE(s64.testDigest()); } } TEST(Stream, CopyState) { for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { XXH32State s32(seed); XXH64State s64(seed); for (auto const input : kTestInputs) { auto t32(s32); t32.update(input.data(), input.size()); s32 = t32; auto t64(s64); t64.update(input.data(), input.size()); s64 = t64; } EXPECT_TRUE(s32.testDigest()); EXPECT_TRUE(s64.testDigest()); } }