summaryrefslogtreecommitdiffstats
path: root/src/zstd/contrib/linux-kernel/test/XXHashUserlandTest.cpp
blob: f50401a2e19df4191e526305e6e1acce0a6bcec9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
extern "C" {
#include <linux/errno.h>
#include <linux/xxhash.h>
}
#include <gtest/gtest.h>
#include <array>
#include <iostream>
#include <memory>
#include <string>
#define XXH_STATIC_LINKING_ONLY
#include <xxhash.h>

using namespace std;

namespace {
const std::array<std::string, 11> 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());
  }
}