xref: /netbsd-src/external/bsd/jemalloc.old/dist/test/unit/hash.c (revision 8e33eff89e26cf71871ead62f0d5063e1313c33a)
1*8e33eff8Schristos /*
2*8e33eff8Schristos  * This file is based on code that is part of SMHasher
3*8e33eff8Schristos  * (https://code.google.com/p/smhasher/), and is subject to the MIT license
4*8e33eff8Schristos  * (http://www.opensource.org/licenses/mit-license.php).  Both email addresses
5*8e33eff8Schristos  * associated with the source code's revision history belong to Austin Appleby,
6*8e33eff8Schristos  * and the revision history ranges from 2010 to 2012.  Therefore the copyright
7*8e33eff8Schristos  * and license are here taken to be:
8*8e33eff8Schristos  *
9*8e33eff8Schristos  * Copyright (c) 2010-2012 Austin Appleby
10*8e33eff8Schristos  *
11*8e33eff8Schristos  * Permission is hereby granted, free of charge, to any person obtaining a copy
12*8e33eff8Schristos  * of this software and associated documentation files (the "Software"), to deal
13*8e33eff8Schristos  * in the Software without restriction, including without limitation the rights
14*8e33eff8Schristos  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15*8e33eff8Schristos  * copies of the Software, and to permit persons to whom the Software is
16*8e33eff8Schristos  * furnished to do so, subject to the following conditions:
17*8e33eff8Schristos  *
18*8e33eff8Schristos  * The above copyright notice and this permission notice shall be included in
19*8e33eff8Schristos  * all copies or substantial portions of the Software.
20*8e33eff8Schristos  *
21*8e33eff8Schristos  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22*8e33eff8Schristos  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23*8e33eff8Schristos  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24*8e33eff8Schristos  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25*8e33eff8Schristos  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26*8e33eff8Schristos  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27*8e33eff8Schristos  * THE SOFTWARE.
28*8e33eff8Schristos  */
29*8e33eff8Schristos 
30*8e33eff8Schristos #include "test/jemalloc_test.h"
31*8e33eff8Schristos #include "jemalloc/internal/hash.h"
32*8e33eff8Schristos 
33*8e33eff8Schristos typedef enum {
34*8e33eff8Schristos 	hash_variant_x86_32,
35*8e33eff8Schristos 	hash_variant_x86_128,
36*8e33eff8Schristos 	hash_variant_x64_128
37*8e33eff8Schristos } hash_variant_t;
38*8e33eff8Schristos 
39*8e33eff8Schristos static int
40*8e33eff8Schristos hash_variant_bits(hash_variant_t variant) {
41*8e33eff8Schristos 	switch (variant) {
42*8e33eff8Schristos 	case hash_variant_x86_32: return 32;
43*8e33eff8Schristos 	case hash_variant_x86_128: return 128;
44*8e33eff8Schristos 	case hash_variant_x64_128: return 128;
45*8e33eff8Schristos 	default: not_reached();
46*8e33eff8Schristos 	}
47*8e33eff8Schristos }
48*8e33eff8Schristos 
49*8e33eff8Schristos static const char *
50*8e33eff8Schristos hash_variant_string(hash_variant_t variant) {
51*8e33eff8Schristos 	switch (variant) {
52*8e33eff8Schristos 	case hash_variant_x86_32: return "hash_x86_32";
53*8e33eff8Schristos 	case hash_variant_x86_128: return "hash_x86_128";
54*8e33eff8Schristos 	case hash_variant_x64_128: return "hash_x64_128";
55*8e33eff8Schristos 	default: not_reached();
56*8e33eff8Schristos 	}
57*8e33eff8Schristos }
58*8e33eff8Schristos 
59*8e33eff8Schristos #define KEY_SIZE	256
60*8e33eff8Schristos static void
61*8e33eff8Schristos hash_variant_verify_key(hash_variant_t variant, uint8_t *key) {
62*8e33eff8Schristos 	const int hashbytes = hash_variant_bits(variant) / 8;
63*8e33eff8Schristos 	const int hashes_size = hashbytes * 256;
64*8e33eff8Schristos 	VARIABLE_ARRAY(uint8_t, hashes, hashes_size);
65*8e33eff8Schristos 	VARIABLE_ARRAY(uint8_t, final, hashbytes);
66*8e33eff8Schristos 	unsigned i;
67*8e33eff8Schristos 	uint32_t computed, expected;
68*8e33eff8Schristos 
69*8e33eff8Schristos 	memset(key, 0, KEY_SIZE);
70*8e33eff8Schristos 	memset(hashes, 0, hashes_size);
71*8e33eff8Schristos 	memset(final, 0, hashbytes);
72*8e33eff8Schristos 
73*8e33eff8Schristos 	/*
74*8e33eff8Schristos 	 * Hash keys of the form {0}, {0,1}, {0,1,2}, ..., {0,1,...,255} as the
75*8e33eff8Schristos 	 * seed.
76*8e33eff8Schristos 	 */
77*8e33eff8Schristos 	for (i = 0; i < 256; i++) {
78*8e33eff8Schristos 		key[i] = (uint8_t)i;
79*8e33eff8Schristos 		switch (variant) {
80*8e33eff8Schristos 		case hash_variant_x86_32: {
81*8e33eff8Schristos 			uint32_t out;
82*8e33eff8Schristos 			out = hash_x86_32(key, i, 256-i);
83*8e33eff8Schristos 			memcpy(&hashes[i*hashbytes], &out, hashbytes);
84*8e33eff8Schristos 			break;
85*8e33eff8Schristos 		} case hash_variant_x86_128: {
86*8e33eff8Schristos 			uint64_t out[2];
87*8e33eff8Schristos 			hash_x86_128(key, i, 256-i, out);
88*8e33eff8Schristos 			memcpy(&hashes[i*hashbytes], out, hashbytes);
89*8e33eff8Schristos 			break;
90*8e33eff8Schristos 		} case hash_variant_x64_128: {
91*8e33eff8Schristos 			uint64_t out[2];
92*8e33eff8Schristos 			hash_x64_128(key, i, 256-i, out);
93*8e33eff8Schristos 			memcpy(&hashes[i*hashbytes], out, hashbytes);
94*8e33eff8Schristos 			break;
95*8e33eff8Schristos 		} default: not_reached();
96*8e33eff8Schristos 		}
97*8e33eff8Schristos 	}
98*8e33eff8Schristos 
99*8e33eff8Schristos 	/* Hash the result array. */
100*8e33eff8Schristos 	switch (variant) {
101*8e33eff8Schristos 	case hash_variant_x86_32: {
102*8e33eff8Schristos 		uint32_t out = hash_x86_32(hashes, hashes_size, 0);
103*8e33eff8Schristos 		memcpy(final, &out, sizeof(out));
104*8e33eff8Schristos 		break;
105*8e33eff8Schristos 	} case hash_variant_x86_128: {
106*8e33eff8Schristos 		uint64_t out[2];
107*8e33eff8Schristos 		hash_x86_128(hashes, hashes_size, 0, out);
108*8e33eff8Schristos 		memcpy(final, out, sizeof(out));
109*8e33eff8Schristos 		break;
110*8e33eff8Schristos 	} case hash_variant_x64_128: {
111*8e33eff8Schristos 		uint64_t out[2];
112*8e33eff8Schristos 		hash_x64_128(hashes, hashes_size, 0, out);
113*8e33eff8Schristos 		memcpy(final, out, sizeof(out));
114*8e33eff8Schristos 		break;
115*8e33eff8Schristos 	} default: not_reached();
116*8e33eff8Schristos 	}
117*8e33eff8Schristos 
118*8e33eff8Schristos 	computed = (final[0] << 0) | (final[1] << 8) | (final[2] << 16) |
119*8e33eff8Schristos 	    (final[3] << 24);
120*8e33eff8Schristos 
121*8e33eff8Schristos 	switch (variant) {
122*8e33eff8Schristos #ifdef JEMALLOC_BIG_ENDIAN
123*8e33eff8Schristos 	case hash_variant_x86_32: expected = 0x6213303eU; break;
124*8e33eff8Schristos 	case hash_variant_x86_128: expected = 0x266820caU; break;
125*8e33eff8Schristos 	case hash_variant_x64_128: expected = 0xcc622b6fU; break;
126*8e33eff8Schristos #else
127*8e33eff8Schristos 	case hash_variant_x86_32: expected = 0xb0f57ee3U; break;
128*8e33eff8Schristos 	case hash_variant_x86_128: expected = 0xb3ece62aU; break;
129*8e33eff8Schristos 	case hash_variant_x64_128: expected = 0x6384ba69U; break;
130*8e33eff8Schristos #endif
131*8e33eff8Schristos 	default: not_reached();
132*8e33eff8Schristos 	}
133*8e33eff8Schristos 
134*8e33eff8Schristos 	assert_u32_eq(computed, expected,
135*8e33eff8Schristos 	    "Hash mismatch for %s(): expected %#x but got %#x",
136*8e33eff8Schristos 	    hash_variant_string(variant), expected, computed);
137*8e33eff8Schristos }
138*8e33eff8Schristos 
139*8e33eff8Schristos static void
140*8e33eff8Schristos hash_variant_verify(hash_variant_t variant) {
141*8e33eff8Schristos #define MAX_ALIGN	16
142*8e33eff8Schristos 	uint8_t key[KEY_SIZE + (MAX_ALIGN - 1)];
143*8e33eff8Schristos 	unsigned i;
144*8e33eff8Schristos 
145*8e33eff8Schristos 	for (i = 0; i < MAX_ALIGN; i++) {
146*8e33eff8Schristos 		hash_variant_verify_key(variant, &key[i]);
147*8e33eff8Schristos 	}
148*8e33eff8Schristos #undef MAX_ALIGN
149*8e33eff8Schristos }
150*8e33eff8Schristos #undef KEY_SIZE
151*8e33eff8Schristos 
152*8e33eff8Schristos TEST_BEGIN(test_hash_x86_32) {
153*8e33eff8Schristos 	hash_variant_verify(hash_variant_x86_32);
154*8e33eff8Schristos }
155*8e33eff8Schristos TEST_END
156*8e33eff8Schristos 
157*8e33eff8Schristos TEST_BEGIN(test_hash_x86_128) {
158*8e33eff8Schristos 	hash_variant_verify(hash_variant_x86_128);
159*8e33eff8Schristos }
160*8e33eff8Schristos TEST_END
161*8e33eff8Schristos 
162*8e33eff8Schristos TEST_BEGIN(test_hash_x64_128) {
163*8e33eff8Schristos 	hash_variant_verify(hash_variant_x64_128);
164*8e33eff8Schristos }
165*8e33eff8Schristos TEST_END
166*8e33eff8Schristos 
167*8e33eff8Schristos int
168*8e33eff8Schristos main(void) {
169*8e33eff8Schristos 	return test(
170*8e33eff8Schristos 	    test_hash_x86_32,
171*8e33eff8Schristos 	    test_hash_x86_128,
172*8e33eff8Schristos 	    test_hash_x64_128);
173*8e33eff8Schristos }
174