]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-hashmap.c
7f25ad101141c2c253475b753994cc55314d5731
[thirdparty/systemd.git] / src / test / test-hashmap.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "hashmap.h"
4 #include "tests.h"
5
6 unsigned custom_counter = 0;
7 static void custom_destruct(void* p) {
8 custom_counter--;
9 free(p);
10 }
11
12 DEFINE_HASH_OPS_FULL(boring_hash_ops, char, string_hash_func, string_compare_func, free, char, free);
13 DEFINE_HASH_OPS_FULL(custom_hash_ops, char, string_hash_func, string_compare_func, custom_destruct, char, custom_destruct);
14
15 TEST(ordered_hashmap_next) {
16 _cleanup_ordered_hashmap_free_ OrderedHashmap *m = NULL;
17 int i;
18
19 assert_se(m = ordered_hashmap_new(NULL));
20 for (i = -2; i <= 2; i++)
21 assert_se(ordered_hashmap_put(m, INT_TO_PTR(i), INT_TO_PTR(i+10)) == 1);
22 for (i = -2; i <= 1; i++)
23 assert_se(ordered_hashmap_next(m, INT_TO_PTR(i)) == INT_TO_PTR(i+11));
24 assert_se(!ordered_hashmap_next(m, INT_TO_PTR(2)));
25 assert_se(!ordered_hashmap_next(NULL, INT_TO_PTR(1)));
26 assert_se(!ordered_hashmap_next(m, INT_TO_PTR(3)));
27 }
28
29 TEST(uint64_compare_func) {
30 const uint64_t a = 0x100, b = 0x101;
31
32 assert_se(uint64_compare_func(&a, &a) == 0);
33 assert_se(uint64_compare_func(&a, &b) == -1);
34 assert_se(uint64_compare_func(&b, &a) == 1);
35 }
36
37 TEST(trivial_compare_func) {
38 assert_se(trivial_compare_func(INT_TO_PTR('a'), INT_TO_PTR('a')) == 0);
39 assert_se(trivial_compare_func(INT_TO_PTR('a'), INT_TO_PTR('b')) == -1);
40 assert_se(trivial_compare_func(INT_TO_PTR('b'), INT_TO_PTR('a')) == 1);
41 }
42
43 TEST(string_compare_func) {
44 ASSERT_NE(string_compare_func("fred", "wilma"), 0);
45 assert_se(string_compare_func("fred", "fred") == 0);
46 }
47
48 static void compare_cache(Hashmap *map, IteratedCache *cache) {
49 const void **keys = NULL, **values = NULL;
50 unsigned num, idx;
51 void *k, *v;
52
53 assert_se(iterated_cache_get(cache, &keys, &values, &num) == 0);
54 assert_se(num == 0 || keys);
55 assert_se(num == 0 || values);
56
57 idx = 0;
58 HASHMAP_FOREACH_KEY(v, k, map) {
59 assert_se(v == values[idx]);
60 assert_se(k == keys[idx]);
61
62 idx++;
63 }
64
65 assert_se(idx == num);
66 }
67
68 TEST(iterated_cache) {
69 Hashmap *m;
70 IteratedCache *c;
71
72 assert_se(m = hashmap_new(NULL));
73 assert_se(c = hashmap_iterated_cache_new(m));
74 compare_cache(m, c);
75
76 for (int stage = 0; stage < 100; stage++) {
77
78 for (int i = 0; i < 100; i++) {
79 int foo = stage * 1000 + i;
80
81 assert_se(hashmap_put(m, INT_TO_PTR(foo), INT_TO_PTR(foo + 777)) == 1);
82 }
83
84 compare_cache(m, c);
85
86 if (!(stage % 10)) {
87 for (int i = 0; i < 100; i++) {
88 int foo = stage * 1000 + i;
89
90 assert_se(hashmap_remove(m, INT_TO_PTR(foo)) == INT_TO_PTR(foo + 777));
91 }
92
93 compare_cache(m, c);
94 }
95 }
96
97 hashmap_clear(m);
98 compare_cache(m, c);
99
100 ASSERT_NULL(hashmap_free(m));
101 ASSERT_NULL(iterated_cache_free(c));
102 }
103
104 TEST(hashmap_put_strdup) {
105 _cleanup_hashmap_free_ Hashmap *m = NULL;
106 char *s;
107
108 /* We don't have ordered_hashmap_put_strdup() yet. If it is added,
109 * these tests should be moved to test-hashmap-plain.c. */
110
111 assert_se(hashmap_put_strdup(&m, "foo", "bar") == 1);
112 assert_se(hashmap_put_strdup(&m, "foo", "bar") == 0);
113 assert_se(hashmap_put_strdup(&m, "foo", "BAR") == -EEXIST);
114 assert_se(hashmap_put_strdup(&m, "foo", "bar") == 0);
115 assert_se(hashmap_contains(m, "foo"));
116
117 s = hashmap_get(m, "foo");
118 ASSERT_STREQ(s, "bar");
119
120 assert_se(hashmap_put_strdup(&m, "xxx", "bar") == 1);
121 assert_se(hashmap_put_strdup(&m, "xxx", "bar") == 0);
122 assert_se(hashmap_put_strdup(&m, "xxx", "BAR") == -EEXIST);
123 assert_se(hashmap_put_strdup(&m, "xxx", "bar") == 0);
124 assert_se(hashmap_contains(m, "xxx"));
125
126 s = hashmap_get(m, "xxx");
127 ASSERT_STREQ(s, "bar");
128 }
129
130 TEST(hashmap_put_strdup_null) {
131 _cleanup_hashmap_free_ Hashmap *m = NULL;
132 char *s;
133
134 assert_se(hashmap_put_strdup(&m, "foo", "bar") == 1);
135 assert_se(hashmap_put_strdup(&m, "foo", "bar") == 0);
136 assert_se(hashmap_put_strdup(&m, "foo", NULL) == -EEXIST);
137 assert_se(hashmap_put_strdup(&m, "foo", "bar") == 0);
138 assert_se(hashmap_contains(m, "foo"));
139
140 s = hashmap_get(m, "foo");
141 ASSERT_STREQ(s, "bar");
142
143 assert_se(hashmap_put_strdup(&m, "xxx", NULL) == 1);
144 assert_se(hashmap_put_strdup(&m, "xxx", "bar") == -EEXIST);
145 assert_se(hashmap_put_strdup(&m, "xxx", NULL) == 0);
146 assert_se(hashmap_contains(m, "xxx"));
147
148 s = hashmap_get(m, "xxx");
149 ASSERT_NULL(s);
150 }
151
152 /* This file tests in test-hashmap-plain.c, and tests in test-hashmap-ordered.c, which is generated
153 * from test-hashmap-plain.c. Hashmap tests should be added to test-hashmap-plain.c, and here only if
154 * they don't apply to ordered hashmaps. */
155
156 /* This variable allows us to assert that the tests from different compilation units were actually run. */
157 int n_extern_tests_run = 0;
158
159 static int intro(void) {
160 assert_se(n_extern_tests_run == 0);
161 return EXIT_SUCCESS;
162 }
163
164 static int outro(void) {
165 /* Ensure hashmap and ordered_hashmap were tested. */
166 assert_se(n_extern_tests_run == 2);
167 return EXIT_SUCCESS;
168 }
169
170 DEFINE_TEST_MAIN_FULL(LOG_INFO, intro, outro);