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
167
168
169
170
171
172
173
|
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "mmh3.h"
typedef struct {
const char *name;
const void *data;
size_t len;
uint64_t seed;
uint64_t expected0;
uint64_t expected1;
} test_vector;
static int
test_mmh3_128_vector(const test_vector *test)
{
uint64_t out[2] = {0, 0};
mmh3_128(
test->data,
test->len,
test->seed,
out
);
if (out[0] != test->expected0 ||
out[1] != test->expected1) {
fprintf(
stderr,
"FAIL: %s\n"
" expected: %016" PRIx64 " %016" PRIx64 "\n"
" actual: %016" PRIx64 " %016" PRIx64 "\n",
test->name,
test->expected0,
test->expected1,
out[0],
out[1]
);
return 1;
}
printf("PASS: %s\n", test->name);
return 0;
}
static int
test_mmh3_128_unaligned(void)
{
static const char text[] =
"The quick brown fox jumps over the lazy dog";
uint8_t buffer[sizeof(text) + 1];
/*
* Force the input to begin at an address offset by one byte.
* This catches implementations that incorrectly cast arbitrary
* byte pointers to uint64_t * and perform aligned word reads.
*/
memcpy(buffer + 1, text, sizeof(text) - 1);
const test_vector test = {
.name = "x64_128 unaligned input",
.data = buffer + 1,
.len = sizeof(text) - 1,
.seed = 0,
.expected0 = UINT64_C(0xe34bbc7bbc071b6c),
.expected1 = UINT64_C(0x7a433ca9c49a9347),
};
return test_mmh3_128_vector(&test);
}
int
main(void)
{
static const char empty[] = "";
static const char foo[] = "foo";
static const char hello[] = "hello";
static const char block16[] = "0123456789abcdef";
static const char block17[] = "0123456789abcdefg";
static const char quickfox[] =
"The quick brown fox jumps over the lazy dog";
static const test_vector tests[] = {
{
.name = "x64_128 empty, seed 0",
.data = empty,
.len = 0,
.seed = 0,
.expected0 = UINT64_C(0x0000000000000000),
.expected1 = UINT64_C(0x0000000000000000),
},
{
.name = "x64_128 foo, seed 0",
.data = foo,
.len = sizeof(foo) - 1,
.seed = 0,
.expected0 = UINT64_C(0xe271865701f54561),
.expected1 = UINT64_C(0x7eaf87e42bba7d87),
},
{
.name = "x64_128 hello, seed 0",
.data = hello,
.len = sizeof(hello) - 1,
.seed = 0,
.expected0 = UINT64_C(0xcbd8a7b341bd9b02),
.expected1 = UINT64_C(0x5b1e906a48ae1d19),
},
{
.name = "x64_128 exactly 16 bytes",
.data = block16,
.len = sizeof(block16) - 1,
.seed = 0,
.expected0 = UINT64_C(0x4be06d94cf4ad1a7),
.expected1 = UINT64_C(0x87c35b5c63a708da),
},
{
.name = "x64_128 17 bytes",
.data = block17,
.len = sizeof(block17) - 1,
.seed = 0,
.expected0 = UINT64_C(0x8e32612daa45f9de),
.expected1 = UINT64_C(0x0800f4c206c372ee),
},
{
.name = "x64_128 quick fox, seed 0",
.data = quickfox,
.len = sizeof(quickfox) - 1,
.seed = 0,
.expected0 = UINT64_C(0xe34bbc7bbc071b6c),
.expected1 = UINT64_C(0x7a433ca9c49a9347),
},
{
.name = "x64_128 foo, seed 42",
.data = foo,
.len = sizeof(foo) - 1,
.seed = 42,
.expected0 = UINT64_C(0xf4569d51637053f2),
.expected1 = UINT64_C(0xa279b5d8eeb09aa9),
},
};
int failures = 0;
for (size_t i = 0;
i < sizeof(tests) / sizeof(tests[0]);
i++) {
failures += test_mmh3_128_vector(&tests[i]);
}
failures += test_mmh3_128_unaligned();
if (failures != 0) {
fprintf(
stderr,
"\n%d test%s failed\n",
failures,
failures == 1 ? "" : "s"
);
return 1;
}
printf("\nAll mmh3 tests passed.\n");
return 0;
}
|