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