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