1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.codec.digest;
19
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertNotEquals;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24 import static org.junit.jupiter.api.Assumptions.assumeTrue;
25
26 import java.nio.ByteBuffer;
27 import java.util.Arrays;
28 import java.util.concurrent.ThreadLocalRandom;
29
30 import org.apache.commons.codec.binary.StringUtils;
31 import org.apache.commons.codec.digest.MurmurHash3.IncrementalHash32;
32 import org.apache.commons.codec.digest.MurmurHash3.IncrementalHash32x86;
33 import org.junit.jupiter.api.Test;
34
35
36
37
38 @SuppressWarnings("deprecation")
39 class MurmurHash3Test {
40
41
42 private static final String TEST_HASH64 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?";
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 private static final int[] RANDOM_INTS = { 46, 246, 249, 184, 247, 84, 99, 144, 62, 77, 195, 220, 92, 20, 150, 159, 38, 40, 124, 252, 185, 28, 63, 13, 213,
72 172, 85, 198, 118, 74, 109, 157, 132, 216, 76, 177, 173, 23, 140, 86, 146, 95, 54, 176, 114, 179, 234, 174, 183, 141, 122, 12, 60, 116, 200, 142, 6,
73 167, 59, 240, 33, 29, 165, 111, 243, 30, 219, 110, 255, 53, 32, 35, 64, 225, 96, 152, 70, 41, 133, 80, 244, 127, 57, 199, 5, 164, 151, 49, 26, 180,
74 203, 83, 108, 39, 126, 208, 42, 206, 178, 19, 69, 223, 71, 231, 250, 125, 211, 232, 189, 55, 44, 82, 48, 221, 43, 192, 241, 103, 155, 27, 51, 163,
75 21, 169, 91, 94, 217, 191, 78, 72, 93, 102, 104, 105, 8, 113, 100, 143, 89, 245, 227, 120, 160, 251, 153, 145, 45, 218, 168, 233, 229, 253, 67, 22,
76 182, 98, 137, 128, 135, 11, 214, 66, 73, 171, 188, 170, 131, 207, 79, 106, 24, 75, 237, 194, 7, 129, 215, 81, 248, 242, 16, 25, 136, 147, 156, 97,
77 52, 10, 181, 17, 205, 58, 101, 68, 230, 1, 37, 0, 222, 88, 130, 148, 224, 47, 50, 197, 34, 212, 196, 209, 14, 36, 139, 228, 154, 31, 175, 202, 236,
78 161, 3, 162, 190, 254, 134, 119, 4, 61, 65, 117, 186, 107, 204, 9, 187, 201, 90, 149, 226, 56, 239, 238, 235, 112, 87, 18, 121, 115, 138, 123, 210,
79 2, 193, 166, 158, 15 };
80
81
82
83
84
85 private static final byte[] RANDOM_BYTES;
86
87 static {
88 RANDOM_BYTES = new byte[RANDOM_INTS.length];
89 for (int i = 0; i < RANDOM_BYTES.length; i++) {
90 RANDOM_BYTES[i] = (byte) RANDOM_INTS[i];
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 private static void assertIncrementalHash32(final byte[] bytes, final int seed, final int... blocks) {
117 int offset = 0;
118 int total = 0;
119 final IncrementalHash32 inc = new IncrementalHash32();
120 inc.start(seed);
121 for (final int block : blocks) {
122 total += block;
123 final int h1 = MurmurHash3.hash32(bytes, 0, total, seed);
124 inc.add(bytes, offset, block);
125 offset += block;
126 final int h2 = inc.end();
127 assertEquals(h1, h2, "Hashes differ");
128 assertEquals(h1, inc.end(), "Hashes differ after no additional data");
129 }
130 }
131
132
133
134
135
136
137
138
139
140
141
142
143
144 private static void assertIncrementalHash32x86(final byte[] bytes, final int seed, final int... blocks) {
145 int offset = 0;
146 int total = 0;
147 final IncrementalHash32x86 inc = new IncrementalHash32x86();
148 inc.start(seed);
149 for (final int block : blocks) {
150 total += block;
151 final int h1 = MurmurHash3.hash32x86(bytes, 0, total, seed);
152 inc.add(bytes, offset, block);
153 offset += block;
154 final int h2 = inc.end();
155 assertEquals(h1, h2, "Hashes differ");
156 assertEquals(h1, inc.end(), "Hashes differ after no additional data");
157 }
158 }
159
160
161
162
163
164
165 private static long[] createLongTestData() {
166 final long[] data = new long[100];
167
168 data[0] = 0;
169 data[1] = Long.MIN_VALUE;
170 data[2] = Long.MAX_VALUE;
171 data[3] = -1L;
172 for (int i = 4; i < data.length; i++) {
173 data[i] = ThreadLocalRandom.current().nextLong();
174 }
175 return data;
176 }
177
178
179
180
181
182
183
184 private static int[] createRandomBlocks(final int maxLength) {
185 final int[] blocks = new int[20];
186 int count = 0;
187 int length = 0;
188 while (count < blocks.length && length < maxLength) {
189
190 final int size = ThreadLocalRandom.current().nextInt(1, 9);
191 blocks[count++] = size;
192 length += size;
193 }
194 return Arrays.copyOf(blocks, count);
195 }
196
197
198
199
200
201
202
203
204
205 private static boolean negativeBytes(final byte[] bytes, final int start, final int length) {
206 for (int i = start; i < start + length; i++) {
207 if (bytes[i] < 0) {
208 return true;
209 }
210 }
211 return false;
212 }
213
214
215
216
217
218
219
220
221
222
223 @Test
224 void testHash128() {
225
226 assertArrayEquals(new long[] {-5614308156300707300L, -4165733009867452172L},
227 MurmurHash3.hash128(RANDOM_BYTES));
228
229
230
231
232
233 final long[][] answers = {
234 {-7122613646888064702L, -8341524471658347240L}, {5659994275039884826L, -962335545730945195L},
235 {-7641758224504050283L, 4083131074855072837L}, {-9123564721037921804L, -3321998102976419641L},
236 {-7999620158275145567L, -7769992740725283391L}, {2419143614837736468L, -5474637306496300103L},
237 {7781591175729494939L, -9023178611551692650L}, {-3431043156265556247L, -6589990064676612981L},
238 {6315693694262400182L, -6219942557302821890L}, {-8249934145502892979L, -5646083202776239948L},
239 {7500109050276796947L, 5350477981718987260L}, {-6102338673930022315L, 3413065069102535261L},
240 {-6440683413407781313L, -2374360388921904146L}, {-3071236194203069122L, 7531604855739305895L},
241 {-7629408037856591130L, -4070301959951145257L}, {860008171111471563L, -9026008285726889896L},
242 {8059667613600971894L, 3236009436748930210L}, {1833746055900036985L, 1418052485321768916L},
243 {8161230977297923537L, -2668130155009407119L}, {3653111839268905630L, 5525563908135615453L},
244 {-9163026480602019754L, 6819447647029564735L}, {1102346610654592779L, -6881918401879761029L},
245 {-3109499571828331931L, -3782255367340446228L}, {-7467915444290531104L, 4704551260862209500L},
246 {1237530251176898868L, 6144786892208594932L}, {2347717913548230384L, -7461066668225718223L},
247 {-7963311463560798404L, 8435801462986138227L}, {-7493166089060196513L, 8163503673197886404L},
248 {6807249306539951962L, -1438886581269648819L}, {6752656991043418179L, 6334147827922066123L},
249 {-4534351735605790331L, -4530801663887858236L}, {-7886946241830957955L, -6261339648449285315L}
250 };
251 for (int i = 0; i < answers.length; i++) {
252 final byte[] bytes = Arrays.copyOf(RANDOM_BYTES, i);
253 assertArrayEquals(answers[i], MurmurHash3.hash128(bytes));
254 }
255 }
256
257
258
259
260
261
262
263
264
265
266 @Test
267 void testHash128String() {
268 final int seed = 104729;
269
270 final int minSize = 1;
271 final int maxSize = 11;
272
273 final int codePoints = 112956;
274 final char[] chars = new char[(maxSize - minSize) * 2];
275 for (int i = 0; i < 1000; i++) {
276 int pos = 0;
277 final int size = ThreadLocalRandom.current().nextInt(minSize, maxSize);
278 for (int j = 0; j < size; j++) {
279 final int codePoint = ThreadLocalRandom.current().nextInt(codePoints);
280 pos += Character.toChars(codePoint, chars, pos);
281 }
282 final String text = String.copyValueOf(chars, 0, pos);
283 final byte[] bytes = StringUtils.getBytesUtf8(text);
284 final long[] h1 = MurmurHash3.hash128(bytes, 0, bytes.length, seed);
285 final long[] h2 = MurmurHash3.hash128(text);
286 assertArrayEquals(h1, h2);
287 }
288 }
289
290
291
292
293
294
295
296
297
298
299 @Test
300 void testHash128WithOffsetLengthAndNegativeSeed() {
301
302 final int seed = -42;
303 final int offset = 13;
304
305
306
307 final long[][] answers = {
308 {5954234972212089025L, 3342108296337967352L},
309 {8501094764898402923L, 7873951092908129427L}, {-3334322685492296196L, -2842715922956549478L},
310 {-2177918982459519644L, -1612349961980368636L}, {4172870320608886992L, -4177375712254136503L},
311 {7546965006884307324L, -5222114032564054641L}, {-2885083166621537267L, -2069868899915344482L},
312 {-2397098497873118851L, 4990578036999888806L}, {-706479374719025018L, 7531201699171849870L},
313 {6487943141157228609L, 3576221902299447884L}, {6671331646806999453L, -3428049860825046360L},
314 {-8700221138601237020L, -2748450904559980545L}, {-9028762509863648063L, 6130259301750313402L},
315 {729958512305702590L, -36367317333638988L}, {-3803232241584178983L, -4257744207892929651L},
316 {5734013720237474696L, -760784490666078990L}, {-6097477411153026656L, 625288777006549065L},
317 {1320365359996757504L, -2251971390373072541L}, {5551441703887653022L, -3516892619809375941L},
318 {698875391638415033L, 3456972931370496131L}, {5874956830271303805L, -6074126509360777023L},
319 {-7030758398537734781L, -3174643657101295554L}, {6835789852786226556L, 7245353136839389595L},
320 {-7755767580598793204L, -6680491060945077989L}, {-3099789923710523185L, -2751080516924952518L},
321 {-7772046549951435453L, 5263206145535830491L}, {7458715941971015543L, 5470582752171544854L},
322 {-7753394773760064468L, -2330157750295630617L}, {-5899278942232791979L, 6235686401271389982L},
323 {4881732293467626532L, 2617335658565007304L}, {-5722863941703478257L, -5424475653939430258L},
324 {-3703319768293496315L, -2124426428486426443L}
325 };
326 for (int i = 0; i < answers.length; i++) {
327 assertArrayEquals(answers[i], MurmurHash3.hash128(RANDOM_BYTES, offset, i, seed), "Length: " + i);
328 }
329 }
330
331
332
333
334
335
336
337
338
339
340 @Test
341 void testHash128WithOffsetLengthAndSeed() {
342
343 final int seed = 42;
344 final int offset = 13;
345
346
347
348
349
350 final long[][] answers = {
351 {-1140915396076141277L, -3386313222241793095L},
352 {2745805417334040752L, -3045882272665292331L}, {6807939080212835946L, -1975749467247671127L},
353 {-7924884987449335214L, -4468571497642087939L}, {3005389733967167773L, -5809440073240597398L},
354 {8032745196600164727L, 4545709434702374224L}, {2095398623732573832L, 1778447136435513908L},
355 {4492723708121417255L, -7411125500882394867L}, {8467397417110552178L, -1503802302645548949L},
356 {4189760269121918355L, -8004336343217265057L}, {4939298084211301953L, -8419135013628844658L},
357 {5497136916151148085L, -394028342910298191L}, {3405983294878231737L, -3216533807498089078L},
358 {5833223403351466775L, -1792451370239813325L}, {7730583391236194819L, 5356157313842354092L},
359 {3111977482488580945L, -3119414725698132191L}, {3314524606404365027L, -1923219843083192742L},
360 {7299569240140613949L, 4176392429810027494L}, {6398084683727166117L, 7703960505857395788L},
361 {-8594572031068184774L, 4394224719145783692L}, {-7589785442804461713L, 4110439243215224554L},
362 {-5343610105946840628L, -4423992782020122809L}, {-522490326525787270L, 289136460641968781L},
363 {-5320637070354802556L, -7845553044730489027L}, {1344456408744313334L, 3803048032054968586L},
364 {1131205296221907191L, -6256656049039287019L}, {8583339267101027117L, 8934225022848628726L},
365 {-6379552869905441749L, 8973517768420051734L}, {5076646564516328801L, 8561479196844000567L},
366 {-4610341636137642517L, -6694266039505142069L}, {-758896383254029789L, 4050360662271552727L},
367 {-6123628195475753507L, 4283875822581966645L}
368 };
369 for (int i = 0; i < answers.length; i++) {
370 assertArrayEquals(answers[i], MurmurHash3.hash128(RANDOM_BYTES, offset, i, seed), "Length: " + i);
371 }
372 }
373
374
375
376
377
378
379
380
381
382
383 @Test
384 void testHash128x64() {
385
386
387
388 assertArrayEquals(new long[] {1972113670104592209L, 5171809317673151911L},
389 MurmurHash3.hash128x64(RANDOM_BYTES));
390
391
392
393
394
395 final long[][] answers = {
396 {0L, 0L}, {-2808653841080383123L, -2531784594030660343L},
397 {-1284575471001240306L, -8226941173794461820L}, {1645529003294647142L, 4109127559758330427L},
398 {-4117979116203940765L, -8362902660322042742L}, {2559943399590596158L, 4738005461125350075L},
399 {-1651760031591552651L, -5386079254924224461L}, {-6208043960690815609L, 7862371518025305074L},
400 {-5150023478423646337L, 8346305334874564507L}, {7658274117911906792L, -4962914659382404165L},
401 {1309458104226302269L, 570003296096149119L}, {7440169453173347487L, -3489345781066813740L},
402 {-5698784298612201352L, 3595618450161835420L}, {-3822574792738072442L, 6878153771369862041L},
403 {3705084673301918328L, 3202155281274291907L}, {-6797166743928506931L, -4447271093653551597L},
404 {5240533565589385084L, -5575481185288758327L}, {-8467620131382649428L, -6450630367251114468L},
405 {3632866961828686471L, -5957695976089313500L}, {-6450283648077271139L, -7908632714374518059L},
406 {226350826556351719L, 8225586794606475685L}, {-2382996224496980401L, 2188369078123678011L},
407 {-1337544762358780825L, 7004253486151757299L}, {2889033453638709716L, -4099509333153901374L},
408 {-8644950936809596954L, -5144522919639618331L}, {-5628571865255520773L, -839021001655132087L},
409 {-5226774667293212446L, -505255961194269502L}, {1337107025517938142L, 3260952073019398505L},
410 {9149852874328582511L, 1880188360994521535L}, {-4035957988359881846L, -7709057850766490780L},
411 {-3842593823306330815L, 3805147088291453755L}, {4030161393619149616L, -2813603781312455238L}
412 };
413 for (int i = 0; i < answers.length; i++) {
414 final byte[] bytes = Arrays.copyOf(RANDOM_BYTES, i);
415 assertArrayEquals(answers[i], MurmurHash3.hash128x64(bytes));
416 }
417 }
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433 @Test
434 void testHash128x64WithOffsetLengthAndNegativeSeed() {
435
436 final int seed = -42;
437 final int offset = 13;
438
439
440
441
442
443 final long[][] answers = {
444 {7182599573337898253L, -6490979146667806054L},
445 {-461284136738605467L, 7073284964362976233L}, {-3090354666589400212L, 2978755180788824810L},
446 {5052807367580803906L, -4497188744879598335L}, {5003711854877353474L, -6616808651483337088L},
447 {2043501804923817748L, -760668448196918637L}, {6813003268375229932L, -1818545210475363684L},
448 {4488070015393027916L, 8520186429078977003L}, {4709278711722456062L, -2262080641289046033L},
449 {-5944514262756048380L, 5968714500873552518L}, {-2304397529301122510L, 6451500469518446488L},
450 {-1054078041081348909L, -915114408909600132L}, {1300471646869277217L, -399493387666437046L},
451 {-2821780479886030222L, -9061571187511294733L}, {8005764841242557505L, 4135287855434326053L},
452 {318307346637037498L, -5355856739901286522L}, {3380719536119187025L, 1890890833937151467L},
453 {2691044185935730001L, 7963546423617895734L}, {-5277462388534000227L, 3613853764390780573L},
454 {8504421722476165699L, 2058020162708103700L}, {-6578421288092422241L, 3311200163790829579L},
455 {-5915037218487974215L, -7385137075895184179L}, {659642911937398022L, 854071824595671049L},
456 {-7007237968866727198L, 1372258010932080058L}, {622891376282772539L, -4140783491297489868L},
457 {8357110718969014985L, -4737117827581590306L}, {2208857857926305405L, -8360240839768465042L},
458 {858120048221036376L, -5822288789703639119L}, {-1988334009458340679L, 1262479472434068698L},
459 {-8580307083590783934L, 3634449965473715778L}, {6705664584730187559L, 5192304951463791556L},
460 {-6426410954037604142L, -1579122709247558101L}
461 };
462 for (int i = 0; i < answers.length; i++) {
463 assertArrayEquals(answers[i], MurmurHash3.hash128x64(RANDOM_BYTES, offset, i, seed), "Length: " + i);
464 }
465 }
466
467
468
469
470
471
472
473
474
475
476 @Test
477 void testHash128x64WithOffsetLengthAndSeed() {
478
479 final int seed = 42;
480 final int offset = 13;
481
482
483
484
485
486 final long[][] answers = {
487 {-1140915396076141277L, -3386313222241793095L},
488 {2745805417334040752L, -3045882272665292331L}, {6807939080212835946L, -1975749467247671127L},
489 {-7924884987449335214L, -4468571497642087939L}, {3005389733967167773L, -5809440073240597398L},
490 {8032745196600164727L, 4545709434702374224L}, {2095398623732573832L, 1778447136435513908L},
491 {4492723708121417255L, -7411125500882394867L}, {8467397417110552178L, -1503802302645548949L},
492 {4189760269121918355L, -8004336343217265057L}, {4939298084211301953L, -8419135013628844658L},
493 {5497136916151148085L, -394028342910298191L}, {3405983294878231737L, -3216533807498089078L},
494 {5833223403351466775L, -1792451370239813325L}, {7730583391236194819L, 5356157313842354092L},
495 {3111977482488580945L, -3119414725698132191L}, {3314524606404365027L, -1923219843083192742L},
496 {7299569240140613949L, 4176392429810027494L}, {6398084683727166117L, 7703960505857395788L},
497 {-8594572031068184774L, 4394224719145783692L}, {-7589785442804461713L, 4110439243215224554L},
498 {-5343610105946840628L, -4423992782020122809L}, {-522490326525787270L, 289136460641968781L},
499 {-5320637070354802556L, -7845553044730489027L}, {1344456408744313334L, 3803048032054968586L},
500 {1131205296221907191L, -6256656049039287019L}, {8583339267101027117L, 8934225022848628726L},
501 {-6379552869905441749L, 8973517768420051734L}, {5076646564516328801L, 8561479196844000567L},
502 {-4610341636137642517L, -6694266039505142069L}, {-758896383254029789L, 4050360662271552727L},
503 {-6123628195475753507L, 4283875822581966645L}
504 };
505 for (int i = 0; i < answers.length; i++) {
506 assertArrayEquals(answers[i], MurmurHash3.hash128x64(RANDOM_BYTES, offset, i, seed), "Length: " + i);
507 }
508 }
509
510
511
512
513
514
515
516
517
518
519 @Test
520 void testHash32() {
521
522 assertEquals(1905657630, MurmurHash3.hash32(RANDOM_BYTES));
523
524
525
526
527
528 final int[] answers = { -965378730, 418246248, 1175981702, -616767012, -12304673, 1697005142, -1212417875, -420043393, -826068069, -1721451528,
529 -544986914, 892942691, 27535194, 974863697, 1835661694, -894915836, 1826914566, -677571679, 1218764493, -375719050, -1320048170, -503583763,
530 1321750696, -175065786, -496878386, -12065683, 512351473, 716560510, -1944803590, 10253199, 1105638211, 525704533, };
531 for (int i = 0; i < answers.length; i++) {
532 final byte[] bytes = Arrays.copyOf(RANDOM_BYTES, i);
533
534
535 if (i % 4 == 0 || !negativeBytes(bytes, i / 4 * 4, i % 4)) {
536 assertEquals(answers[i], MurmurHash3.hash32(bytes));
537 } else {
538 assertNotEquals(answers[i], MurmurHash3.hash32(bytes));
539 }
540 }
541 }
542
543
544
545
546 @Test
547 void testHash32Long() {
548
549 final int offset = 0;
550 final int seed = 104729;
551
552 final int length = Long.BYTES;
553 final ByteBuffer buffer = ByteBuffer.allocate(length);
554 final byte[] bytes = buffer.array();
555 final long[] data = createLongTestData();
556 for (final long i : data) {
557 buffer.putLong(0, i);
558 assertEquals(MurmurHash3.hash32x86(bytes, offset, length, seed), MurmurHash3.hash32(i));
559 }
560 }
561
562
563
564
565 @Test
566 void testHash32LongLong() {
567
568 final int offset = 0;
569 final int seed = 104729;
570
571 final int length = Long.BYTES * 2;
572 final ByteBuffer buffer = ByteBuffer.allocate(length);
573 final byte[] bytes = buffer.array();
574 final long[] data = createLongTestData();
575 for (final long i : data) {
576 for (final long j : data) {
577 buffer.putLong(0, i);
578 buffer.putLong(Long.BYTES, j);
579 assertEquals(MurmurHash3.hash32x86(bytes, offset, length, seed), MurmurHash3.hash32(i, j));
580 }
581 }
582 }
583
584
585
586
587 @Test
588 void testHash32LongLongSeed() {
589
590 final int offset = 0;
591 final int seed = 104729;
592
593 final int length = Long.BYTES * 2;
594 final ByteBuffer buffer = ByteBuffer.allocate(length);
595 final byte[] bytes = buffer.array();
596 final long[] data = createLongTestData();
597 for (final long i : data) {
598 for (final long j : data) {
599 buffer.putLong(0, i);
600 buffer.putLong(Long.BYTES, j);
601 assertEquals(MurmurHash3.hash32x86(bytes, offset, length, seed), MurmurHash3.hash32(i, j, seed));
602 }
603 }
604 }
605
606
607
608
609 @Test
610 void testHash32LongSeed() {
611
612 final int offset = 0;
613 final int seed = 104729;
614
615 final int length = Long.BYTES;
616 final ByteBuffer buffer = ByteBuffer.allocate(length);
617 final byte[] bytes = buffer.array();
618 final long[] data = createLongTestData();
619 for (final long i : data) {
620 buffer.putLong(0, i);
621 assertEquals(MurmurHash3.hash32x86(bytes, offset, length, seed), MurmurHash3.hash32(i, seed));
622 }
623 }
624
625
626
627
628
629
630
631
632
633 @Test
634 void testHash32String() {
635 final int seed = 104729;
636
637 final int minSize = 1;
638 final int maxSize = 11;
639
640 final int codePoints = 112956;
641 final char[] chars = new char[(maxSize - minSize) * 2];
642 for (int i = 0; i < 1000; i++) {
643 int pos = 0;
644 final int size = ThreadLocalRandom.current().nextInt(minSize, maxSize);
645 for (int j = 0; j < size; j++) {
646 final int codePoint = ThreadLocalRandom.current().nextInt(codePoints);
647 pos += Character.toChars(codePoint, chars, pos);
648 }
649 final String text = String.copyValueOf(chars, 0, pos);
650 final byte[] bytes = StringUtils.getBytesUtf8(text);
651 final int h1 = MurmurHash3.hash32(bytes, 0, bytes.length, seed);
652 final int h2 = MurmurHash3.hash32(text);
653 assertEquals(h1, h2);
654 }
655 }
656
657
658
659
660
661
662
663
664
665
666 @Test
667 void testHash32WithLength() {
668
669 assertEquals(1905657630, MurmurHash3.hash32(RANDOM_BYTES, RANDOM_BYTES.length));
670
671
672
673
674
675 final int[] answers = { -965378730, 418246248, 1175981702, -616767012, -12304673, 1697005142, -1212417875, -420043393, -826068069, -1721451528,
676 -544986914, 892942691, 27535194, 974863697, 1835661694, -894915836, 1826914566, -677571679, 1218764493, -375719050, -1320048170, -503583763,
677 1321750696, -175065786, -496878386, -12065683, 512351473, 716560510, -1944803590, 10253199, 1105638211, 525704533, };
678 for (int i = 0; i < answers.length; i++) {
679
680
681 if (i % 4 == 0 || !negativeBytes(RANDOM_BYTES, i / 4 * 4, i % 4)) {
682 assertEquals(answers[i], MurmurHash3.hash32(RANDOM_BYTES, i));
683 } else {
684 assertNotEquals(answers[i], MurmurHash3.hash32(RANDOM_BYTES, i));
685 }
686 }
687 }
688
689
690
691
692
693
694
695
696
697
698 @Test
699 void testHash32WithLengthAndSeed() {
700 final int seed = -42;
701
702 assertEquals(1693958011, MurmurHash3.hash32(RANDOM_BYTES, RANDOM_BYTES.length, seed));
703
704
705
706
707
708 final int[] answers = { 192929823, 7537536, -99368911, -1261039957, -1719251056, -399594848, 372285930, -80756529, 1770924588, -1071759082, 1832217706,
709 1921413466, 1701676113, 675584253, 1620634486, 427719405, -973727623, 533209078, 136016960, 1947798330, 428635832, -1125743884, 793211715,
710 -2068889169, -136818786, -720841364, -891446378, 1990860976, -710528065, -1602505694, -1493714677, 1911121524, };
711 for (int i = 0; i < answers.length; i++) {
712
713
714 if (i % 4 == 0 || !negativeBytes(RANDOM_BYTES, i / 4 * 4, i % 4)) {
715 assertEquals(answers[i], MurmurHash3.hash32(RANDOM_BYTES, i, seed));
716 } else {
717 assertNotEquals(answers[i], MurmurHash3.hash32(RANDOM_BYTES, i, seed));
718 }
719 }
720 }
721
722
723
724
725
726
727
728
729
730
731 @Test
732 void testHash32WithOffsetLengthAndSeed() {
733 final int seed = -42;
734 final int offset = 13;
735
736
737
738
739
740 final int[] answers = { 192929823, -27171978, -1282326280, -816314453, -1176217753, -1904531247, 1962794233, -1302316624, -1151850323, -1464386748,
741 -369299427, 972232488, 1747314487, 2137398916, 690986564, -1985866226, -678669121, -2123325690, -253319081, 46181235, 656058278, 1401175653,
742 1750113912, -1567219725, 2032742772, -2024269989, -305340794, 1161737942, -661265418, 172838872, -650122718, -1934812417, };
743 for (int i = 0; i < answers.length; i++) {
744
745
746 if (i % 4 == 0 || !negativeBytes(RANDOM_BYTES, offset + i / 4 * 4, i % 4)) {
747 assertEquals(answers[i], MurmurHash3.hash32(RANDOM_BYTES, offset, i, seed));
748 } else {
749 assertNotEquals(answers[i], MurmurHash3.hash32(RANDOM_BYTES, offset, i, seed));
750 }
751 }
752 }
753
754
755
756
757 @Test
758 void testHash32WithTrailingNegativeSignedBytesIsInvalid() {
759
760
761
762
763
764
765
766
767 assertNotEquals(-43192051, MurmurHash3.hash32(new byte[] { -1 }, 0, 1, 0));
768 assertNotEquals(-582037868, MurmurHash3.hash32(new byte[] { 0, -1 }, 0, 2, 0));
769 assertNotEquals(922088087, MurmurHash3.hash32(new byte[] { 0, 0, -1 }, 0, 3, 0));
770 assertNotEquals(-1309567588, MurmurHash3.hash32(new byte[] { -1, 0 }, 0, 2, 0));
771 assertNotEquals(-363779670, MurmurHash3.hash32(new byte[] { -1, 0, 0 }, 0, 3, 0));
772 assertNotEquals(-225068062, MurmurHash3.hash32(new byte[] { 0, -1, 0 }, 0, 3, 0));
773 }
774
775
776
777
778
779
780
781
782
783
784 @Test
785 void testHash32x86() {
786
787
788
789 assertEquals(1546271276, MurmurHash3.hash32x86(RANDOM_BYTES));
790
791
792
793
794
795 final int[] answers = { 0, -1353253853, 915381745, -734983419, 1271125654, -1042265893, -1204521619, 735845843, 138310876, -1918938664, 1399647898,
796 -1126342309, 2067593280, 1220975287, 1941281084, -1289513180, 942412060, -618173583, -269546647, -1645631262, 1162379906, -1960125577,
797 -1856773195, 1980513522, 1174612855, 905810751, 1044578220, -1758486689, -491393913, 839836946, -435014415, 2044851178 };
798 for (int i = 0; i < answers.length; i++) {
799 final byte[] bytes = Arrays.copyOf(RANDOM_BYTES, i);
800 assertEquals(answers[i], MurmurHash3.hash32x86(bytes));
801 }
802 }
803
804
805
806
807
808
809
810
811
812
813 @Test
814 void testHash32x86WithOffsetLengthAndSeed() {
815
816 final int seed = -42;
817 final int offset = 13;
818 final int[] answers = { 192929823, -27171978, -1282326280, -816314453, -1176217753, -1904531247, 1962794233, -1302316624, -1151850323, -1464386748,
819 -369299427, 972232488, 1747314487, 2137398916, 690986564, -1985866226, -678669121, -2123325690, -253319081, 46181235, 656058278, 1401175653,
820 1750113912, -1567219725, 2032742772, -2024269989, -305340794, 1161737942, -661265418, 172838872, -650122718, -1934812417 };
821 for (int i = 0; i < answers.length; i++) {
822 assertEquals(answers[i], MurmurHash3.hash32x86(RANDOM_BYTES, offset, i, seed));
823 }
824 }
825
826
827
828
829 @Test
830 void testHash32x86WithTrailingNegativeSignedBytes() {
831
832
833 assertEquals(-43192051, MurmurHash3.hash32x86(new byte[] { -1 }, 0, 1, 0));
834 assertEquals(-582037868, MurmurHash3.hash32x86(new byte[] { 0, -1 }, 0, 2, 0));
835 assertEquals(922088087, MurmurHash3.hash32x86(new byte[] { 0, 0, -1 }, 0, 3, 0));
836 assertEquals(-1309567588, MurmurHash3.hash32x86(new byte[] { -1, 0 }, 0, 2, 0));
837 assertEquals(-363779670, MurmurHash3.hash32x86(new byte[] { -1, 0, 0 }, 0, 3, 0));
838 assertEquals(-225068062, MurmurHash3.hash32x86(new byte[] { 0, -1, 0 }, 0, 3, 0));
839 }
840
841
842
843
844 @Test
845 void testHash64() {
846 final byte[] origin = StringUtils.getBytesUtf8(TEST_HASH64);
847 final long hash = MurmurHash3.hash64(origin);
848 assertEquals(5785358552565094607L, hash);
849 }
850
851
852
853
854
855
856
857
858 @Test
859 void testHash64InNotEqualToHash128() {
860 for (int i = 0; i < 32; i++) {
861 final byte[] bytes = Arrays.copyOf(RANDOM_BYTES, i);
862 final long h1 = MurmurHash3.hash64(bytes);
863 final long[] hash = MurmurHash3.hash128(bytes);
864 assertNotEquals(hash[0], h1, "Did not expect hash64 to match upper bits of hash128");
865 assertNotEquals(hash[1], h1, "Did not expect hash64 to match lower bits of hash128");
866 }
867 }
868
869
870
871
872 @Test
873 void testHash64WithOffsetAndLength() {
874 final byte[] origin = StringUtils.getBytesUtf8(TEST_HASH64);
875 final byte[] originOffset = new byte[origin.length + 150];
876 Arrays.fill(originOffset, (byte) 123);
877 System.arraycopy(origin, 0, originOffset, 150, origin.length);
878 final long hash = MurmurHash3.hash64(originOffset, 150, origin.length);
879 assertEquals(5785358552565094607L, hash);
880 }
881
882
883
884
885
886 @Test
887 void testHash64WithPrimitives() {
888
889 final int offset = 0;
890 final int seed = 104729;
891
892 final int iters = 1000;
893 final ByteBuffer shortBuffer = ByteBuffer.allocate(Short.BYTES);
894 final ByteBuffer intBuffer = ByteBuffer.allocate(Integer.BYTES);
895 final ByteBuffer longBuffer = ByteBuffer.allocate(Long.BYTES);
896 final byte[] shortBytes = shortBuffer.array();
897 final byte[] intBytes = intBuffer.array();
898 final byte[] longBytes = longBuffer.array();
899 for (int i = 0; i < iters; ++i) {
900 final long ln = ThreadLocalRandom.current().nextLong();
901
902 final int in = (int) (ln >>> 3);
903 final short sn = (short) (ln >>> 5);
904 shortBuffer.putShort(0, sn);
905 assertEquals(MurmurHash3.hash64(shortBytes, offset, shortBytes.length, seed), MurmurHash3.hash64(sn));
906 intBuffer.putInt(0, in);
907 assertEquals(MurmurHash3.hash64(intBytes, offset, intBytes.length, seed), MurmurHash3.hash64(in));
908 longBuffer.putLong(0, ln);
909 assertEquals(MurmurHash3.hash64(longBytes, offset, longBytes.length, seed), MurmurHash3.hash64(ln));
910 }
911 }
912
913
914
915
916 @Test
917 void testIncrementalHash32() {
918 final byte[] bytes = new byte[1023];
919 ThreadLocalRandom.current().nextBytes(bytes);
920
921 for (final int seed : new int[] { -567, 0, 6787990 }) {
922
923
924 assertIncrementalHash32(bytes, seed, 0, 0);
925
926 assertIncrementalHash32(bytes, seed, 1, 1, 1, 1, 1, 1, 1, 1);
927
928 assertIncrementalHash32(bytes, seed, 1, 4);
929 assertIncrementalHash32(bytes, seed, 2, 4);
930 assertIncrementalHash32(bytes, seed, 3, 4);
931
932 assertIncrementalHash32(bytes, seed, 4, 1);
933 assertIncrementalHash32(bytes, seed, 4, 2);
934 assertIncrementalHash32(bytes, seed, 4, 3);
935
936 assertIncrementalHash32(bytes, seed, 4, 16, 64);
937
938 for (int i = 0; i < 10; i++) {
939 assertIncrementalHash32x86(bytes, seed, createRandomBlocks(bytes.length));
940 }
941 }
942 }
943
944
945
946
947 @Test
948 void testIncrementalHash32x86() {
949 final byte[] bytes = new byte[1023];
950 ThreadLocalRandom.current().nextBytes(bytes);
951
952 for (final int seed : new int[] { -567, 0, 6787990 }) {
953
954
955 assertIncrementalHash32x86(bytes, seed, 0, 0);
956
957 assertIncrementalHash32x86(bytes, seed, 1, 1, 1, 1, 1, 1, 1, 1);
958
959 assertIncrementalHash32x86(bytes, seed, 1, 4);
960 assertIncrementalHash32x86(bytes, seed, 2, 4);
961 assertIncrementalHash32x86(bytes, seed, 3, 4);
962
963 assertIncrementalHash32x86(bytes, seed, 4, 1);
964 assertIncrementalHash32x86(bytes, seed, 4, 2);
965 assertIncrementalHash32x86(bytes, seed, 4, 3);
966
967 assertIncrementalHash32x86(bytes, seed, 4, 16, 64);
968
969 for (int i = 0; i < 10; i++) {
970 assertIncrementalHash32x86(bytes, seed, createRandomBlocks(bytes.length));
971 }
972 }
973 }
974
975
976
977
978
979
980 @Test
981 void testIncrementalHashWithUnprocessedBytesAndHugeLengthArray() {
982
983
984
985 final int unprocessedSize = 3;
986 final int hugeLength = Integer.MAX_VALUE - 2;
987 assertTrue(unprocessedSize + hugeLength < 4, "This should overflow to negative");
988
989
990 byte[] bytes = null;
991 try {
992 bytes = new byte[hugeLength];
993 } catch (final OutOfMemoryError ignore) {
994
995
996 }
997 assumeTrue(bytes != null, "Cannot allocate array of length " + hugeLength);
998
999 final IncrementalHash32x86 inc = new IncrementalHash32x86();
1000 inc.start(0);
1001
1002 inc.add(bytes, 0, unprocessedSize);
1003
1004 inc.add(bytes, 0, hugeLength);
1005 }
1006 }