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