chiark / gitweb /
9080df5da8fe582cc9f07f5699b7535e5ddec2b0
[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 "strv.h"
21 #include "util.h"
22 #include "hashmap.h"
23
24 void test_hashmap_funcs(void);
25
26 static void test_hashmap_replace(void) {
27         Hashmap *m;
28         char *val1, *val2, *val3, *val4, *val5, *r;
29
30         m = hashmap_new(&string_hash_ops);
31
32         val1 = strdup("val1");
33         assert_se(val1);
34         val2 = strdup("val2");
35         assert_se(val2);
36         val3 = strdup("val3");
37         assert_se(val3);
38         val4 = strdup("val4");
39         assert_se(val4);
40         val5 = strdup("val5");
41         assert_se(val5);
42
43         hashmap_put(m, "key 1", val1);
44         hashmap_put(m, "key 2", val2);
45         hashmap_put(m, "key 3", val3);
46         hashmap_put(m, "key 4", val4);
47
48         hashmap_replace(m, "key 3", val1);
49         r = hashmap_get(m, "key 3");
50         assert_se(streq(r, "val1"));
51
52         hashmap_replace(m, "key 5", val5);
53         r = hashmap_get(m, "key 5");
54         assert_se(streq(r, "val5"));
55
56         free(val1);
57         free(val2);
58         free(val3);
59         free(val4);
60         free(val5);
61         hashmap_free(m);
62 }
63
64 static void test_hashmap_copy(void) {
65         Hashmap *m, *copy;
66         char *val1, *val2, *val3, *val4, *r;
67
68         val1 = strdup("val1");
69         assert_se(val1);
70         val2 = strdup("val2");
71         assert_se(val2);
72         val3 = strdup("val3");
73         assert_se(val3);
74         val4 = strdup("val4");
75         assert_se(val4);
76
77         m = hashmap_new(&string_hash_ops);
78
79         hashmap_put(m, "key 1", val1);
80         hashmap_put(m, "key 2", val2);
81         hashmap_put(m, "key 3", val3);
82         hashmap_put(m, "key 4", val4);
83
84         copy = hashmap_copy(m);
85
86         r = hashmap_get(copy, "key 1");
87         assert_se(streq(r, "val1"));
88         r = hashmap_get(copy, "key 2");
89         assert_se(streq(r, "val2"));
90         r = hashmap_get(copy, "key 3");
91         assert_se(streq(r, "val3"));
92         r = hashmap_get(copy, "key 4");
93         assert_se(streq(r, "val4"));
94
95         hashmap_free_free(copy);
96         hashmap_free(m);
97 }
98
99 static void test_hashmap_get_strv(void) {
100         Hashmap *m;
101         char **strv;
102         char *val1, *val2, *val3, *val4;
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         val1 = strdup("val1");
141         assert_se(val1);
142         val2 = strdup("val2");
143         assert_se(val2);
144         val3 = strdup("val3");
145         assert_se(val3);
146         val4 = strdup("val4");
147         assert_se(val4);
148
149         m = hashmap_new(&string_hash_ops);
150         n = hashmap_new(&string_hash_ops);
151
152         hashmap_put(m, "key 1", val1);
153         hashmap_put(m, "key 2", val2);
154         hashmap_put(m, "key 3", val3);
155         hashmap_put(m, "key 4", val4);
156
157         hashmap_move_one(n, m, "key 3");
158         hashmap_move_one(n, m, "key 4");
159
160         r = hashmap_get(n, "key 3");
161         assert_se(r && streq(r, "val3"));
162         r = hashmap_get(n, "key 4");
163         assert_se(r && streq(r, "val4"));
164         r = hashmap_get(m, "key 3");
165         assert_se(!r);
166
167
168         hashmap_free_free(m);
169         hashmap_free_free(n);
170 }
171
172 static void test_hashmap_update(void) {
173         Hashmap *m;
174         char *val1, *val2, *r;
175
176         m = hashmap_new(&string_hash_ops);
177         val1 = strdup("old_value");
178         assert_se(val1);
179         val2 = strdup("new_value");
180         assert_se(val2);
181
182         hashmap_put(m, "key 1", val1);
183         r = hashmap_get(m, "key 1");
184         assert_se(streq(r, "old_value"));
185
186         hashmap_update(m, "key 1", val2);
187         r = hashmap_get(m, "key 1");
188         assert_se(streq(r, "new_value"));
189
190         free(val1);
191         free(val2);
192         hashmap_free(m);
193 }
194
195 static void test_hashmap_put(void) {
196         Hashmap *m;
197         int valid_hashmap_put;
198
199         m = hashmap_new(&string_hash_ops);
200
201         valid_hashmap_put = hashmap_put(m, "key 1", (void*) (const char *) "val 1");
202         assert_se(valid_hashmap_put == 1);
203
204         assert_se(m);
205         hashmap_free(m);
206 }
207
208 static void test_hashmap_remove_and_put(void) {
209         _cleanup_hashmap_free_ Hashmap *m = NULL;
210         int valid;
211         char *r;
212
213         m = hashmap_new(&string_hash_ops);
214         assert_se(m);
215
216         valid = hashmap_remove_and_put(m, "unvalid key", "new key", NULL);
217         assert_se(valid < 0);
218
219         valid = hashmap_put(m, "key 1", (void*) (const char *) "val 1");
220         assert_se(valid == 1);
221         valid = hashmap_remove_and_put(m, "key 1", "key 2", (void*) (const char *) "val 2");
222         assert_se(valid == 0);
223
224         r = hashmap_get(m, "key 2");
225         assert_se(streq(r, "val 2"));
226         assert_se(!hashmap_get(m, "key 1"));
227
228         valid = hashmap_put(m, "key 3", (void*) (const char *) "val 3");
229         assert_se(valid == 1);
230         valid = hashmap_remove_and_put(m, "key 3", "key 2", (void*) (const char *) "val 2");
231         assert_se(valid < 0);
232 }
233
234 static void test_hashmap_ensure_allocated(void) {
235         Hashmap *m;
236         int valid_hashmap;
237
238         m = hashmap_new(&string_hash_ops);
239
240         valid_hashmap = hashmap_ensure_allocated(&m, &string_hash_ops);
241         assert_se(valid_hashmap == 0);
242
243         assert_se(m);
244         hashmap_free(m);
245 }
246
247 static void test_hashmap_foreach_key(void) {
248         Hashmap *m;
249         Iterator i;
250         bool key_found[] = { false, false, false, false };
251         const char *s;
252         const char *key;
253         static const char key_table[] =
254                 "key 1\0"
255                 "key 2\0"
256                 "key 3\0"
257                 "key 4\0";
258
259         m = hashmap_new(&string_hash_ops);
260
261         NULSTR_FOREACH(key, key_table)
262                 hashmap_put(m, key, (void*) (const char*) "my dummy val");
263
264         HASHMAP_FOREACH_KEY(s, key, m, i) {
265                 if (!key_found[0] && streq(key, "key 1"))
266                         key_found[0] = true;
267                 else if (!key_found[1] && streq(key, "key 2"))
268                         key_found[1] = true;
269                 else if (!key_found[2] && streq(key, "key 3"))
270                         key_found[2] = true;
271                 else if (!key_found[3] && streq(key, "fail"))
272                         key_found[3] = true;
273         }
274
275         assert_se(m);
276         assert_se(key_found[0] && key_found[1] && key_found[2] && !key_found[3]);
277
278         hashmap_free(m);
279 }
280
281 static void test_hashmap_foreach(void) {
282         Hashmap *m;
283         Iterator i;
284         bool value_found[] = { false, false, false, false };
285         char *val1, *val2, *val3, *val4, *s;
286
287         val1 = strdup("my val1");
288         assert_se(val1);
289         val2 = strdup("my val2");
290         assert_se(val2);
291         val3 = strdup("my val3");
292         assert_se(val3);
293         val4 = strdup("my val4");
294         assert_se(val4);
295
296         m = hashmap_new(&string_hash_ops);
297
298         hashmap_put(m, "Key 1", val1);
299         hashmap_put(m, "Key 2", val2);
300         hashmap_put(m, "Key 3", val3);
301         hashmap_put(m, "Key 4", val4);
302
303         HASHMAP_FOREACH(s, m, i) {
304                 if (!value_found[0] && streq(s, val1))
305                         value_found[0] = true;
306                 else if (!value_found[1] && streq(s, val2))
307                         value_found[1] = true;
308                 else if (!value_found[2] && streq(s, val3))
309                         value_found[2] = true;
310                 else if (!value_found[3] && streq(s, val4))
311                         value_found[3] = true;
312         }
313
314         assert_se(m);
315         assert_se(value_found[0] && value_found[1] && value_found[2] && value_found[3]);
316
317         hashmap_free_free(m);
318 }
319
320 static void test_hashmap_merge(void) {
321         Hashmap *m;
322         Hashmap *n;
323         char *val1, *val2, *val3, *val4, *r;
324
325         val1 = strdup("my val1");
326         assert_se(val1);
327         val2 = strdup("my val2");
328         assert_se(val2);
329         val3 = strdup("my val3");
330         assert_se(val3);
331         val4 = strdup("my val4");
332         assert_se(val4);
333
334         n = hashmap_new(&string_hash_ops);
335         m = hashmap_new(&string_hash_ops);
336
337         hashmap_put(m, "Key 1", val1);
338         hashmap_put(m, "Key 2", val2);
339         hashmap_put(n, "Key 3", val3);
340         hashmap_put(n, "Key 4", val4);
341
342         assert_se(hashmap_merge(m, n) == 0);
343         r = hashmap_get(m, "Key 3");
344         assert_se(r && streq(r, "my val3"));
345         r = hashmap_get(m, "Key 4");
346         assert_se(r && streq(r, "my val4"));
347
348         assert_se(n);
349         assert_se(m);
350         hashmap_free(n);
351         hashmap_free_free(m);
352 }
353
354 static void test_hashmap_contains(void) {
355         Hashmap *m;
356         char *val1;
357
358         val1 = strdup("my val");
359         assert_se(val1);
360
361         m = hashmap_new(&string_hash_ops);
362
363         assert_se(!hashmap_contains(m, "Key 1"));
364         hashmap_put(m, "Key 1", val1);
365         assert_se(hashmap_contains(m, "Key 1"));
366
367         assert_se(m);
368         hashmap_free_free(m);
369 }
370
371 static void test_hashmap_isempty(void) {
372         Hashmap *m;
373         char *val1;
374
375         val1 = strdup("my val");
376         assert_se(val1);
377
378         m = hashmap_new(&string_hash_ops);
379
380         assert_se(hashmap_isempty(m));
381         hashmap_put(m, "Key 1", val1);
382         assert_se(!hashmap_isempty(m));
383
384         assert_se(m);
385         hashmap_free_free(m);
386 }
387
388 static void test_hashmap_size(void) {
389         Hashmap *m;
390         char *val1, *val2, *val3, *val4;
391
392         val1 = strdup("my val");
393         assert_se(val1);
394         val2 = strdup("my val");
395         assert_se(val2);
396         val3 = strdup("my val");
397         assert_se(val3);
398         val4 = strdup("my val");
399         assert_se(val4);
400
401         m = hashmap_new(&string_hash_ops);
402
403         hashmap_put(m, "Key 1", val1);
404         hashmap_put(m, "Key 2", val2);
405         hashmap_put(m, "Key 3", val3);
406         hashmap_put(m, "Key 4", val4);
407
408         assert_se(m);
409         assert_se(hashmap_size(m) == 4);
410         hashmap_free_free(m);
411 }
412
413 static void test_hashmap_get(void) {
414         Hashmap *m;
415         char *r;
416         char *val;
417
418         val = strdup("my val");
419         assert_se(val);
420
421         m = hashmap_new(&string_hash_ops);
422
423         hashmap_put(m, "Key 1", val);
424
425         r = hashmap_get(m, "Key 1");
426         assert_se(streq(r, val));
427
428         assert_se(m);
429         hashmap_free_free(m);
430 }
431
432 static void test_hashmap_many(void) {
433         Hashmap *h;
434         unsigned i;
435
436 #define N_ENTRIES 100000
437
438         assert_se(h = hashmap_new(NULL));
439
440         for (i = 1; i < N_ENTRIES*3; i+=3) {
441                 assert_se(hashmap_put(h, UINT_TO_PTR(i), UINT_TO_PTR(i)) >= 0);
442                 assert_se(PTR_TO_UINT(hashmap_get(h, UINT_TO_PTR(i))) == i);
443         }
444
445         for (i = 1; i < N_ENTRIES*3; i++)
446                 assert_se(hashmap_contains(h, UINT_TO_PTR(i)) == (i % 3 == 1));
447
448         log_info("%u <= %u * 0.75 = %g", hashmap_size(h), hashmap_buckets(h), hashmap_buckets(h) * 0.75);
449
450         assert_se(hashmap_size(h) <= hashmap_buckets(h) * 0.75);
451         assert_se(hashmap_size(h) == N_ENTRIES);
452
453         hashmap_free(h);
454 }
455
456 static void test_hashmap_first_key(void) {
457         _cleanup_hashmap_free_ Hashmap *m = NULL;
458
459         m = hashmap_new(&string_hash_ops);
460         assert_se(m);
461
462         assert_se(!hashmap_first_key(m));
463         assert_se(hashmap_put(m, "key 1", NULL) == 1);
464         assert_se(streq(hashmap_first_key(m), "key 1"));
465         assert_se(hashmap_put(m, "key 2", NULL) == 1);
466 #ifdef ORDERED
467         assert_se(streq(hashmap_first_key(m), "key 1"));
468         assert_se(hashmap_remove(m, "key 1") == NULL);
469         assert_se(streq(hashmap_first_key(m), "key 2"));
470 #endif
471 }
472
473 static void test_hashmap_steal_first_key(void) {
474         _cleanup_hashmap_free_ Hashmap *m = NULL;
475
476         m = hashmap_new(&string_hash_ops);
477         assert_se(m);
478
479         assert_se(!hashmap_steal_first_key(m));
480         assert_se(hashmap_put(m, "key 1", NULL) == 1);
481         assert_se(streq(hashmap_steal_first_key(m), "key 1"));
482
483         assert_se(hashmap_isempty(m));
484 }
485
486 static void test_hashmap_steal_first(void) {
487         _cleanup_hashmap_free_ Hashmap *m = NULL;
488         int seen[3] = {};
489         char *val;
490
491         m = hashmap_new(&string_hash_ops);
492         assert_se(m);
493
494         assert_se(hashmap_put(m, "key 1", (void*) "1") == 1);
495         assert_se(hashmap_put(m, "key 2", (void*) "22") == 1);
496         assert_se(hashmap_put(m, "key 3", (void*) "333") == 1);
497
498         while ((val = hashmap_steal_first(m)))
499                 seen[strlen(val) - 1]++;
500
501         assert_se(seen[0] == 1 && seen[1] == 1 && seen[2] == 1);
502
503         assert_se(hashmap_isempty(m));
504 }
505
506 static void test_hashmap_clear_free_free(void) {
507         _cleanup_hashmap_free_ Hashmap *m = NULL;
508
509         m = hashmap_new(&string_hash_ops);
510         assert_se(m);
511
512         assert_se(hashmap_put(m, strdup("key 1"), NULL) == 1);
513         assert_se(hashmap_put(m, strdup("key 2"), NULL) == 1);
514         assert_se(hashmap_put(m, strdup("key 3"), NULL) == 1);
515
516         hashmap_clear_free_free(m);
517         assert_se(hashmap_isempty(m));
518 }
519
520 void test_hashmap_funcs(void) {
521         test_hashmap_copy();
522         test_hashmap_get_strv();
523         test_hashmap_move_one();
524         test_hashmap_replace();
525         test_hashmap_update();
526         test_hashmap_put();
527         test_hashmap_remove_and_put();
528         test_hashmap_ensure_allocated();
529         test_hashmap_foreach();
530         test_hashmap_foreach_key();
531         test_hashmap_contains();
532         test_hashmap_merge();
533         test_hashmap_isempty();
534         test_hashmap_get();
535         test_hashmap_size();
536         test_hashmap_many();
537         test_hashmap_first_key();
538         test_hashmap_steal_first_key();
539         test_hashmap_steal_first();
540         test_hashmap_clear_free_free();
541 }