1 extern "C" {
2 #include <linux/errno.h>
3 #include <linux/xxhash.h>
4 }
5 #include <gtest/gtest.h>
6 #include <array>
7 #include <iostream>
8 #include <memory>
9 #include <string>
10 #define XXH_STATIC_LINKING_ONLY
11 #include <xxhash.h>
12
13 using namespace std;
14
15 namespace {
16 const std::array<std::string, 11> kTestInputs = {
17 "",
18 "0",
19 "01234",
20 "0123456789abcde",
21 "0123456789abcdef",
22 "0123456789abcdef0",
23 "0123456789abcdef0123",
24 "0123456789abcdef0123456789abcde",
25 "0123456789abcdef0123456789abcdef",
26 "0123456789abcdef0123456789abcdef0",
27 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
28 };
29
testXXH32(const void * input,const size_t length,uint32_t seed)30 bool testXXH32(const void *input, const size_t length, uint32_t seed) {
31 return XXH32(input, length, seed) == xxh32(input, length, seed);
32 }
33
testXXH64(const void * input,const size_t length,uint32_t seed)34 bool testXXH64(const void *input, const size_t length, uint32_t seed) {
35 return XXH64(input, length, seed) == xxh64(input, length, seed);
36 }
37
38 class XXH32State {
39 struct xxh32_state kernelState;
40 XXH32_state_t state;
41
42 public:
XXH32State(const uint32_t seed)43 explicit XXH32State(const uint32_t seed) { reset(seed); }
XXH32State(XXH32State const & other)44 XXH32State(XXH32State const& other) noexcept {
45 xxh32_copy_state(&kernelState, &other.kernelState);
46 XXH32_copyState(&state, &other.state);
47 }
operator =(XXH32State const & other)48 XXH32State& operator=(XXH32State const& other) noexcept {
49 xxh32_copy_state(&kernelState, &other.kernelState);
50 XXH32_copyState(&state, &other.state);
51 return *this;
52 }
53
reset(const uint32_t seed)54 void reset(const uint32_t seed) {
55 xxh32_reset(&kernelState, seed);
56 EXPECT_EQ(0, XXH32_reset(&state, seed));
57 }
58
update(const void * input,const size_t length)59 void update(const void *input, const size_t length) {
60 EXPECT_EQ(0, xxh32_update(&kernelState, input, length));
61 EXPECT_EQ(0, (int)XXH32_update(&state, input, length));
62 }
63
testDigest() const64 bool testDigest() const {
65 return xxh32_digest(&kernelState) == XXH32_digest(&state);
66 }
67 };
68
69 class XXH64State {
70 struct xxh64_state kernelState;
71 XXH64_state_t state;
72
73 public:
XXH64State(const uint64_t seed)74 explicit XXH64State(const uint64_t seed) { reset(seed); }
XXH64State(XXH64State const & other)75 XXH64State(XXH64State const& other) noexcept {
76 xxh64_copy_state(&kernelState, &other.kernelState);
77 XXH64_copyState(&state, &other.state);
78 }
operator =(XXH64State const & other)79 XXH64State& operator=(XXH64State const& other) noexcept {
80 xxh64_copy_state(&kernelState, &other.kernelState);
81 XXH64_copyState(&state, &other.state);
82 return *this;
83 }
84
reset(const uint64_t seed)85 void reset(const uint64_t seed) {
86 xxh64_reset(&kernelState, seed);
87 EXPECT_EQ(0, XXH64_reset(&state, seed));
88 }
89
update(const void * input,const size_t length)90 void update(const void *input, const size_t length) {
91 EXPECT_EQ(0, xxh64_update(&kernelState, input, length));
92 EXPECT_EQ(0, (int)XXH64_update(&state, input, length));
93 }
94
testDigest() const95 bool testDigest() const {
96 return xxh64_digest(&kernelState) == XXH64_digest(&state);
97 }
98 };
99 }
100
TEST(Simple,Null)101 TEST(Simple, Null) {
102 EXPECT_TRUE(testXXH32(NULL, 0, 0));
103 EXPECT_TRUE(testXXH64(NULL, 0, 0));
104 }
105
TEST(Stream,Null)106 TEST(Stream, Null) {
107 struct xxh32_state state32;
108 xxh32_reset(&state32, 0);
109 EXPECT_EQ(-EINVAL, xxh32_update(&state32, NULL, 0));
110
111 struct xxh64_state state64;
112 xxh64_reset(&state64, 0);
113 EXPECT_EQ(-EINVAL, xxh64_update(&state64, NULL, 0));
114 }
115
TEST(Simple,TestInputs)116 TEST(Simple, TestInputs) {
117 for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) {
118 for (auto const input : kTestInputs) {
119 EXPECT_TRUE(testXXH32(input.data(), input.size(), seed));
120 EXPECT_TRUE(testXXH64(input.data(), input.size(), (uint64_t)seed));
121 }
122 }
123 }
124
TEST(Stream,TestInputs)125 TEST(Stream, TestInputs) {
126 for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) {
127 for (auto const input : kTestInputs) {
128 XXH32State s32(seed);
129 XXH64State s64(seed);
130 s32.update(input.data(), input.size());
131 s64.update(input.data(), input.size());
132 EXPECT_TRUE(s32.testDigest());
133 EXPECT_TRUE(s64.testDigest());
134 }
135 }
136 }
137
TEST(Stream,MultipleTestInputs)138 TEST(Stream, MultipleTestInputs) {
139 for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) {
140 XXH32State s32(seed);
141 XXH64State s64(seed);
142 for (auto const input : kTestInputs) {
143 s32.update(input.data(), input.size());
144 s64.update(input.data(), input.size());
145 }
146 EXPECT_TRUE(s32.testDigest());
147 EXPECT_TRUE(s64.testDigest());
148 }
149 }
150
TEST(Stream,CopyState)151 TEST(Stream, CopyState) {
152 for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) {
153 XXH32State s32(seed);
154 XXH64State s64(seed);
155 for (auto const input : kTestInputs) {
156 auto t32(s32);
157 t32.update(input.data(), input.size());
158 s32 = t32;
159 auto t64(s64);
160 t64.update(input.data(), input.size());
161 s64 = t64;
162 }
163 EXPECT_TRUE(s32.testDigest());
164 EXPECT_TRUE(s64.testDigest());
165 }
166 }
167