2 This file is part of systemd
4 Copyright 2013 Daniel Buch
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.
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.
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/>.
25 static void test_hashmap_replace(void) {
27 char *val1
, *val2
, *val3
, *val4
, *val5
, *r
;
29 m
= hashmap_new(&string_hash_ops
);
31 val1
= strdup("val1");
33 val2
= strdup("val2");
35 val3
= strdup("val3");
37 val4
= strdup("val4");
39 val5
= strdup("val5");
42 hashmap_put(m
, "key 1", val1
);
43 hashmap_put(m
, "key 2", val2
);
44 hashmap_put(m
, "key 3", val3
);
45 hashmap_put(m
, "key 4", val4
);
47 hashmap_replace(m
, "key 3", val1
);
48 r
= hashmap_get(m
, "key 3");
49 assert_se(streq(r
, "val1"));
51 hashmap_replace(m
, "key 5", val5
);
52 r
= hashmap_get(m
, "key 5");
53 assert_se(streq(r
, "val5"));
63 static void test_hashmap_copy(void) {
65 char *val1
, *val2
, *val3
, *val4
, *r
;
67 val1
= strdup("val1");
69 val2
= strdup("val2");
71 val3
= strdup("val3");
73 val4
= strdup("val4");
76 m
= hashmap_new(&string_hash_ops
);
78 hashmap_put(m
, "key 1", val1
);
79 hashmap_put(m
, "key 2", val2
);
80 hashmap_put(m
, "key 3", val3
);
81 hashmap_put(m
, "key 4", val4
);
83 copy
= hashmap_copy(m
);
85 r
= hashmap_get(copy
, "key 1");
86 assert_se(streq(r
, "val1"));
87 r
= hashmap_get(copy
, "key 2");
88 assert_se(streq(r
, "val2"));
89 r
= hashmap_get(copy
, "key 3");
90 assert_se(streq(r
, "val3"));
91 r
= hashmap_get(copy
, "key 4");
92 assert_se(streq(r
, "val4"));
94 hashmap_free_free(copy
);
98 static void test_hashmap_get_strv(void) {
101 char *val1
, *val2
, *val3
, *val4
;
103 val1
= strdup("val1");
105 val2
= strdup("val2");
107 val3
= strdup("val3");
109 val4
= strdup("val4");
112 m
= hashmap_new(&string_hash_ops
);
114 hashmap_put(m
, "key 1", val1
);
115 hashmap_put(m
, "key 2", val2
);
116 hashmap_put(m
, "key 3", val3
);
117 hashmap_put(m
, "key 4", val4
);
119 strv
= hashmap_get_strv(m
);
121 assert_se(streq(strv
[0], "val1"));
122 assert_se(streq(strv
[1], "val2"));
123 assert_se(streq(strv
[2], "val3"));
124 assert_se(streq(strv
[3], "val4"));
131 static void test_hashmap_move_one(void) {
133 char *val1
, *val2
, *val3
, *val4
, *r
;
135 val1
= strdup("val1");
137 val2
= strdup("val2");
139 val3
= strdup("val3");
141 val4
= strdup("val4");
144 m
= hashmap_new(&string_hash_ops
);
145 n
= hashmap_new(&string_hash_ops
);
147 hashmap_put(m
, "key 1", val1
);
148 hashmap_put(m
, "key 2", val2
);
149 hashmap_put(m
, "key 3", val3
);
150 hashmap_put(m
, "key 4", val4
);
152 hashmap_move_one(n
, m
, "key 3");
153 hashmap_move_one(n
, m
, "key 4");
155 r
= hashmap_get(n
, "key 3");
156 assert_se(r
&& streq(r
, "val3"));
157 r
= hashmap_get(n
, "key 4");
158 assert_se(r
&& streq(r
, "val4"));
159 r
= hashmap_get(m
, "key 3");
163 hashmap_free_free(m
);
164 hashmap_free_free(n
);
167 static void test_hashmap_next(void) {
169 char *val1
, *val2
, *val3
, *val4
, *r
;
171 m
= hashmap_new(&string_hash_ops
);
172 val1
= strdup("val1");
174 val2
= strdup("val2");
176 val3
= strdup("val3");
178 val4
= strdup("val4");
181 hashmap_put(m
, "key 1", val1
);
182 hashmap_put(m
, "key 2", val2
);
183 hashmap_put(m
, "key 3", val3
);
184 hashmap_put(m
, "key 4", val4
);
186 r
= hashmap_next(m
, "key 1");
187 assert_se(streq(r
, val2
));
188 r
= hashmap_next(m
, "key 2");
189 assert_se(streq(r
, val3
));
190 r
= hashmap_next(m
, "key 3");
191 assert_se(streq(r
, val4
));
192 r
= hashmap_next(m
, "key 4");
195 hashmap_free_free(m
);
198 static void test_hashmap_update(void) {
200 char *val1
, *val2
, *r
;
202 m
= hashmap_new(&string_hash_ops
);
203 val1
= strdup("old_value");
205 val2
= strdup("new_value");
208 hashmap_put(m
, "key 1", val1
);
209 r
= hashmap_get(m
, "key 1");
210 assert_se(streq(r
, "old_value"));
212 hashmap_update(m
, "key 1", val2
);
213 r
= hashmap_get(m
, "key 1");
214 assert_se(streq(r
, "new_value"));
221 static void test_hashmap_put(void) {
223 int valid_hashmap_put
;
225 m
= hashmap_new(&string_hash_ops
);
227 valid_hashmap_put
= hashmap_put(m
, "key 1", (void*) (const char *) "val 1");
228 assert_se(valid_hashmap_put
== 1);
234 static void test_hashmap_remove_and_put(void) {
235 _cleanup_hashmap_free_ Hashmap
*m
= NULL
;
239 m
= hashmap_new(&string_hash_ops
);
242 valid
= hashmap_remove_and_put(m
, "unvalid key", "new key", NULL
);
243 assert_se(valid
< 0);
245 valid
= hashmap_put(m
, "key 1", (void*) (const char *) "val 1");
246 assert_se(valid
== 1);
247 valid
= hashmap_remove_and_put(m
, "key 1", "key 2", (void*) (const char *) "val 2");
248 assert_se(valid
== 0);
250 r
= hashmap_get(m
, "key 2");
251 assert_se(streq(r
, "val 2"));
252 assert_se(!hashmap_get(m
, "key 1"));
254 valid
= hashmap_put(m
, "key 3", (void*) (const char *) "val 3");
255 assert_se(valid
== 1);
256 valid
= hashmap_remove_and_put(m
, "key 3", "key 2", (void*) (const char *) "val 2");
257 assert_se(valid
< 0);
260 static void test_hashmap_ensure_allocated(void) {
264 m
= hashmap_new(&string_hash_ops
);
266 valid_hashmap
= hashmap_ensure_allocated(&m
, &string_hash_ops
);
267 assert_se(valid_hashmap
== 0);
273 static void test_hashmap_foreach_key(void) {
276 bool key_found
[] = { false, false, false, false };
279 static const char key_table
[] =
285 m
= hashmap_new(&string_hash_ops
);
287 NULSTR_FOREACH(key
, key_table
)
288 hashmap_put(m
, key
, (void*) (const char*) "my dummy val");
290 HASHMAP_FOREACH_KEY(s
, key
, m
, i
) {
291 if (!key_found
[0] && streq(key
, "key 1"))
293 else if (!key_found
[1] && streq(key
, "key 2"))
295 else if (!key_found
[2] && streq(key
, "key 3"))
297 else if (!key_found
[3] && streq(key
, "fail"))
302 assert_se(key_found
[0] && key_found
[1] && key_found
[2] && !key_found
[3]);
307 static void test_hashmap_foreach(void) {
310 bool value_found
[] = { false, false, false, false };
311 char *val1
, *val2
, *val3
, *val4
, *s
;
313 val1
= strdup("my val1");
315 val2
= strdup("my val2");
317 val3
= strdup("my val3");
319 val4
= strdup("my val4");
322 m
= hashmap_new(&string_hash_ops
);
324 hashmap_put(m
, "Key 1", val1
);
325 hashmap_put(m
, "Key 2", val2
);
326 hashmap_put(m
, "Key 3", val3
);
327 hashmap_put(m
, "Key 4", val4
);
329 HASHMAP_FOREACH(s
, m
, i
) {
330 if (!value_found
[0] && streq(s
, val1
))
331 value_found
[0] = true;
332 else if (!value_found
[1] && streq(s
, val2
))
333 value_found
[1] = true;
334 else if (!value_found
[2] && streq(s
, val3
))
335 value_found
[2] = true;
336 else if (!value_found
[3] && streq(s
, val4
))
337 value_found
[3] = true;
341 assert_se(value_found
[0] && value_found
[1] && value_found
[2] && value_found
[3]);
343 hashmap_free_free(m
);
346 static void test_hashmap_foreach_backwards(void) {
349 char *val1
, *val2
, *val3
, *val4
, *s
;
350 bool value_found
[] = { false, false, false, false };
352 val1
= strdup("my val1");
354 val2
= strdup("my val2");
356 val3
= strdup("my val3");
358 val4
= strdup("my val4");
361 m
= hashmap_new(&string_hash_ops
);
362 hashmap_put(m
, "Key 1", val1
);
363 hashmap_put(m
, "Key 2", val2
);
364 hashmap_put(m
, "Key 3", val3
);
365 hashmap_put(m
, "Key 4", val4
);
367 HASHMAP_FOREACH_BACKWARDS(s
, m
, i
) {
368 if (!value_found
[0] && streq(s
, val1
))
369 value_found
[0] = true;
370 else if (!value_found
[1] && streq(s
, val2
))
371 value_found
[1] = true;
372 else if (!value_found
[2] && streq(s
, val3
))
373 value_found
[2] = true;
374 else if (!value_found
[3] && streq(s
, val4
))
375 value_found
[3] = true;
379 assert_se(value_found
[0] && value_found
[1] && value_found
[2] && value_found
[3]);
381 hashmap_free_free(m
);
384 static void test_hashmap_merge(void) {
387 char *val1
, *val2
, *val3
, *val4
, *r
;
389 val1
= strdup("my val1");
391 val2
= strdup("my val2");
393 val3
= strdup("my val3");
395 val4
= strdup("my val4");
398 n
= hashmap_new(&string_hash_ops
);
399 m
= hashmap_new(&string_hash_ops
);
401 hashmap_put(m
, "Key 1", val1
);
402 hashmap_put(m
, "Key 2", val2
);
403 hashmap_put(n
, "Key 3", val3
);
404 hashmap_put(n
, "Key 4", val4
);
406 assert_se(hashmap_merge(m
, n
) == 0);
407 r
= hashmap_get(m
, "Key 3");
408 assert_se(r
&& streq(r
, "my val3"));
409 r
= hashmap_get(m
, "Key 4");
410 assert_se(r
&& streq(r
, "my val4"));
415 hashmap_free_free(m
);
418 static void test_hashmap_contains(void) {
422 val1
= strdup("my val");
425 m
= hashmap_new(&string_hash_ops
);
427 assert_se(!hashmap_contains(m
, "Key 1"));
428 hashmap_put(m
, "Key 1", val1
);
429 assert_se(hashmap_contains(m
, "Key 1"));
432 hashmap_free_free(m
);
435 static void test_hashmap_isempty(void) {
439 val1
= strdup("my val");
442 m
= hashmap_new(&string_hash_ops
);
444 assert_se(hashmap_isempty(m
));
445 hashmap_put(m
, "Key 1", val1
);
446 assert_se(!hashmap_isempty(m
));
449 hashmap_free_free(m
);
452 static void test_hashmap_size(void) {
454 char *val1
, *val2
, *val3
, *val4
;
456 val1
= strdup("my val");
458 val2
= strdup("my val");
460 val3
= strdup("my val");
462 val4
= strdup("my val");
465 m
= hashmap_new(&string_hash_ops
);
467 hashmap_put(m
, "Key 1", val1
);
468 hashmap_put(m
, "Key 2", val2
);
469 hashmap_put(m
, "Key 3", val3
);
470 hashmap_put(m
, "Key 4", val4
);
473 assert_se(hashmap_size(m
) == 4);
474 hashmap_free_free(m
);
477 static void test_hashmap_get(void) {
482 val
= strdup("my val");
485 m
= hashmap_new(&string_hash_ops
);
487 hashmap_put(m
, "Key 1", val
);
489 r
= hashmap_get(m
, "Key 1");
490 assert_se(streq(r
, val
));
493 hashmap_free_free(m
);
496 static void test_hashmap_many(void) {
500 #define N_ENTRIES 100000
502 assert_se(h
= hashmap_new(NULL
));
504 for (i
= 1; i
< N_ENTRIES
*3; i
+=3) {
505 assert_se(hashmap_put(h
, UINT_TO_PTR(i
), UINT_TO_PTR(i
)) >= 0);
506 assert_se(PTR_TO_UINT(hashmap_get(h
, UINT_TO_PTR(i
))) == i
);
509 for (i
= 1; i
< N_ENTRIES
*3; i
++)
510 assert_se(hashmap_contains(h
, UINT_TO_PTR(i
)) == (i
% 3 == 1));
512 log_info("%u <= %u * 0.75 = %g", hashmap_size(h
), hashmap_buckets(h
), hashmap_buckets(h
) * 0.75);
514 assert_se(hashmap_size(h
) <= hashmap_buckets(h
) * 0.75);
515 assert_se(hashmap_size(h
) == N_ENTRIES
);
520 static void test_hashmap_first_key(void) {
521 _cleanup_hashmap_free_ Hashmap
*m
= NULL
;
523 m
= hashmap_new(&string_hash_ops
);
526 assert_se(!hashmap_first_key(m
));
527 assert_se(hashmap_put(m
, "key 1", NULL
) == 1);
528 assert_se(streq(hashmap_first_key(m
), "key 1"));
529 assert_se(hashmap_put(m
, "key 2", NULL
) == 1);
530 assert_se(streq(hashmap_first_key(m
), "key 1"));
531 assert_se(hashmap_remove(m
, "key 1") == NULL
);
532 assert_se(streq(hashmap_first_key(m
), "key 2"));
535 static void test_hashmap_last(void) {
536 _cleanup_hashmap_free_ Hashmap
*m
= NULL
;
538 m
= hashmap_new(&string_hash_ops
);
541 assert_se(!hashmap_last(m
));
542 assert_se(hashmap_put(m
, "key 1", (void *) (const char *) "val 1") == 1);
543 assert_se(streq(hashmap_last(m
), "val 1"));
544 assert_se(hashmap_put(m
, "key 2", (void *) (const char *) "bar") == 1);
545 assert_se(streq(hashmap_last(m
), "bar"));
546 assert_se(hashmap_remove(m
, "key 2"));
547 assert_se(streq(hashmap_last(m
), "val 1"));
550 static void test_hashmap_steal_first_key(void) {
551 _cleanup_hashmap_free_ Hashmap
*m
= NULL
;
553 m
= hashmap_new(&string_hash_ops
);
556 assert_se(!hashmap_steal_first_key(m
));
557 assert_se(hashmap_put(m
, "key 1", NULL
) == 1);
558 assert_se(streq(hashmap_steal_first_key(m
), "key 1"));
560 assert_se(hashmap_isempty(m
));
563 static void test_hashmap_clear_free_free(void) {
564 _cleanup_hashmap_free_ Hashmap
*m
= NULL
;
566 m
= hashmap_new(&string_hash_ops
);
569 assert_se(hashmap_put(m
, strdup("key 1"), NULL
) == 1);
570 assert_se(hashmap_put(m
, strdup("key 2"), NULL
) == 1);
571 assert_se(hashmap_put(m
, strdup("key 3"), NULL
) == 1);
573 hashmap_clear_free_free(m
);
574 assert_se(hashmap_isempty(m
));
577 static void test_uint64_compare_func(void) {
578 const uint64_t a
= 0x100, b
= 0x101;
580 assert_se(uint64_compare_func(&a
, &a
) == 0);
581 assert_se(uint64_compare_func(&a
, &b
) == -1);
582 assert_se(uint64_compare_func(&b
, &a
) == 1);
585 static void test_trivial_compare_func(void) {
586 assert_se(trivial_compare_func(INT_TO_PTR('a'), INT_TO_PTR('a')) == 0);
587 assert_se(trivial_compare_func(INT_TO_PTR('a'), INT_TO_PTR('b')) == -1);
588 assert_se(trivial_compare_func(INT_TO_PTR('b'), INT_TO_PTR('a')) == 1);
591 static void test_string_compare_func(void) {
592 assert_se(!string_compare_func("fred", "wilma") == 0);
593 assert_se(string_compare_func("fred", "fred") == 0);
596 int main(int argc
, const char *argv
[]) {
598 test_hashmap_get_strv();
599 test_hashmap_move_one();
601 test_hashmap_replace();
602 test_hashmap_update();
604 test_hashmap_remove_and_put();
605 test_hashmap_ensure_allocated();
606 test_hashmap_foreach();
607 test_hashmap_foreach_backwards();
608 test_hashmap_foreach_key();
609 test_hashmap_contains();
610 test_hashmap_merge();
611 test_hashmap_isempty();
615 test_hashmap_first_key();
617 test_hashmap_steal_first_key();
618 test_hashmap_clear_free_free();
619 test_uint64_compare_func();
620 test_trivial_compare_func();
621 test_string_compare_func();