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