xref: /freebsd/sys/contrib/openzfs/tests/unit/test_cityhash.c (revision 22649d4dba730d46244fd2dff4fd174903c8379f)
1*22649d4dSMartin Matuska // SPDX-License-Identifier: CDDL-1.0
2*22649d4dSMartin Matuska /*
3*22649d4dSMartin Matuska  * This file and its contents are supplied under the terms of the
4*22649d4dSMartin Matuska  * Common Development and Distribution License ("CDDL"), version 1.0.
5*22649d4dSMartin Matuska  * You may only use this file in accordance with the terms of version
6*22649d4dSMartin Matuska  * 1.0 of the CDDL.
7*22649d4dSMartin Matuska  *
8*22649d4dSMartin Matuska  * A full copy of the text of the CDDL should have accompanied this
9*22649d4dSMartin Matuska  * source.  A copy of the CDDL is also available via the Internet at
10*22649d4dSMartin Matuska  * https://opensource.org/license/CDDL-1.0.
11*22649d4dSMartin Matuska  */
12*22649d4dSMartin Matuska 
13*22649d4dSMartin Matuska /*
14*22649d4dSMartin Matuska  * Copyright (c) 2026, Christos Longros.
15*22649d4dSMartin Matuska  */
16*22649d4dSMartin Matuska 
17*22649d4dSMartin Matuska #include <sys/types.h>
18*22649d4dSMartin Matuska #include <cityhash.h>
19*22649d4dSMartin Matuska 
20*22649d4dSMartin Matuska #include "unit.h"
21*22649d4dSMartin Matuska 
22*22649d4dSMartin Matuska /* ========== */
23*22649d4dSMartin Matuska 
24*22649d4dSMartin Matuska /*
25*22649d4dSMartin Matuska  * cityhash maps one to four uint64_t words to a single uint64_t hash.  The
26*22649d4dSMartin Matuska  * output is fixed by the algorithm, so we can verify exact results.
27*22649d4dSMartin Matuska  */
28*22649d4dSMartin Matuska static MunitResult
test_cityhash_known(const MunitParameter params[],void * data)29*22649d4dSMartin Matuska test_cityhash_known(const MunitParameter params[], void *data)
30*22649d4dSMartin Matuska {
31*22649d4dSMartin Matuska 	(void) params, (void) data;
32*22649d4dSMartin Matuska 
33*22649d4dSMartin Matuska 	unit_eq(cityhash1(0), 0x7087061603e53293ULL);
34*22649d4dSMartin Matuska 	unit_eq(cityhash1(0x0123456789abcdefULL), 0x4d72820d4fcae8ffULL);
35*22649d4dSMartin Matuska 	unit_eq(cityhash2(1, 2), 0x8f1c7927f8b5dff2ULL);
36*22649d4dSMartin Matuska 	unit_eq(cityhash3(1, 2, 3), 0x4f6fe08120ecb540ULL);
37*22649d4dSMartin Matuska 	unit_eq(cityhash4(0x1111111111111111ULL, 0x2222222222222222ULL,
38*22649d4dSMartin Matuska 	    0x3333333333333333ULL, 0x4444444444444444ULL),
39*22649d4dSMartin Matuska 	    0xa6370a2070fdfd12ULL);
40*22649d4dSMartin Matuska 
41*22649d4dSMartin Matuska 	return (MUNIT_OK);
42*22649d4dSMartin Matuska }
43*22649d4dSMartin Matuska 
44*22649d4dSMartin Matuska /*
45*22649d4dSMartin Matuska  * cityhash1/2/3 are specialized versions of cityhash4, so each must match
46*22649d4dSMartin Matuska  * cityhash4 on the same arguments.  cityhash1 passes its word as the 2nd
47*22649d4dSMartin Matuska  * argument.
48*22649d4dSMartin Matuska  */
49*22649d4dSMartin Matuska static MunitResult
test_cityhash_specialized(const MunitParameter params[],void * data)50*22649d4dSMartin Matuska test_cityhash_specialized(const MunitParameter params[], void *data)
51*22649d4dSMartin Matuska {
52*22649d4dSMartin Matuska 	(void) params, (void) data;
53*22649d4dSMartin Matuska 
54*22649d4dSMartin Matuska 	uint64_t a = 0xdeadbeefULL, b = 0xfeedfaceULL, c = 0x00c0ffeeULL;
55*22649d4dSMartin Matuska 
56*22649d4dSMartin Matuska 	unit_eq(cityhash1(a), cityhash4(0, a, 0, 0));
57*22649d4dSMartin Matuska 	unit_eq(cityhash2(a, b), cityhash4(a, b, 0, 0));
58*22649d4dSMartin Matuska 	unit_eq(cityhash3(a, b, c), cityhash4(a, b, c, 0));
59*22649d4dSMartin Matuska 
60*22649d4dSMartin Matuska 	return (MUNIT_OK);
61*22649d4dSMartin Matuska }
62*22649d4dSMartin Matuska 
63*22649d4dSMartin Matuska /* Different arguments produce different hash results. */
64*22649d4dSMartin Matuska static MunitResult
test_cityhash_distinct(const MunitParameter params[],void * data)65*22649d4dSMartin Matuska test_cityhash_distinct(const MunitParameter params[], void *data)
66*22649d4dSMartin Matuska {
67*22649d4dSMartin Matuska 	(void) params, (void) data;
68*22649d4dSMartin Matuska 
69*22649d4dSMartin Matuska 	uint64_t base = cityhash4(1, 2, 3, 4);
70*22649d4dSMartin Matuska 	unit_ne(base, cityhash4(9, 2, 3, 4));	/* first word */
71*22649d4dSMartin Matuska 	unit_ne(base, cityhash4(1, 9, 3, 4));	/* second word */
72*22649d4dSMartin Matuska 	unit_ne(base, cityhash4(1, 2, 9, 4));	/* third word */
73*22649d4dSMartin Matuska 	unit_ne(base, cityhash4(1, 2, 3, 9));	/* fourth word */
74*22649d4dSMartin Matuska 	unit_ne(cityhash1(0), cityhash1(1));
75*22649d4dSMartin Matuska 
76*22649d4dSMartin Matuska 	return (MUNIT_OK);
77*22649d4dSMartin Matuska }
78*22649d4dSMartin Matuska 
79*22649d4dSMartin Matuska /* ========== */
80*22649d4dSMartin Matuska 
81*22649d4dSMartin Matuska static const MunitTest cityhash_tests[] = {
82*22649d4dSMartin Matuska 	UNIT_TEST("known",		test_cityhash_known),
83*22649d4dSMartin Matuska 	UNIT_TEST("specialized",	test_cityhash_specialized),
84*22649d4dSMartin Matuska 	UNIT_TEST("distinct",		test_cityhash_distinct),
85*22649d4dSMartin Matuska 	{ 0 },
86*22649d4dSMartin Matuska };
87*22649d4dSMartin Matuska 
88*22649d4dSMartin Matuska static const MunitSuite cityhash_test_suite = {
89*22649d4dSMartin Matuska 	"cityhash.",
90*22649d4dSMartin Matuska 	cityhash_tests,
91*22649d4dSMartin Matuska 	NULL,
92*22649d4dSMartin Matuska 	1,
93*22649d4dSMartin Matuska 	MUNIT_SUITE_OPTION_NONE,
94*22649d4dSMartin Matuska };
95*22649d4dSMartin Matuska 
96*22649d4dSMartin Matuska int
main(int argc,char ** argv)97*22649d4dSMartin Matuska main(int argc, char **argv)
98*22649d4dSMartin Matuska {
99*22649d4dSMartin Matuska 	return (munit_suite_main(&cityhash_test_suite, NULL, argc, argv));
100*22649d4dSMartin Matuska }
101