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