Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include "alloc-util.h"
4 : : #include "hashmap.h"
5 : : #include "log.h"
6 : : #include "nulstr-util.h"
7 : : #include "stdio-util.h"
8 : : #include "string-util.h"
9 : : #include "strv.h"
10 : : #include "time-util.h"
11 : : #include "tests.h"
12 : :
13 : : void test_hashmap_funcs(void);
14 : :
15 : 3 : static void test_hashmap_replace(void) {
16 : : Hashmap *m;
17 : : char *val1, *val2, *val3, *val4, *val5, *r;
18 : :
19 [ + - ]: 3 : log_info("/* %s */", __func__);
20 : :
21 : 3 : m = hashmap_new(&string_hash_ops);
22 : :
23 : 3 : val1 = strdup("val1");
24 [ - + ]: 3 : assert_se(val1);
25 : 3 : val2 = strdup("val2");
26 [ - + ]: 3 : assert_se(val2);
27 : 3 : val3 = strdup("val3");
28 [ - + ]: 3 : assert_se(val3);
29 : 3 : val4 = strdup("val4");
30 [ - + ]: 3 : assert_se(val4);
31 : 3 : val5 = strdup("val5");
32 [ - + ]: 3 : assert_se(val5);
33 : :
34 : 3 : hashmap_put(m, "key 1", val1);
35 : 3 : hashmap_put(m, "key 2", val2);
36 : 3 : hashmap_put(m, "key 3", val3);
37 : 3 : hashmap_put(m, "key 4", val4);
38 : :
39 : 3 : hashmap_replace(m, "key 3", val1);
40 : 3 : r = hashmap_get(m, "key 3");
41 [ - + ]: 3 : assert_se(streq(r, "val1"));
42 : :
43 : 3 : hashmap_replace(m, "key 5", val5);
44 : 3 : r = hashmap_get(m, "key 5");
45 [ - + ]: 3 : assert_se(streq(r, "val5"));
46 : :
47 : 3 : free(val1);
48 : 3 : free(val2);
49 : 3 : free(val3);
50 : 3 : free(val4);
51 : 3 : free(val5);
52 : 3 : hashmap_free(m);
53 : 3 : }
54 : :
55 : 3 : static void test_hashmap_copy(void) {
56 : : Hashmap *m, *copy;
57 : : char *val1, *val2, *val3, *val4, *r;
58 : :
59 [ + - ]: 3 : log_info("/* %s */", __func__);
60 : :
61 : 3 : val1 = strdup("val1");
62 [ - + ]: 3 : assert_se(val1);
63 : 3 : val2 = strdup("val2");
64 [ - + ]: 3 : assert_se(val2);
65 : 3 : val3 = strdup("val3");
66 [ - + ]: 3 : assert_se(val3);
67 : 3 : val4 = strdup("val4");
68 [ - + ]: 3 : assert_se(val4);
69 : :
70 : 3 : m = hashmap_new(&string_hash_ops);
71 : :
72 : 3 : hashmap_put(m, "key 1", val1);
73 : 3 : hashmap_put(m, "key 2", val2);
74 : 3 : hashmap_put(m, "key 3", val3);
75 : 3 : hashmap_put(m, "key 4", val4);
76 : :
77 : 3 : copy = hashmap_copy(m);
78 : :
79 : 3 : r = hashmap_get(copy, "key 1");
80 [ - + ]: 3 : assert_se(streq(r, "val1"));
81 : 3 : r = hashmap_get(copy, "key 2");
82 [ - + ]: 3 : assert_se(streq(r, "val2"));
83 : 3 : r = hashmap_get(copy, "key 3");
84 [ - + ]: 3 : assert_se(streq(r, "val3"));
85 : 3 : r = hashmap_get(copy, "key 4");
86 [ - + ]: 3 : assert_se(streq(r, "val4"));
87 : :
88 : 3 : hashmap_free_free(copy);
89 : 3 : hashmap_free(m);
90 : 3 : }
91 : :
92 : 3 : static void test_hashmap_get_strv(void) {
93 : : Hashmap *m;
94 : : char **strv;
95 : : char *val1, *val2, *val3, *val4;
96 : :
97 [ + - ]: 3 : log_info("/* %s */", __func__);
98 : :
99 : 3 : val1 = strdup("val1");
100 [ - + ]: 3 : assert_se(val1);
101 : 3 : val2 = strdup("val2");
102 [ - + ]: 3 : assert_se(val2);
103 : 3 : val3 = strdup("val3");
104 [ - + ]: 3 : assert_se(val3);
105 : 3 : val4 = strdup("val4");
106 [ - + ]: 3 : assert_se(val4);
107 : :
108 : 3 : m = hashmap_new(&string_hash_ops);
109 : :
110 : 3 : hashmap_put(m, "key 1", val1);
111 : 3 : hashmap_put(m, "key 2", val2);
112 : 3 : hashmap_put(m, "key 3", val3);
113 : 3 : hashmap_put(m, "key 4", val4);
114 : :
115 : 3 : strv = hashmap_get_strv(m);
116 : :
117 : : #ifndef ORDERED
118 : 3 : strv = strv_sort(strv);
119 : : #endif
120 : :
121 [ - + ]: 3 : assert_se(streq(strv[0], "val1"));
122 [ - + ]: 3 : assert_se(streq(strv[1], "val2"));
123 [ - + ]: 3 : assert_se(streq(strv[2], "val3"));
124 [ - + ]: 3 : assert_se(streq(strv[3], "val4"));
125 : :
126 : 3 : strv_free(strv);
127 : :
128 : 3 : hashmap_free(m);
129 : 3 : }
130 : :
131 : 3 : static void test_hashmap_move_one(void) {
132 : : Hashmap *m, *n;
133 : : char *val1, *val2, *val3, *val4, *r;
134 : :
135 [ + - ]: 3 : log_info("/* %s */", __func__);
136 : :
137 : 3 : val1 = strdup("val1");
138 [ - + ]: 3 : assert_se(val1);
139 : 3 : val2 = strdup("val2");
140 [ - + ]: 3 : assert_se(val2);
141 : 3 : val3 = strdup("val3");
142 [ - + ]: 3 : assert_se(val3);
143 : 3 : val4 = strdup("val4");
144 [ - + ]: 3 : assert_se(val4);
145 : :
146 : 3 : m = hashmap_new(&string_hash_ops);
147 : 3 : n = hashmap_new(&string_hash_ops);
148 : :
149 : 3 : hashmap_put(m, "key 1", val1);
150 : 3 : hashmap_put(m, "key 2", val2);
151 : 3 : hashmap_put(m, "key 3", val3);
152 : 3 : hashmap_put(m, "key 4", val4);
153 : :
154 [ - + ]: 3 : assert_se(hashmap_move_one(n, NULL, "key 3") == -ENOENT);
155 [ - + ]: 3 : assert_se(hashmap_move_one(n, m, "key 5") == -ENOENT);
156 [ - + ]: 3 : assert_se(hashmap_move_one(n, m, "key 3") == 0);
157 [ - + ]: 3 : assert_se(hashmap_move_one(n, m, "key 4") == 0);
158 : :
159 : 3 : r = hashmap_get(n, "key 3");
160 [ + - - + ]: 3 : assert_se(r && streq(r, "val3"));
161 : 3 : r = hashmap_get(n, "key 4");
162 [ + - - + ]: 3 : assert_se(r && streq(r, "val4"));
163 : 3 : r = hashmap_get(m, "key 3");
164 [ - + ]: 3 : assert_se(!r);
165 : :
166 [ - + ]: 3 : assert_se(hashmap_move_one(n, m, "key 3") == -EEXIST);
167 : :
168 : 3 : hashmap_free_free(m);
169 : 3 : hashmap_free_free(n);
170 : 3 : }
171 : :
172 : 3 : static void test_hashmap_move(void) {
173 : : Hashmap *m, *n;
174 : : char *val1, *val2, *val3, *val4, *r;
175 : :
176 [ + - ]: 3 : log_info("/* %s */", __func__);
177 : :
178 : 3 : val1 = strdup("val1");
179 [ - + ]: 3 : assert_se(val1);
180 : 3 : val2 = strdup("val2");
181 [ - + ]: 3 : assert_se(val2);
182 : 3 : val3 = strdup("val3");
183 [ - + ]: 3 : assert_se(val3);
184 : 3 : val4 = strdup("val4");
185 [ - + ]: 3 : assert_se(val4);
186 : :
187 : 3 : m = hashmap_new(&string_hash_ops);
188 : 3 : n = hashmap_new(&string_hash_ops);
189 : :
190 : 3 : hashmap_put(n, "key 1", strdup(val1));
191 : 3 : hashmap_put(m, "key 1", val1);
192 : 3 : hashmap_put(m, "key 2", val2);
193 : 3 : hashmap_put(m, "key 3", val3);
194 : 3 : hashmap_put(m, "key 4", val4);
195 : :
196 [ - + ]: 3 : assert_se(hashmap_move(n, NULL) == 0);
197 [ - + ]: 3 : assert_se(hashmap_move(n, m) == 0);
198 : :
199 [ - + ]: 3 : assert_se(hashmap_size(m) == 1);
200 : 3 : r = hashmap_get(m, "key 1");
201 [ + - - + ]: 3 : assert_se(r && streq(r, "val1"));
202 : :
203 : 3 : r = hashmap_get(n, "key 1");
204 [ + - - + ]: 3 : assert_se(r && streq(r, "val1"));
205 : 3 : r = hashmap_get(n, "key 2");
206 [ + - - + ]: 3 : assert_se(r && streq(r, "val2"));
207 : 3 : r = hashmap_get(n, "key 3");
208 [ + - - + ]: 3 : assert_se(r && streq(r, "val3"));
209 : 3 : r = hashmap_get(n, "key 4");
210 [ + - - + ]: 3 : assert_se(r && streq(r, "val4"));
211 : :
212 : 3 : hashmap_free_free(m);
213 : 3 : hashmap_free_free(n);
214 : 3 : }
215 : :
216 : 3 : static void test_hashmap_update(void) {
217 : : Hashmap *m;
218 : : char *val1, *val2, *r;
219 : :
220 [ + - ]: 3 : log_info("/* %s */", __func__);
221 : :
222 : 3 : m = hashmap_new(&string_hash_ops);
223 : 3 : val1 = strdup("old_value");
224 [ - + ]: 3 : assert_se(val1);
225 : 3 : val2 = strdup("new_value");
226 [ - + ]: 3 : assert_se(val2);
227 : :
228 : 3 : hashmap_put(m, "key 1", val1);
229 : 3 : r = hashmap_get(m, "key 1");
230 [ - + ]: 3 : assert_se(streq(r, "old_value"));
231 : :
232 [ - + ]: 3 : assert_se(hashmap_update(m, "key 2", val2) == -ENOENT);
233 : 3 : r = hashmap_get(m, "key 1");
234 [ - + ]: 3 : assert_se(streq(r, "old_value"));
235 : :
236 [ - + ]: 3 : assert_se(hashmap_update(m, "key 1", val2) == 0);
237 : 3 : r = hashmap_get(m, "key 1");
238 [ - + ]: 3 : assert_se(streq(r, "new_value"));
239 : :
240 : 3 : free(val1);
241 : 3 : free(val2);
242 : 3 : hashmap_free(m);
243 : 3 : }
244 : :
245 : 3 : static void test_hashmap_put(void) {
246 : 3 : Hashmap *m = NULL;
247 : : int valid_hashmap_put;
248 : 3 : void *val1 = (void*) "val 1";
249 : 3 : void *val2 = (void*) "val 2";
250 : 3 : _cleanup_free_ char* key1 = NULL;
251 : :
252 [ + - ]: 3 : log_info("/* %s */", __func__);
253 : :
254 [ - + ]: 3 : assert_se(hashmap_ensure_allocated(&m, &string_hash_ops) >= 0);
255 [ - + ]: 3 : assert_se(m);
256 : :
257 : 3 : valid_hashmap_put = hashmap_put(m, "key 1", val1);
258 [ - + ]: 3 : assert_se(valid_hashmap_put == 1);
259 [ - + ]: 3 : assert_se(hashmap_put(m, "key 1", val1) == 0);
260 [ - + ]: 3 : assert_se(hashmap_put(m, "key 1", val2) == -EEXIST);
261 : 3 : key1 = strdup("key 1");
262 [ - + ]: 3 : assert_se(hashmap_put(m, key1, val1) == 0);
263 [ - + ]: 3 : assert_se(hashmap_put(m, key1, val2) == -EEXIST);
264 : :
265 : 3 : hashmap_free(m);
266 : 3 : }
267 : :
268 : 3 : static void test_hashmap_remove(void) {
269 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
270 : : char *r;
271 : :
272 [ + - ]: 3 : log_info("/* %s */", __func__);
273 : :
274 : 3 : r = hashmap_remove(NULL, "key 1");
275 [ - + ]: 3 : assert_se(r == NULL);
276 : :
277 : 3 : m = hashmap_new(&string_hash_ops);
278 [ - + ]: 3 : assert_se(m);
279 : :
280 : 3 : r = hashmap_remove(m, "no such key");
281 [ - + ]: 3 : assert_se(r == NULL);
282 : :
283 : 3 : hashmap_put(m, "key 1", (void*) "val 1");
284 : 3 : hashmap_put(m, "key 2", (void*) "val 2");
285 : :
286 : 3 : r = hashmap_remove(m, "key 1");
287 [ - + ]: 3 : assert_se(streq(r, "val 1"));
288 : :
289 : 3 : r = hashmap_get(m, "key 2");
290 [ - + ]: 3 : assert_se(streq(r, "val 2"));
291 [ - + ]: 3 : assert_se(!hashmap_get(m, "key 1"));
292 : 3 : }
293 : :
294 : 3 : static void test_hashmap_remove2(void) {
295 : 3 : _cleanup_hashmap_free_free_free_ Hashmap *m = NULL;
296 : 3 : char key1[] = "key 1";
297 : 3 : char key2[] = "key 2";
298 : 3 : char val1[] = "val 1";
299 : 3 : char val2[] = "val 2";
300 : : void *r, *r2;
301 : :
302 [ + - ]: 3 : log_info("/* %s */", __func__);
303 : :
304 : 3 : r = hashmap_remove2(NULL, "key 1", &r2);
305 [ - + ]: 3 : assert_se(r == NULL);
306 : :
307 : 3 : m = hashmap_new(&string_hash_ops);
308 [ - + ]: 3 : assert_se(m);
309 : :
310 : 3 : r = hashmap_remove2(m, "no such key", &r2);
311 [ - + ]: 3 : assert_se(r == NULL);
312 : :
313 : 3 : hashmap_put(m, strdup(key1), strdup(val1));
314 : 3 : hashmap_put(m, strdup(key2), strdup(val2));
315 : :
316 : 3 : r = hashmap_remove2(m, key1, &r2);
317 [ - + ]: 3 : assert_se(streq(r, val1));
318 [ - + ]: 3 : assert_se(streq(r2, key1));
319 : 3 : free(r);
320 : 3 : free(r2);
321 : :
322 : 3 : r = hashmap_get(m, key2);
323 [ - + ]: 3 : assert_se(streq(r, val2));
324 [ - + ]: 3 : assert_se(!hashmap_get(m, key1));
325 : 3 : }
326 : :
327 : 3 : static void test_hashmap_remove_value(void) {
328 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
329 : : char *r;
330 : :
331 : 3 : char val1[] = "val 1";
332 : 3 : char val2[] = "val 2";
333 : :
334 [ + - ]: 3 : log_info("/* %s */", __func__);
335 : :
336 : 3 : r = hashmap_remove_value(NULL, "key 1", val1);
337 [ - + ]: 3 : assert_se(r == NULL);
338 : :
339 : 3 : m = hashmap_new(&string_hash_ops);
340 [ - + ]: 3 : assert_se(m);
341 : :
342 : 3 : r = hashmap_remove_value(m, "key 1", val1);
343 [ - + ]: 3 : assert_se(r == NULL);
344 : :
345 : 3 : hashmap_put(m, "key 1", val1);
346 : 3 : hashmap_put(m, "key 2", val2);
347 : :
348 : 3 : r = hashmap_remove_value(m, "key 1", val1);
349 [ - + ]: 3 : assert_se(streq(r, "val 1"));
350 : :
351 : 3 : r = hashmap_get(m, "key 2");
352 [ - + ]: 3 : assert_se(streq(r, "val 2"));
353 [ - + ]: 3 : assert_se(!hashmap_get(m, "key 1"));
354 : :
355 : 3 : r = hashmap_remove_value(m, "key 2", val1);
356 [ - + ]: 3 : assert_se(r == NULL);
357 : :
358 : 3 : r = hashmap_get(m, "key 2");
359 [ - + ]: 3 : assert_se(streq(r, "val 2"));
360 [ - + ]: 3 : assert_se(!hashmap_get(m, "key 1"));
361 : 3 : }
362 : :
363 : 3 : static void test_hashmap_remove_and_put(void) {
364 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
365 : : int valid;
366 : : char *r;
367 : :
368 [ + - ]: 3 : log_info("/* %s */", __func__);
369 : :
370 : 3 : m = hashmap_new(&string_hash_ops);
371 [ - + ]: 3 : assert_se(m);
372 : :
373 : 3 : valid = hashmap_remove_and_put(m, "invalid key", "new key", NULL);
374 [ - + ]: 3 : assert_se(valid == -ENOENT);
375 : :
376 : 3 : valid = hashmap_put(m, "key 1", (void*) (const char *) "val 1");
377 [ - + ]: 3 : assert_se(valid == 1);
378 : :
379 : 3 : valid = hashmap_remove_and_put(NULL, "key 1", "key 2", (void*) (const char *) "val 2");
380 [ - + ]: 3 : assert_se(valid == -ENOENT);
381 : :
382 : 3 : valid = hashmap_remove_and_put(m, "key 1", "key 2", (void*) (const char *) "val 2");
383 [ - + ]: 3 : assert_se(valid == 0);
384 : :
385 : 3 : r = hashmap_get(m, "key 2");
386 [ - + ]: 3 : assert_se(streq(r, "val 2"));
387 [ - + ]: 3 : assert_se(!hashmap_get(m, "key 1"));
388 : :
389 : 3 : valid = hashmap_put(m, "key 3", (void*) (const char *) "val 3");
390 [ - + ]: 3 : assert_se(valid == 1);
391 : 3 : valid = hashmap_remove_and_put(m, "key 3", "key 2", (void*) (const char *) "val 2");
392 [ - + ]: 3 : assert_se(valid == -EEXIST);
393 : 3 : }
394 : :
395 : 3 : static void test_hashmap_remove_and_replace(void) {
396 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
397 : : int valid;
398 : 3 : void *key1 = UINT_TO_PTR(1);
399 : 3 : void *key2 = UINT_TO_PTR(2);
400 : 3 : void *key3 = UINT_TO_PTR(3);
401 : : void *r;
402 : : int i, j;
403 : :
404 [ + - ]: 3 : log_info("/* %s */", __func__);
405 : :
406 : 3 : m = hashmap_new(&trivial_hash_ops);
407 [ - + ]: 3 : assert_se(m);
408 : :
409 : 3 : valid = hashmap_remove_and_replace(m, key1, key2, NULL);
410 [ - + ]: 3 : assert_se(valid == -ENOENT);
411 : :
412 : 3 : valid = hashmap_put(m, key1, key1);
413 [ - + ]: 3 : assert_se(valid == 1);
414 : :
415 : 3 : valid = hashmap_remove_and_replace(NULL, key1, key2, key2);
416 [ - + ]: 3 : assert_se(valid == -ENOENT);
417 : :
418 : 3 : valid = hashmap_remove_and_replace(m, key1, key2, key2);
419 [ - + ]: 3 : assert_se(valid == 0);
420 : :
421 : 3 : r = hashmap_get(m, key2);
422 [ - + ]: 3 : assert_se(r == key2);
423 [ - + ]: 3 : assert_se(!hashmap_get(m, key1));
424 : :
425 : 3 : valid = hashmap_put(m, key3, key3);
426 [ - + ]: 3 : assert_se(valid == 1);
427 : 3 : valid = hashmap_remove_and_replace(m, key3, key2, key2);
428 [ - + ]: 3 : assert_se(valid == 0);
429 : 3 : r = hashmap_get(m, key2);
430 [ - + ]: 3 : assert_se(r == key2);
431 [ - + ]: 3 : assert_se(!hashmap_get(m, key3));
432 : :
433 : : /* Repeat this test several times to increase the chance of hitting
434 : : * the less likely case in hashmap_remove_and_replace where it
435 : : * compensates for the backward shift. */
436 [ + + ]: 63 : for (i = 0; i < 20; i++) {
437 : 60 : hashmap_clear(m);
438 : :
439 [ + + ]: 420 : for (j = 1; j < 7; j++)
440 : 360 : hashmap_put(m, UINT_TO_PTR(10*i + j), UINT_TO_PTR(10*i + j));
441 : 120 : valid = hashmap_remove_and_replace(m, UINT_TO_PTR(10*i + 1),
442 : 60 : UINT_TO_PTR(10*i + 2),
443 : 60 : UINT_TO_PTR(10*i + 2));
444 [ - + ]: 60 : assert_se(valid == 0);
445 [ - + ]: 60 : assert_se(!hashmap_get(m, UINT_TO_PTR(10*i + 1)));
446 [ + + ]: 360 : for (j = 2; j < 7; j++) {
447 : 300 : r = hashmap_get(m, UINT_TO_PTR(10*i + j));
448 [ - + ]: 300 : assert_se(r == UINT_TO_PTR(10*i + j));
449 : : }
450 : : }
451 : 3 : }
452 : :
453 : 3 : static void test_hashmap_ensure_allocated(void) {
454 : : Hashmap *m;
455 : : int valid_hashmap;
456 : :
457 [ + - ]: 3 : log_info("/* %s */", __func__);
458 : :
459 : 3 : m = hashmap_new(&string_hash_ops);
460 : :
461 : 3 : valid_hashmap = hashmap_ensure_allocated(&m, &string_hash_ops);
462 [ - + ]: 3 : assert_se(valid_hashmap == 0);
463 : :
464 [ - + ]: 3 : assert_se(m);
465 : 3 : hashmap_free(m);
466 : 3 : }
467 : :
468 : 3 : static void test_hashmap_foreach_key(void) {
469 : : Hashmap *m;
470 : : Iterator i;
471 : 3 : bool key_found[] = { false, false, false, false };
472 : : const char *s;
473 : : const char *key;
474 : : static const char key_table[] =
475 : : "key 1\0"
476 : : "key 2\0"
477 : : "key 3\0"
478 : : "key 4\0";
479 : :
480 [ + - ]: 3 : log_info("/* %s */", __func__);
481 : :
482 : 3 : m = hashmap_new(&string_hash_ops);
483 : :
484 [ + - + + ]: 15 : NULSTR_FOREACH(key, key_table)
485 : 12 : hashmap_put(m, key, (void*) (const char*) "my dummy val");
486 : :
487 [ + + ]: 15 : HASHMAP_FOREACH_KEY(s, key, m, i) {
488 [ - + ]: 12 : assert(s);
489 [ + + + + ]: 12 : if (!key_found[0] && streq(key, "key 1"))
490 : 3 : key_found[0] = true;
491 [ + + + + ]: 9 : else if (!key_found[1] && streq(key, "key 2"))
492 : 3 : key_found[1] = true;
493 [ + + + + ]: 6 : else if (!key_found[2] && streq(key, "key 3"))
494 : 3 : key_found[2] = true;
495 [ + - - + ]: 3 : else if (!key_found[3] && streq(key, "fail"))
496 : 0 : key_found[3] = true;
497 : : }
498 : :
499 [ - + ]: 3 : assert_se(m);
500 [ + - - + : 3 : assert_se(key_found[0] && key_found[1] && key_found[2] && !key_found[3]);
+ - - + +
- - + ]
501 : :
502 : 3 : hashmap_free(m);
503 : 3 : }
504 : :
505 : 3 : static void test_hashmap_foreach(void) {
506 : : Hashmap *m;
507 : : Iterator i;
508 : 3 : bool value_found[] = { false, false, false, false };
509 : : char *val1, *val2, *val3, *val4, *s;
510 : : unsigned count;
511 : :
512 [ + - ]: 3 : log_info("/* %s */", __func__);
513 : :
514 : 3 : val1 = strdup("my val1");
515 [ - + ]: 3 : assert_se(val1);
516 : 3 : val2 = strdup("my val2");
517 [ - + ]: 3 : assert_se(val2);
518 : 3 : val3 = strdup("my val3");
519 [ - + ]: 3 : assert_se(val3);
520 : 3 : val4 = strdup("my val4");
521 [ - + ]: 3 : assert_se(val4);
522 : :
523 : 3 : m = NULL;
524 : :
525 : 3 : count = 0;
526 [ - + ]: 3 : HASHMAP_FOREACH(s, m, i)
527 : 0 : count++;
528 [ - + ]: 3 : assert_se(count == 0);
529 : :
530 : 3 : m = hashmap_new(&string_hash_ops);
531 : :
532 : 3 : count = 0;
533 [ - + ]: 3 : HASHMAP_FOREACH(s, m, i)
534 : 0 : count++;
535 [ - + ]: 3 : assert_se(count == 0);
536 : :
537 : 3 : hashmap_put(m, "Key 1", val1);
538 : 3 : hashmap_put(m, "Key 2", val2);
539 : 3 : hashmap_put(m, "Key 3", val3);
540 : 3 : hashmap_put(m, "Key 4", val4);
541 : :
542 [ + + ]: 15 : HASHMAP_FOREACH(s, m, i) {
543 [ + + + + ]: 12 : if (!value_found[0] && streq(s, val1))
544 : 3 : value_found[0] = true;
545 [ + + + + ]: 9 : else if (!value_found[1] && streq(s, val2))
546 : 3 : value_found[1] = true;
547 [ + + + - ]: 6 : else if (!value_found[2] && streq(s, val3))
548 : 3 : value_found[2] = true;
549 [ + - + - ]: 3 : else if (!value_found[3] && streq(s, val4))
550 : 3 : value_found[3] = true;
551 : : }
552 : :
553 [ - + ]: 3 : assert_se(m);
554 [ + - - + : 3 : assert_se(value_found[0] && value_found[1] && value_found[2] && value_found[3]);
+ - - + +
- - + ]
555 : :
556 : 3 : hashmap_free_free(m);
557 : 3 : }
558 : :
559 : 3 : static void test_hashmap_merge(void) {
560 : : Hashmap *m;
561 : : Hashmap *n;
562 : : char *val1, *val2, *val3, *val4, *r;
563 : :
564 [ + - ]: 3 : log_info("/* %s */", __func__);
565 : :
566 : 3 : val1 = strdup("my val1");
567 [ - + ]: 3 : assert_se(val1);
568 : 3 : val2 = strdup("my val2");
569 [ - + ]: 3 : assert_se(val2);
570 : 3 : val3 = strdup("my val3");
571 [ - + ]: 3 : assert_se(val3);
572 : 3 : val4 = strdup("my val4");
573 [ - + ]: 3 : assert_se(val4);
574 : :
575 : 3 : n = hashmap_new(&string_hash_ops);
576 : 3 : m = hashmap_new(&string_hash_ops);
577 : :
578 : 3 : hashmap_put(m, "Key 1", val1);
579 : 3 : hashmap_put(m, "Key 2", val2);
580 : 3 : hashmap_put(n, "Key 3", val3);
581 : 3 : hashmap_put(n, "Key 4", val4);
582 : :
583 [ - + ]: 3 : assert_se(hashmap_merge(m, n) == 0);
584 : 3 : r = hashmap_get(m, "Key 3");
585 [ + - - + ]: 3 : assert_se(r && streq(r, "my val3"));
586 : 3 : r = hashmap_get(m, "Key 4");
587 [ + - - + ]: 3 : assert_se(r && streq(r, "my val4"));
588 : :
589 [ - + ]: 3 : assert_se(n);
590 [ - + ]: 3 : assert_se(m);
591 : 3 : hashmap_free(n);
592 : 3 : hashmap_free_free(m);
593 : 3 : }
594 : :
595 : 3 : static void test_hashmap_contains(void) {
596 : : Hashmap *m;
597 : : char *val1;
598 : :
599 [ + - ]: 3 : log_info("/* %s */", __func__);
600 : :
601 : 3 : val1 = strdup("my val");
602 [ - + ]: 3 : assert_se(val1);
603 : :
604 : 3 : m = hashmap_new(&string_hash_ops);
605 : :
606 [ - + ]: 3 : assert_se(!hashmap_contains(m, "Key 1"));
607 : 3 : hashmap_put(m, "Key 1", val1);
608 [ - + ]: 3 : assert_se(hashmap_contains(m, "Key 1"));
609 [ - + ]: 3 : assert_se(!hashmap_contains(m, "Key 2"));
610 : :
611 [ - + ]: 3 : assert_se(!hashmap_contains(NULL, "Key 1"));
612 : :
613 [ - + ]: 3 : assert_se(m);
614 : 3 : hashmap_free_free(m);
615 : 3 : }
616 : :
617 : 3 : static void test_hashmap_isempty(void) {
618 : : Hashmap *m;
619 : : char *val1;
620 : :
621 [ + - ]: 3 : log_info("/* %s */", __func__);
622 : :
623 : 3 : val1 = strdup("my val");
624 [ - + ]: 3 : assert_se(val1);
625 : :
626 : 3 : m = hashmap_new(&string_hash_ops);
627 : :
628 [ - + ]: 3 : assert_se(hashmap_isempty(m));
629 : 3 : hashmap_put(m, "Key 1", val1);
630 [ - + ]: 3 : assert_se(!hashmap_isempty(m));
631 : :
632 [ - + ]: 3 : assert_se(m);
633 : 3 : hashmap_free_free(m);
634 : 3 : }
635 : :
636 : 3 : static void test_hashmap_size(void) {
637 : : Hashmap *m;
638 : : char *val1, *val2, *val3, *val4;
639 : :
640 [ + - ]: 3 : log_info("/* %s */", __func__);
641 : :
642 : 3 : val1 = strdup("my val");
643 [ - + ]: 3 : assert_se(val1);
644 : 3 : val2 = strdup("my val");
645 [ - + ]: 3 : assert_se(val2);
646 : 3 : val3 = strdup("my val");
647 [ - + ]: 3 : assert_se(val3);
648 : 3 : val4 = strdup("my val");
649 [ - + ]: 3 : assert_se(val4);
650 : :
651 [ - + ]: 3 : assert_se(hashmap_size(NULL) == 0);
652 [ - + ]: 3 : assert_se(hashmap_buckets(NULL) == 0);
653 : :
654 : 3 : m = hashmap_new(&string_hash_ops);
655 : :
656 : 3 : hashmap_put(m, "Key 1", val1);
657 : 3 : hashmap_put(m, "Key 2", val2);
658 : 3 : hashmap_put(m, "Key 3", val3);
659 : 3 : hashmap_put(m, "Key 4", val4);
660 : :
661 [ - + ]: 3 : assert_se(m);
662 [ - + ]: 3 : assert_se(hashmap_size(m) == 4);
663 [ - + ]: 3 : assert_se(hashmap_buckets(m) >= 4);
664 : 3 : hashmap_free_free(m);
665 : 3 : }
666 : :
667 : 3 : static void test_hashmap_get(void) {
668 : : Hashmap *m;
669 : : char *r;
670 : : char *val;
671 : :
672 [ + - ]: 3 : log_info("/* %s */", __func__);
673 : :
674 : 3 : val = strdup("my val");
675 [ - + ]: 3 : assert_se(val);
676 : :
677 : 3 : r = hashmap_get(NULL, "Key 1");
678 [ - + ]: 3 : assert_se(r == NULL);
679 : :
680 : 3 : m = hashmap_new(&string_hash_ops);
681 : :
682 : 3 : hashmap_put(m, "Key 1", val);
683 : :
684 : 3 : r = hashmap_get(m, "Key 1");
685 [ - + ]: 3 : assert_se(streq(r, val));
686 : :
687 : 3 : r = hashmap_get(m, "no such key");
688 [ - + ]: 3 : assert_se(r == NULL);
689 : :
690 [ - + ]: 3 : assert_se(m);
691 : 3 : hashmap_free_free(m);
692 : 3 : }
693 : :
694 : 3 : static void test_hashmap_get2(void) {
695 : : Hashmap *m;
696 : : char *r;
697 : : char *val;
698 : 3 : char key_orig[] = "Key 1";
699 : : void *key_copy;
700 : :
701 [ + - ]: 3 : log_info("/* %s */", __func__);
702 : :
703 : 3 : val = strdup("my val");
704 [ - + ]: 3 : assert_se(val);
705 : :
706 : 3 : key_copy = strdup(key_orig);
707 [ - + ]: 3 : assert_se(key_copy);
708 : :
709 : 3 : r = hashmap_get2(NULL, key_orig, &key_copy);
710 [ - + ]: 3 : assert_se(r == NULL);
711 : :
712 : 3 : m = hashmap_new(&string_hash_ops);
713 : :
714 : 3 : hashmap_put(m, key_copy, val);
715 : 3 : key_copy = NULL;
716 : :
717 : 3 : r = hashmap_get2(m, key_orig, &key_copy);
718 [ - + ]: 3 : assert_se(streq(r, val));
719 [ - + ]: 3 : assert_se(key_orig != key_copy);
720 [ - + ]: 3 : assert_se(streq(key_orig, key_copy));
721 : :
722 : 3 : r = hashmap_get2(m, "no such key", NULL);
723 [ - + ]: 3 : assert_se(r == NULL);
724 : :
725 [ - + ]: 3 : assert_se(m);
726 : 3 : hashmap_free_free_free(m);
727 : 3 : }
728 : :
729 : 1426062 : static void crippled_hashmap_func(const void *p, struct siphash *state) {
730 : 1426062 : return trivial_hash_func(INT_TO_PTR(PTR_TO_INT(p) & 0xff), state);
731 : : }
732 : :
733 : : static const struct hash_ops crippled_hashmap_ops = {
734 : : .hash = crippled_hashmap_func,
735 : : .compare = trivial_compare_func,
736 : : };
737 : :
738 : 3 : static void test_hashmap_many(void) {
739 : : Hashmap *h;
740 : : unsigned i, j;
741 : : void *v, *k;
742 : 3 : bool slow = slow_tests_enabled();
743 : : const struct {
744 : : const char *title;
745 : : const struct hash_ops *ops;
746 : : unsigned n_entries;
747 : 9 : } tests[] = {
748 [ + - ]: 3 : { "trivial_hashmap_ops", NULL, slow ? 1 << 20 : 240 },
749 [ + - ]: 3 : { "crippled_hashmap_ops", &crippled_hashmap_ops, slow ? 1 << 14 : 140 },
750 : : };
751 : :
752 [ + - + - ]: 3 : log_info("/* %s (%s) */", __func__, slow ? "slow" : "fast");
753 : :
754 [ + + ]: 9 : for (j = 0; j < ELEMENTSOF(tests); j++) {
755 : 6 : usec_t ts = now(CLOCK_MONOTONIC), n;
756 : : char b[FORMAT_TIMESPAN_MAX];
757 : :
758 [ - + ]: 6 : assert_se(h = hashmap_new(tests[j].ops));
759 : :
760 [ + + ]: 3194886 : for (i = 1; i < tests[j].n_entries*3; i+=3) {
761 [ - + ]: 3194880 : assert_se(hashmap_put(h, UINT_TO_PTR(i), UINT_TO_PTR(i)) >= 0);
762 [ - + ]: 3194880 : assert_se(PTR_TO_UINT(hashmap_get(h, UINT_TO_PTR(i))) == i);
763 : : }
764 : :
765 [ + + ]: 9584640 : for (i = 1; i < tests[j].n_entries*3; i++)
766 [ - + ]: 9584634 : assert_se(hashmap_contains(h, UINT_TO_PTR(i)) == (i % 3 == 1));
767 : :
768 [ + - ]: 6 : log_info("%s %u <= %u * 0.8 = %g",
769 : : tests[j].title, hashmap_size(h), hashmap_buckets(h), hashmap_buckets(h) * 0.8);
770 : :
771 [ - + ]: 6 : assert_se(hashmap_size(h) <= hashmap_buckets(h) * 0.8);
772 [ - + ]: 6 : assert_se(hashmap_size(h) == tests[j].n_entries);
773 : :
774 [ + + ]: 3194886 : while (!hashmap_isempty(h)) {
775 : 3194880 : k = hashmap_first_key(h);
776 : 3194880 : v = hashmap_remove(h, k);
777 [ - + ]: 3194880 : assert_se(v == k);
778 : : }
779 : :
780 : 6 : hashmap_free(h);
781 : :
782 : 6 : n = now(CLOCK_MONOTONIC);
783 [ + - ]: 6 : log_info("test took %s", format_timespan(b, sizeof b, n - ts, 0));
784 : : }
785 : 3 : }
786 : :
787 : : extern unsigned custom_counter;
788 : : extern const struct hash_ops boring_hash_ops, custom_hash_ops;
789 : :
790 : 3 : static void test_hashmap_free(void) {
791 : : Hashmap *h;
792 : 3 : bool slow = slow_tests_enabled();
793 : : usec_t ts, n;
794 : : char b[FORMAT_TIMESPAN_MAX];
795 [ + - ]: 3 : unsigned n_entries = slow ? 1 << 20 : 240;
796 : :
797 : : const struct {
798 : : const char *title;
799 : : const struct hash_ops *ops;
800 : : unsigned expect_counter;
801 : 6 : } tests[] = {
802 : 3 : { "string_hash_ops", &boring_hash_ops, 2 * n_entries},
803 : : { "custom_free_hash_ops", &custom_hash_ops, 0 },
804 : : };
805 : :
806 [ + - + - ]: 3 : log_info("/* %s (%s, %u entries) */", __func__, slow ? "slow" : "fast", n_entries);
807 : :
808 [ + + ]: 9 : for (unsigned j = 0; j < ELEMENTSOF(tests); j++) {
809 : 6 : ts = now(CLOCK_MONOTONIC);
810 [ - + ]: 6 : assert_se(h = hashmap_new(tests[j].ops));
811 : :
812 : 6 : custom_counter = 0;
813 [ + + ]: 6291462 : for (unsigned i = 0; i < n_entries; i++) {
814 : : char s[DECIMAL_STR_MAX(unsigned)];
815 : : char *k, *v;
816 : :
817 [ - + ]: 6291456 : xsprintf(s, "%u", i);
818 [ - + ]: 6291456 : assert_se(k = strdup(s));
819 [ - + ]: 6291456 : assert_se(v = strdup(s));
820 : 6291456 : custom_counter += 2;
821 : :
822 [ - + ]: 6291456 : assert_se(hashmap_put(h, k, v) >= 0);
823 : : }
824 : :
825 : 6 : hashmap_free(h);
826 : :
827 : 6 : n = now(CLOCK_MONOTONIC);
828 [ + - ]: 6 : log_info("%s test took %s", tests[j].title, format_timespan(b, sizeof b, n - ts, 0));
829 : :
830 [ - + ]: 6 : assert_se(custom_counter == tests[j].expect_counter);
831 : : }
832 : 3 : }
833 : :
834 : : typedef struct Item {
835 : : int seen;
836 : : } Item;
837 : 9 : static void item_seen(Item *item) {
838 : 9 : item->seen++;
839 : 9 : }
840 : :
841 : 3 : static void test_hashmap_free_with_destructor(void) {
842 : : Hashmap *m;
843 : 3 : struct Item items[4] = {};
844 : : unsigned i;
845 : :
846 [ + - ]: 3 : log_info("/* %s */", __func__);
847 : :
848 [ - + ]: 3 : assert_se(m = hashmap_new(NULL));
849 [ + + ]: 12 : for (i = 0; i < ELEMENTSOF(items) - 1; i++)
850 [ - + ]: 9 : assert_se(hashmap_put(m, INT_TO_PTR(i), items + i) == 1);
851 : :
852 [ + + ]: 12 : m = hashmap_free_with_destructor(m, item_seen);
853 [ - + ]: 3 : assert_se(items[0].seen == 1);
854 [ - + ]: 3 : assert_se(items[1].seen == 1);
855 [ - + ]: 3 : assert_se(items[2].seen == 1);
856 [ - + ]: 3 : assert_se(items[3].seen == 0);
857 : 3 : }
858 : :
859 : 3 : static void test_hashmap_first(void) {
860 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
861 : :
862 [ + - ]: 3 : log_info("/* %s */", __func__);
863 : :
864 : 3 : m = hashmap_new(&string_hash_ops);
865 [ - + ]: 3 : assert_se(m);
866 : :
867 [ - + ]: 3 : assert_se(!hashmap_first(m));
868 [ - + ]: 3 : assert_se(hashmap_put(m, "key 1", (void*) "val 1") == 1);
869 [ - + ]: 3 : assert_se(streq(hashmap_first(m), "val 1"));
870 [ - + ]: 3 : assert_se(hashmap_put(m, "key 2", (void*) "val 2") == 1);
871 : : #ifdef ORDERED
872 : : assert_se(streq(hashmap_first(m), "val 1"));
873 : : assert_se(hashmap_remove(m, "key 1"));
874 : : assert_se(streq(hashmap_first(m), "val 2"));
875 : : #endif
876 : 3 : }
877 : :
878 : 3 : static void test_hashmap_first_key(void) {
879 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
880 : :
881 [ + - ]: 3 : log_info("/* %s */", __func__);
882 : :
883 : 3 : m = hashmap_new(&string_hash_ops);
884 [ - + ]: 3 : assert_se(m);
885 : :
886 [ - + ]: 3 : assert_se(!hashmap_first_key(m));
887 [ - + ]: 3 : assert_se(hashmap_put(m, "key 1", NULL) == 1);
888 [ - + ]: 3 : assert_se(streq(hashmap_first_key(m), "key 1"));
889 [ - + ]: 3 : assert_se(hashmap_put(m, "key 2", NULL) == 1);
890 : : #ifdef ORDERED
891 : : assert_se(streq(hashmap_first_key(m), "key 1"));
892 : : assert_se(hashmap_remove(m, "key 1") == NULL);
893 : : assert_se(streq(hashmap_first_key(m), "key 2"));
894 : : #endif
895 : 3 : }
896 : :
897 : 3 : static void test_hashmap_steal_first_key(void) {
898 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
899 : :
900 [ + - ]: 3 : log_info("/* %s */", __func__);
901 : :
902 : 3 : m = hashmap_new(&string_hash_ops);
903 [ - + ]: 3 : assert_se(m);
904 : :
905 [ - + ]: 3 : assert_se(!hashmap_steal_first_key(m));
906 [ - + ]: 3 : assert_se(hashmap_put(m, "key 1", NULL) == 1);
907 [ - + ]: 3 : assert_se(streq(hashmap_steal_first_key(m), "key 1"));
908 : :
909 [ - + ]: 3 : assert_se(hashmap_isempty(m));
910 : 3 : }
911 : :
912 : 3 : static void test_hashmap_steal_first(void) {
913 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
914 : 3 : int seen[3] = {};
915 : : char *val;
916 : :
917 [ + - ]: 3 : log_info("/* %s */", __func__);
918 : :
919 : 3 : m = hashmap_new(&string_hash_ops);
920 [ - + ]: 3 : assert_se(m);
921 : :
922 [ - + ]: 3 : assert_se(hashmap_put(m, "key 1", (void*) "1") == 1);
923 [ - + ]: 3 : assert_se(hashmap_put(m, "key 2", (void*) "22") == 1);
924 [ - + ]: 3 : assert_se(hashmap_put(m, "key 3", (void*) "333") == 1);
925 : :
926 [ + + ]: 12 : while ((val = hashmap_steal_first(m)))
927 : 9 : seen[strlen(val) - 1]++;
928 : :
929 [ + - - + : 3 : assert_se(seen[0] == 1 && seen[1] == 1 && seen[2] == 1);
+ - - + ]
930 : :
931 [ - + ]: 3 : assert_se(hashmap_isempty(m));
932 : 3 : }
933 : :
934 : 3 : static void test_hashmap_clear_free_free(void) {
935 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
936 : :
937 [ + - ]: 3 : log_info("/* %s */", __func__);
938 : :
939 : 3 : m = hashmap_new(&string_hash_ops);
940 [ - + ]: 3 : assert_se(m);
941 : :
942 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 1"), NULL) == 1);
943 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 2"), NULL) == 1);
944 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 3"), NULL) == 1);
945 : :
946 : 3 : hashmap_clear_free_free(m);
947 [ - + ]: 3 : assert_se(hashmap_isempty(m));
948 : :
949 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 1"), strdup("value 1")) == 1);
950 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 2"), strdup("value 2")) == 1);
951 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 3"), strdup("value 3")) == 1);
952 : :
953 : 3 : hashmap_clear_free_free(m);
954 [ - + ]: 3 : assert_se(hashmap_isempty(m));
955 : 3 : }
956 : :
957 : 9 : DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(test_hash_ops_key, char, string_hash_func, string_compare_func, free);
958 : 18 : DEFINE_PRIVATE_HASH_OPS_FULL(test_hash_ops_full, char, string_hash_func, string_compare_func, free, char, free);
959 : :
960 : 3 : static void test_hashmap_clear_free_with_destructor(void) {
961 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
962 : :
963 [ + - ]: 3 : log_info("/* %s */", __func__);
964 : :
965 : 3 : m = hashmap_new(&test_hash_ops_key);
966 [ - + ]: 3 : assert_se(m);
967 : :
968 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 1"), NULL) == 1);
969 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 2"), NULL) == 1);
970 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 3"), NULL) == 1);
971 : :
972 : 3 : hashmap_clear_free(m);
973 [ - + ]: 3 : assert_se(hashmap_isempty(m));
974 : 3 : m = hashmap_free(m);
975 : :
976 : 3 : m = hashmap_new(&test_hash_ops_full);
977 [ - + ]: 3 : assert_se(m);
978 : :
979 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 1"), strdup("value 1")) == 1);
980 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 2"), strdup("value 2")) == 1);
981 [ - + ]: 3 : assert_se(hashmap_put(m, strdup("key 3"), strdup("value 3")) == 1);
982 : :
983 : 3 : hashmap_clear_free(m);
984 [ - + ]: 3 : assert_se(hashmap_isempty(m));
985 : 3 : }
986 : :
987 : 3 : static void test_hashmap_reserve(void) {
988 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
989 : :
990 [ + - ]: 3 : log_info("/* %s */", __func__);
991 : :
992 : 3 : m = hashmap_new(&string_hash_ops);
993 : :
994 [ - + ]: 3 : assert_se(hashmap_reserve(m, 1) == 0);
995 [ - + ]: 3 : assert_se(hashmap_buckets(m) < 1000);
996 [ - + ]: 3 : assert_se(hashmap_reserve(m, 1000) == 0);
997 [ - + ]: 3 : assert_se(hashmap_buckets(m) >= 1000);
998 [ - + ]: 3 : assert_se(hashmap_isempty(m));
999 : :
1000 [ - + ]: 3 : assert_se(hashmap_put(m, "key 1", (void*) "val 1") == 1);
1001 : :
1002 [ - + ]: 3 : assert_se(hashmap_reserve(m, UINT_MAX) == -ENOMEM);
1003 [ - + ]: 3 : assert_se(hashmap_reserve(m, UINT_MAX - 1) == -ENOMEM);
1004 : 3 : }
1005 : :
1006 : 3 : static void test_path_hashmap(void) {
1007 : 3 : _cleanup_hashmap_free_ Hashmap *h = NULL;
1008 : :
1009 [ + - ]: 3 : log_info("/* %s */", __func__);
1010 : :
1011 [ - + ]: 3 : assert_se(h = hashmap_new(&path_hash_ops));
1012 : :
1013 [ - + ]: 3 : assert_se(hashmap_put(h, "foo", INT_TO_PTR(1)) >= 0);
1014 [ - + ]: 3 : assert_se(hashmap_put(h, "/foo", INT_TO_PTR(2)) >= 0);
1015 [ - + ]: 3 : assert_se(hashmap_put(h, "//foo", INT_TO_PTR(3)) == -EEXIST);
1016 [ - + ]: 3 : assert_se(hashmap_put(h, "//foox/", INT_TO_PTR(4)) >= 0);
1017 [ - + ]: 3 : assert_se(hashmap_put(h, "/foox////", INT_TO_PTR(5)) == -EEXIST);
1018 [ - + ]: 3 : assert_se(hashmap_put(h, "foo//////bar/quux//", INT_TO_PTR(6)) >= 0);
1019 [ - + ]: 3 : assert_se(hashmap_put(h, "foo/bar//quux/", INT_TO_PTR(8)) == -EEXIST);
1020 : :
1021 [ - + ]: 3 : assert_se(hashmap_get(h, "foo") == INT_TO_PTR(1));
1022 [ - + ]: 3 : assert_se(hashmap_get(h, "foo/") == INT_TO_PTR(1));
1023 [ - + ]: 3 : assert_se(hashmap_get(h, "foo////") == INT_TO_PTR(1));
1024 [ - + ]: 3 : assert_se(hashmap_get(h, "/foo") == INT_TO_PTR(2));
1025 [ - + ]: 3 : assert_se(hashmap_get(h, "//foo") == INT_TO_PTR(2));
1026 [ - + ]: 3 : assert_se(hashmap_get(h, "/////foo////") == INT_TO_PTR(2));
1027 [ - + ]: 3 : assert_se(hashmap_get(h, "/////foox////") == INT_TO_PTR(4));
1028 [ - + ]: 3 : assert_se(hashmap_get(h, "/foox/") == INT_TO_PTR(4));
1029 [ - + ]: 3 : assert_se(hashmap_get(h, "/foox") == INT_TO_PTR(4));
1030 [ - + ]: 3 : assert_se(!hashmap_get(h, "foox"));
1031 [ - + ]: 3 : assert_se(hashmap_get(h, "foo/bar/quux") == INT_TO_PTR(6));
1032 [ - + ]: 3 : assert_se(hashmap_get(h, "foo////bar////quux/////") == INT_TO_PTR(6));
1033 [ - + ]: 3 : assert_se(!hashmap_get(h, "/foo////bar////quux/////"));
1034 : 3 : }
1035 : :
1036 : 3 : static void test_string_strv_hashmap(void) {
1037 : 3 : _cleanup_hashmap_free_ Hashmap *m = NULL;
1038 : : char **s;
1039 : :
1040 [ + - ]: 3 : log_info("/* %s */", __func__);
1041 : :
1042 [ - + ]: 3 : assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 1);
1043 [ - + ]: 3 : assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 0);
1044 [ - + ]: 3 : assert_se(string_strv_hashmap_put(&m, "foo", "BAR") == 1);
1045 [ - + ]: 3 : assert_se(string_strv_hashmap_put(&m, "foo", "BAR") == 0);
1046 [ - + ]: 3 : assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 0);
1047 [ - + ]: 3 : assert_se(hashmap_contains(m, "foo"));
1048 : :
1049 : 3 : s = hashmap_get(m, "foo");
1050 [ - + ]: 3 : assert_se(strv_equal(s, STRV_MAKE("bar", "BAR")));
1051 : :
1052 [ - + ]: 3 : assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 1);
1053 [ - + ]: 3 : assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 0);
1054 [ - + ]: 3 : assert_se(string_strv_hashmap_put(&m, "xxx", "BAR") == 1);
1055 [ - + ]: 3 : assert_se(string_strv_hashmap_put(&m, "xxx", "BAR") == 0);
1056 [ - + ]: 3 : assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 0);
1057 [ - + ]: 3 : assert_se(hashmap_contains(m, "xxx"));
1058 : :
1059 : 3 : s = hashmap_get(m, "xxx");
1060 [ - + ]: 3 : assert_se(strv_equal(s, STRV_MAKE("bar", "BAR")));
1061 : 3 : }
1062 : :
1063 : 3 : void test_hashmap_funcs(void) {
1064 [ + - ]: 3 : log_info("/************ %s ************/", __func__);
1065 : :
1066 : 3 : test_hashmap_copy();
1067 : 3 : test_hashmap_get_strv();
1068 : 3 : test_hashmap_move_one();
1069 : 3 : test_hashmap_move();
1070 : 3 : test_hashmap_replace();
1071 : 3 : test_hashmap_update();
1072 : 3 : test_hashmap_put();
1073 : 3 : test_hashmap_remove();
1074 : 3 : test_hashmap_remove2();
1075 : 3 : test_hashmap_remove_value();
1076 : 3 : test_hashmap_remove_and_put();
1077 : 3 : test_hashmap_remove_and_replace();
1078 : 3 : test_hashmap_ensure_allocated();
1079 : 3 : test_hashmap_foreach();
1080 : 3 : test_hashmap_foreach_key();
1081 : 3 : test_hashmap_contains();
1082 : 3 : test_hashmap_merge();
1083 : 3 : test_hashmap_isempty();
1084 : 3 : test_hashmap_get();
1085 : 3 : test_hashmap_get2();
1086 : 3 : test_hashmap_size();
1087 : 3 : test_hashmap_many();
1088 : 3 : test_hashmap_free();
1089 : 3 : test_hashmap_free_with_destructor();
1090 : 3 : test_hashmap_first();
1091 : 3 : test_hashmap_first_key();
1092 : 3 : test_hashmap_steal_first_key();
1093 : 3 : test_hashmap_steal_first();
1094 : 3 : test_hashmap_clear_free_free();
1095 : 3 : test_hashmap_clear_free_with_destructor();
1096 : 3 : test_hashmap_reserve();
1097 : 3 : test_path_hashmap();
1098 : 3 : test_string_strv_hashmap();
1099 : 3 : }
|