]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-hashmap-plain.c
Merge pull request #1690 from evverx/run-runtime-directory
[thirdparty/systemd.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 r = hashmap_remove_value(NULL, "key 1", (void*) "val 1");
327 assert_se(r == NULL);
328
329 m = hashmap_new(&string_hash_ops);
330 assert_se(m);
331
332 r = hashmap_remove_value(m, "key 1", (void*) "val 1");
333 assert_se(r == NULL);
334
335 hashmap_put(m, "key 1", (void*) "val 1");
336 hashmap_put(m, "key 2", (void*) "val 2");
337
338 r = hashmap_remove_value(m, "key 1", (void*) "val 1");
339 assert_se(streq(r, "val 1"));
340
341 r = hashmap_get(m, "key 2");
342 assert_se(streq(r, "val 2"));
343 assert_se(!hashmap_get(m, "key 1"));
344
345 r = hashmap_remove_value(m, "key 2", (void*) "val 1");
346 assert_se(r == NULL);
347
348 r = hashmap_get(m, "key 2");
349 assert_se(streq(r, "val 2"));
350 assert_se(!hashmap_get(m, "key 1"));
351 }
352
353 static void test_hashmap_remove_and_put(void) {
354 _cleanup_hashmap_free_ Hashmap *m = NULL;
355 int valid;
356 char *r;
357
358 m = hashmap_new(&string_hash_ops);
359 assert_se(m);
360
361 valid = hashmap_remove_and_put(m, "invalid key", "new key", NULL);
362 assert_se(valid == -ENOENT);
363
364 valid = hashmap_put(m, "key 1", (void*) (const char *) "val 1");
365 assert_se(valid == 1);
366
367 valid = hashmap_remove_and_put(NULL, "key 1", "key 2", (void*) (const char *) "val 2");
368 assert_se(valid == -ENOENT);
369
370 valid = hashmap_remove_and_put(m, "key 1", "key 2", (void*) (const char *) "val 2");
371 assert_se(valid == 0);
372
373 r = hashmap_get(m, "key 2");
374 assert_se(streq(r, "val 2"));
375 assert_se(!hashmap_get(m, "key 1"));
376
377 valid = hashmap_put(m, "key 3", (void*) (const char *) "val 3");
378 assert_se(valid == 1);
379 valid = hashmap_remove_and_put(m, "key 3", "key 2", (void*) (const char *) "val 2");
380 assert_se(valid == -EEXIST);
381 }
382
383 static void test_hashmap_remove_and_replace(void) {
384 _cleanup_hashmap_free_ Hashmap *m = NULL;
385 int valid;
386 void *key1 = UINT_TO_PTR(1);
387 void *key2 = UINT_TO_PTR(2);
388 void *key3 = UINT_TO_PTR(3);
389 void *r;
390 int i, j;
391
392 m = hashmap_new(&trivial_hash_ops);
393 assert_se(m);
394
395 valid = hashmap_remove_and_replace(m, key1, key2, NULL);
396 assert_se(valid == -ENOENT);
397
398 valid = hashmap_put(m, key1, key1);
399 assert_se(valid == 1);
400
401 valid = hashmap_remove_and_replace(NULL, key1, key2, key2);
402 assert_se(valid == -ENOENT);
403
404 valid = hashmap_remove_and_replace(m, key1, key2, key2);
405 assert_se(valid == 0);
406
407 r = hashmap_get(m, key2);
408 assert_se(r == key2);
409 assert_se(!hashmap_get(m, key1));
410
411 valid = hashmap_put(m, key3, key3);
412 assert_se(valid == 1);
413 valid = hashmap_remove_and_replace(m, key3, key2, key2);
414 assert_se(valid == 0);
415 r = hashmap_get(m, key2);
416 assert_se(r == key2);
417 assert_se(!hashmap_get(m, key3));
418
419 /* Repeat this test several times to increase the chance of hitting
420 * the less likely case in hashmap_remove_and_replace where it
421 * compensates for the backward shift. */
422 for (i = 0; i < 20; i++) {
423 hashmap_clear(m);
424
425 for (j = 1; j < 7; j++)
426 hashmap_put(m, UINT_TO_PTR(10*i + j), UINT_TO_PTR(10*i + j));
427 valid = hashmap_remove_and_replace(m, UINT_TO_PTR(10*i + 1),
428 UINT_TO_PTR(10*i + 2),
429 UINT_TO_PTR(10*i + 2));
430 assert_se(valid == 0);
431 assert_se(!hashmap_get(m, UINT_TO_PTR(10*i + 1)));
432 for (j = 2; j < 7; j++) {
433 r = hashmap_get(m, UINT_TO_PTR(10*i + j));
434 assert_se(r == UINT_TO_PTR(10*i + j));
435 }
436 }
437 }
438
439 static void test_hashmap_ensure_allocated(void) {
440 Hashmap *m;
441 int valid_hashmap;
442
443 m = hashmap_new(&string_hash_ops);
444
445 valid_hashmap = hashmap_ensure_allocated(&m, &string_hash_ops);
446 assert_se(valid_hashmap == 0);
447
448 assert_se(m);
449 hashmap_free(m);
450 }
451
452 static void test_hashmap_foreach_key(void) {
453 Hashmap *m;
454 Iterator i;
455 bool key_found[] = { false, false, false, false };
456 const char *s;
457 const char *key;
458 static const char key_table[] =
459 "key 1\0"
460 "key 2\0"
461 "key 3\0"
462 "key 4\0";
463
464 m = hashmap_new(&string_hash_ops);
465
466 NULSTR_FOREACH(key, key_table)
467 hashmap_put(m, key, (void*) (const char*) "my dummy val");
468
469 HASHMAP_FOREACH_KEY(s, key, m, i) {
470 assert(s);
471 if (!key_found[0] && streq(key, "key 1"))
472 key_found[0] = true;
473 else if (!key_found[1] && streq(key, "key 2"))
474 key_found[1] = true;
475 else if (!key_found[2] && streq(key, "key 3"))
476 key_found[2] = true;
477 else if (!key_found[3] && streq(key, "fail"))
478 key_found[3] = true;
479 }
480
481 assert_se(m);
482 assert_se(key_found[0] && key_found[1] && key_found[2] && !key_found[3]);
483
484 hashmap_free(m);
485 }
486
487 static void test_hashmap_foreach(void) {
488 Hashmap *m;
489 Iterator i;
490 bool value_found[] = { false, false, false, false };
491 char *val1, *val2, *val3, *val4, *s;
492 unsigned count;
493
494 val1 = strdup("my val1");
495 assert_se(val1);
496 val2 = strdup("my val2");
497 assert_se(val2);
498 val3 = strdup("my val3");
499 assert_se(val3);
500 val4 = strdup("my val4");
501 assert_se(val4);
502
503 m = NULL;
504
505 count = 0;
506 HASHMAP_FOREACH(s, m, i)
507 count++;
508 assert_se(count == 0);
509
510 m = hashmap_new(&string_hash_ops);
511
512 count = 0;
513 HASHMAP_FOREACH(s, m, i)
514 count++;
515 assert_se(count == 0);
516
517 hashmap_put(m, "Key 1", val1);
518 hashmap_put(m, "Key 2", val2);
519 hashmap_put(m, "Key 3", val3);
520 hashmap_put(m, "Key 4", val4);
521
522 HASHMAP_FOREACH(s, m, i) {
523 if (!value_found[0] && streq(s, val1))
524 value_found[0] = true;
525 else if (!value_found[1] && streq(s, val2))
526 value_found[1] = true;
527 else if (!value_found[2] && streq(s, val3))
528 value_found[2] = true;
529 else if (!value_found[3] && streq(s, val4))
530 value_found[3] = true;
531 }
532
533 assert_se(m);
534 assert_se(value_found[0] && value_found[1] && value_found[2] && value_found[3]);
535
536 hashmap_free_free(m);
537 }
538
539 static void test_hashmap_merge(void) {
540 Hashmap *m;
541 Hashmap *n;
542 char *val1, *val2, *val3, *val4, *r;
543
544 val1 = strdup("my val1");
545 assert_se(val1);
546 val2 = strdup("my val2");
547 assert_se(val2);
548 val3 = strdup("my val3");
549 assert_se(val3);
550 val4 = strdup("my val4");
551 assert_se(val4);
552
553 n = hashmap_new(&string_hash_ops);
554 m = hashmap_new(&string_hash_ops);
555
556 hashmap_put(m, "Key 1", val1);
557 hashmap_put(m, "Key 2", val2);
558 hashmap_put(n, "Key 3", val3);
559 hashmap_put(n, "Key 4", val4);
560
561 assert_se(hashmap_merge(m, n) == 0);
562 r = hashmap_get(m, "Key 3");
563 assert_se(r && streq(r, "my val3"));
564 r = hashmap_get(m, "Key 4");
565 assert_se(r && streq(r, "my val4"));
566
567 assert_se(n);
568 assert_se(m);
569 hashmap_free(n);
570 hashmap_free_free(m);
571 }
572
573 static void test_hashmap_contains(void) {
574 Hashmap *m;
575 char *val1;
576
577 val1 = strdup("my val");
578 assert_se(val1);
579
580 m = hashmap_new(&string_hash_ops);
581
582 assert_se(!hashmap_contains(m, "Key 1"));
583 hashmap_put(m, "Key 1", val1);
584 assert_se(hashmap_contains(m, "Key 1"));
585 assert_se(!hashmap_contains(m, "Key 2"));
586
587 assert_se(!hashmap_contains(NULL, "Key 1"));
588
589 assert_se(m);
590 hashmap_free_free(m);
591 }
592
593 static void test_hashmap_isempty(void) {
594 Hashmap *m;
595 char *val1;
596
597 val1 = strdup("my val");
598 assert_se(val1);
599
600 m = hashmap_new(&string_hash_ops);
601
602 assert_se(hashmap_isempty(m));
603 hashmap_put(m, "Key 1", val1);
604 assert_se(!hashmap_isempty(m));
605
606 assert_se(m);
607 hashmap_free_free(m);
608 }
609
610 static void test_hashmap_size(void) {
611 Hashmap *m;
612 char *val1, *val2, *val3, *val4;
613
614 val1 = strdup("my val");
615 assert_se(val1);
616 val2 = strdup("my val");
617 assert_se(val2);
618 val3 = strdup("my val");
619 assert_se(val3);
620 val4 = strdup("my val");
621 assert_se(val4);
622
623 assert_se(hashmap_size(NULL) == 0);
624 assert_se(hashmap_buckets(NULL) == 0);
625
626 m = hashmap_new(&string_hash_ops);
627
628 hashmap_put(m, "Key 1", val1);
629 hashmap_put(m, "Key 2", val2);
630 hashmap_put(m, "Key 3", val3);
631 hashmap_put(m, "Key 4", val4);
632
633 assert_se(m);
634 assert_se(hashmap_size(m) == 4);
635 assert_se(hashmap_buckets(m) >= 4);
636 hashmap_free_free(m);
637 }
638
639 static void test_hashmap_get(void) {
640 Hashmap *m;
641 char *r;
642 char *val;
643
644 val = strdup("my val");
645 assert_se(val);
646
647 r = hashmap_get(NULL, "Key 1");
648 assert_se(r == NULL);
649
650 m = hashmap_new(&string_hash_ops);
651
652 hashmap_put(m, "Key 1", val);
653
654 r = hashmap_get(m, "Key 1");
655 assert_se(streq(r, val));
656
657 r = hashmap_get(m, "no such key");
658 assert_se(r == NULL);
659
660 assert_se(m);
661 hashmap_free_free(m);
662 }
663
664 static void test_hashmap_get2(void) {
665 Hashmap *m;
666 char *r;
667 char *val;
668 char key_orig[] = "Key 1";
669 void *key_copy;
670
671 val = strdup("my val");
672 assert_se(val);
673
674 key_copy = strdup(key_orig);
675 assert_se(key_copy);
676
677 r = hashmap_get2(NULL, key_orig, &key_copy);
678 assert_se(r == NULL);
679
680 m = hashmap_new(&string_hash_ops);
681
682 hashmap_put(m, key_copy, val);
683 key_copy = NULL;
684
685 r = hashmap_get2(m, key_orig, &key_copy);
686 assert_se(streq(r, val));
687 assert_se(key_orig != key_copy);
688 assert_se(streq(key_orig, key_copy));
689
690 r = hashmap_get2(m, "no such key", NULL);
691 assert_se(r == NULL);
692
693 assert_se(m);
694 hashmap_free_free_free(m);
695 }
696
697 static void crippled_hashmap_func(const void *p, struct siphash *state) {
698 return trivial_hash_func(INT_TO_PTR(PTR_TO_INT(p) & 0xff), state);
699 }
700
701 static const struct hash_ops crippled_hashmap_ops = {
702 .hash = crippled_hashmap_func,
703 .compare = trivial_compare_func,
704 };
705
706 static void test_hashmap_many(void) {
707 Hashmap *h;
708 unsigned i, j;
709 void *v, *k;
710 static const struct {
711 const struct hash_ops *ops;
712 unsigned n_entries;
713 } tests[] = {
714 { .ops = NULL, .n_entries = 1 << 20 },
715 { .ops = &crippled_hashmap_ops, .n_entries = 1 << 14 },
716 };
717
718
719 for (j = 0; j < ELEMENTSOF(tests); j++) {
720 assert_se(h = hashmap_new(tests[j].ops));
721
722 for (i = 1; i < tests[j].n_entries*3; i+=3) {
723 assert_se(hashmap_put(h, UINT_TO_PTR(i), UINT_TO_PTR(i)) >= 0);
724 assert_se(PTR_TO_UINT(hashmap_get(h, UINT_TO_PTR(i))) == i);
725 }
726
727 for (i = 1; i < tests[j].n_entries*3; i++)
728 assert_se(hashmap_contains(h, UINT_TO_PTR(i)) == (i % 3 == 1));
729
730 log_info("%u <= %u * 0.8 = %g", hashmap_size(h), hashmap_buckets(h), hashmap_buckets(h) * 0.8);
731
732 assert_se(hashmap_size(h) <= hashmap_buckets(h) * 0.8);
733 assert_se(hashmap_size(h) == tests[j].n_entries);
734
735 while (!hashmap_isempty(h)) {
736 k = hashmap_first_key(h);
737 v = hashmap_remove(h, k);
738 assert_se(v == k);
739 }
740
741 hashmap_free(h);
742 }
743 }
744
745 static void test_hashmap_first(void) {
746 _cleanup_hashmap_free_ Hashmap *m = NULL;
747
748 m = hashmap_new(&string_hash_ops);
749 assert_se(m);
750
751 assert_se(!hashmap_first(m));
752 assert_se(hashmap_put(m, "key 1", (void*) "val 1") == 1);
753 assert_se(streq(hashmap_first(m), "val 1"));
754 assert_se(hashmap_put(m, "key 2", (void*) "val 2") == 1);
755 #ifdef ORDERED
756 assert_se(streq(hashmap_first(m), "val 1"));
757 assert_se(hashmap_remove(m, "key 1"));
758 assert_se(streq(hashmap_first(m), "val 2"));
759 #endif
760 }
761
762 static void test_hashmap_first_key(void) {
763 _cleanup_hashmap_free_ Hashmap *m = NULL;
764
765 m = hashmap_new(&string_hash_ops);
766 assert_se(m);
767
768 assert_se(!hashmap_first_key(m));
769 assert_se(hashmap_put(m, "key 1", NULL) == 1);
770 assert_se(streq(hashmap_first_key(m), "key 1"));
771 assert_se(hashmap_put(m, "key 2", NULL) == 1);
772 #ifdef ORDERED
773 assert_se(streq(hashmap_first_key(m), "key 1"));
774 assert_se(hashmap_remove(m, "key 1") == NULL);
775 assert_se(streq(hashmap_first_key(m), "key 2"));
776 #endif
777 }
778
779 static void test_hashmap_steal_first_key(void) {
780 _cleanup_hashmap_free_ Hashmap *m = NULL;
781
782 m = hashmap_new(&string_hash_ops);
783 assert_se(m);
784
785 assert_se(!hashmap_steal_first_key(m));
786 assert_se(hashmap_put(m, "key 1", NULL) == 1);
787 assert_se(streq(hashmap_steal_first_key(m), "key 1"));
788
789 assert_se(hashmap_isempty(m));
790 }
791
792 static void test_hashmap_steal_first(void) {
793 _cleanup_hashmap_free_ Hashmap *m = NULL;
794 int seen[3] = {};
795 char *val;
796
797 m = hashmap_new(&string_hash_ops);
798 assert_se(m);
799
800 assert_se(hashmap_put(m, "key 1", (void*) "1") == 1);
801 assert_se(hashmap_put(m, "key 2", (void*) "22") == 1);
802 assert_se(hashmap_put(m, "key 3", (void*) "333") == 1);
803
804 while ((val = hashmap_steal_first(m)))
805 seen[strlen(val) - 1]++;
806
807 assert_se(seen[0] == 1 && seen[1] == 1 && seen[2] == 1);
808
809 assert_se(hashmap_isempty(m));
810 }
811
812 static void test_hashmap_clear_free_free(void) {
813 _cleanup_hashmap_free_ Hashmap *m = NULL;
814
815 m = hashmap_new(&string_hash_ops);
816 assert_se(m);
817
818 assert_se(hashmap_put(m, strdup("key 1"), NULL) == 1);
819 assert_se(hashmap_put(m, strdup("key 2"), NULL) == 1);
820 assert_se(hashmap_put(m, strdup("key 3"), NULL) == 1);
821
822 hashmap_clear_free_free(m);
823 assert_se(hashmap_isempty(m));
824 }
825
826 static void test_hashmap_reserve(void) {
827 _cleanup_hashmap_free_ Hashmap *m = NULL;
828
829 m = hashmap_new(&string_hash_ops);
830
831 assert_se(hashmap_reserve(m, 1) == 0);
832 assert_se(hashmap_buckets(m) < 1000);
833 assert_se(hashmap_reserve(m, 1000) == 0);
834 assert_se(hashmap_buckets(m) >= 1000);
835 assert_se(hashmap_isempty(m));
836
837 assert_se(hashmap_put(m, "key 1", (void*) "val 1") == 1);
838
839 assert_se(hashmap_reserve(m, UINT_MAX) == -ENOMEM);
840 assert_se(hashmap_reserve(m, UINT_MAX - 1) == -ENOMEM);
841 }
842
843 void test_hashmap_funcs(void) {
844 test_hashmap_copy();
845 test_hashmap_get_strv();
846 test_hashmap_move_one();
847 test_hashmap_move();
848 test_hashmap_replace();
849 test_hashmap_update();
850 test_hashmap_put();
851 test_hashmap_remove();
852 test_hashmap_remove2();
853 test_hashmap_remove_value();
854 test_hashmap_remove_and_put();
855 test_hashmap_remove_and_replace();
856 test_hashmap_ensure_allocated();
857 test_hashmap_foreach();
858 test_hashmap_foreach_key();
859 test_hashmap_contains();
860 test_hashmap_merge();
861 test_hashmap_isempty();
862 test_hashmap_get();
863 test_hashmap_get2();
864 test_hashmap_size();
865 test_hashmap_many();
866 test_hashmap_first();
867 test_hashmap_first_key();
868 test_hashmap_steal_first_key();
869 test_hashmap_steal_first();
870 test_hashmap_clear_free_free();
871 test_hashmap_reserve();
872 }