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