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