1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include "random-util.h"
4 #include "set.h"
5 #include "strv.h"
6 #include "tests.h"
7 
8 const bool mempool_use_allowed = VALGRIND;
9 
TEST(set_steal_first)10 TEST(set_steal_first) {
11         _cleanup_set_free_ Set *m = NULL;
12         int seen[3] = {};
13         char *val;
14 
15         m = set_new(&string_hash_ops);
16         assert_se(m);
17 
18         assert_se(set_put(m, (void*) "1") == 1);
19         assert_se(set_put(m, (void*) "22") == 1);
20         assert_se(set_put(m, (void*) "333") == 1);
21 
22         while ((val = set_steal_first(m)))
23                 seen[strlen(val) - 1]++;
24 
25         assert_se(seen[0] == 1 && seen[1] == 1 && seen[2] == 1);
26 
27         assert_se(set_isempty(m));
28 }
29 
30 typedef struct Item {
31         int seen;
32 } Item;
item_seen(Item * item)33 static void item_seen(Item *item) {
34         item->seen++;
35 }
36 
TEST(set_free_with_destructor)37 TEST(set_free_with_destructor) {
38         Set *m;
39         struct Item items[4] = {};
40         unsigned i;
41 
42         assert_se(m = set_new(NULL));
43         for (i = 0; i < ELEMENTSOF(items) - 1; i++)
44                 assert_se(set_put(m, items + i) == 1);
45 
46         m = set_free_with_destructor(m, item_seen);
47         assert_se(items[0].seen == 1);
48         assert_se(items[1].seen == 1);
49         assert_se(items[2].seen == 1);
50         assert_se(items[3].seen == 0);
51 }
52 
53 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_hash_ops, void, trivial_hash_func, trivial_compare_func, Item, item_seen);
54 
TEST(set_free_with_hash_ops)55 TEST(set_free_with_hash_ops) {
56         Set *m;
57         struct Item items[4] = {};
58         unsigned i;
59 
60         assert_se(m = set_new(&item_hash_ops));
61         for (i = 0; i < ELEMENTSOF(items) - 1; i++)
62                 assert_se(set_put(m, items + i) == 1);
63 
64         m = set_free(m);
65         assert_se(items[0].seen == 1);
66         assert_se(items[1].seen == 1);
67         assert_se(items[2].seen == 1);
68         assert_se(items[3].seen == 0);
69 }
70 
TEST(set_put)71 TEST(set_put) {
72         _cleanup_set_free_ Set *m = NULL;
73 
74         m = set_new(&string_hash_ops);
75         assert_se(m);
76 
77         assert_se(set_put(m, (void*) "1") == 1);
78         assert_se(set_put(m, (void*) "22") == 1);
79         assert_se(set_put(m, (void*) "333") == 1);
80         assert_se(set_put(m, (void*) "333") == 0);
81         assert_se(set_remove(m, (void*) "333"));
82         assert_se(set_put(m, (void*) "333") == 1);
83         assert_se(set_put(m, (void*) "333") == 0);
84         assert_se(set_put(m, (void*) "22") == 0);
85 
86         _cleanup_free_ char **t = set_get_strv(m);
87         assert_se(strv_contains(t, "1"));
88         assert_se(strv_contains(t, "22"));
89         assert_se(strv_contains(t, "333"));
90         assert_se(strv_length(t) == 3);
91 }
92 
TEST(set_put_strdup)93 TEST(set_put_strdup) {
94         _cleanup_set_free_ Set *m = NULL;
95 
96         assert_se(set_put_strdup(&m, "aaa") == 1);
97         assert_se(set_put_strdup(&m, "aaa") == 0);
98         assert_se(set_put_strdup(&m, "bbb") == 1);
99         assert_se(set_put_strdup(&m, "bbb") == 0);
100         assert_se(set_put_strdup(&m, "aaa") == 0);
101         assert_se(set_size(m) == 2);
102 }
103 
TEST(set_put_strdupv)104 TEST(set_put_strdupv) {
105         _cleanup_set_free_ Set *m = NULL;
106 
107         assert_se(set_put_strdupv(&m, STRV_MAKE("aaa", "aaa", "bbb", "bbb", "aaa")) == 2);
108         assert_se(set_put_strdupv(&m, STRV_MAKE("aaa", "aaa", "bbb", "bbb", "ccc")) == 1);
109         assert_se(set_size(m) == 3);
110 }
111 
TEST(set_ensure_allocated)112 TEST(set_ensure_allocated) {
113         _cleanup_set_free_ Set *m = NULL;
114 
115         assert_se(set_ensure_allocated(&m, &string_hash_ops) == 1);
116         assert_se(set_ensure_allocated(&m, &string_hash_ops) == 0);
117         assert_se(set_ensure_allocated(&m, NULL) == 0);
118         assert_se(set_size(m) == 0);
119 }
120 
TEST(set_copy)121 TEST(set_copy) {
122         Set *s, *copy;
123         char *key1, *key2, *key3, *key4;
124 
125         key1 = strdup("key1");
126         assert_se(key1);
127         key2 = strdup("key2");
128         assert_se(key2);
129         key3 = strdup("key3");
130         assert_se(key3);
131         key4 = strdup("key4");
132         assert_se(key4);
133 
134         s = set_new(&string_hash_ops);
135         assert_se(s);
136 
137         assert_se(set_put(s, key1) >= 0);
138         assert_se(set_put(s, key2) >= 0);
139         assert_se(set_put(s, key3) >= 0);
140         assert_se(set_put(s, key4) >= 0);
141 
142         copy = set_copy(s);
143         assert_se(copy);
144 
145         assert_se(set_equal(s, copy));
146 
147         set_free(s);
148         set_free_free(copy);
149 }
150 
TEST(set_ensure_put)151 TEST(set_ensure_put) {
152         _cleanup_set_free_ Set *m = NULL;
153 
154         assert_se(set_ensure_put(&m, &string_hash_ops, "a") == 1);
155         assert_se(set_ensure_put(&m, &string_hash_ops, "a") == 0);
156         assert_se(set_ensure_put(&m, NULL, "a") == 0);
157         assert_se(set_ensure_put(&m, &string_hash_ops, "b") == 1);
158         assert_se(set_ensure_put(&m, &string_hash_ops, "b") == 0);
159         assert_se(set_ensure_put(&m, &string_hash_ops, "a") == 0);
160         assert_se(set_size(m) == 2);
161 }
162 
TEST(set_ensure_consume)163 TEST(set_ensure_consume) {
164         _cleanup_set_free_ Set *m = NULL;
165         char *s, *t;
166 
167         assert_se(s = strdup("a"));
168         assert_se(set_ensure_consume(&m, &string_hash_ops_free, s) == 1);
169 
170         assert_se(t = strdup("a"));
171         assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 0);
172 
173         assert_se(t = strdup("a"));
174         assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 0);
175 
176         assert_se(t = strdup("b"));
177         assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 1);
178 
179         assert_se(t = strdup("b"));
180         assert_se(set_ensure_consume(&m, &string_hash_ops_free, t) == 0);
181 
182         assert_se(set_size(m) == 2);
183 }
184 
TEST(set_strjoin)185 TEST(set_strjoin) {
186         _cleanup_set_free_ Set *m = NULL;
187         _cleanup_free_ char *joined = NULL;
188 
189         /* Empty set */
190         assert_se(set_strjoin(m, NULL, false, &joined) >= 0);
191         assert_se(!joined);
192         assert_se(set_strjoin(m, "", false, &joined) >= 0);
193         assert_se(!joined);
194         assert_se(set_strjoin(m, " ", false, &joined) >= 0);
195         assert_se(!joined);
196         assert_se(set_strjoin(m, "xxx", false, &joined) >= 0);
197         assert_se(!joined);
198         assert_se(set_strjoin(m, NULL, true, &joined) >= 0);
199         assert_se(!joined);
200         assert_se(set_strjoin(m, "", true, &joined) >= 0);
201         assert_se(!joined);
202         assert_se(set_strjoin(m, " ", true, &joined) >= 0);
203         assert_se(!joined);
204         assert_se(set_strjoin(m, "xxx", true, &joined) >= 0);
205         assert_se(!joined);
206 
207         /* Single entry */
208         assert_se(set_put_strdup(&m, "aaa") == 1);
209         assert_se(set_strjoin(m, NULL, false, &joined) >= 0);
210         assert_se(streq(joined, "aaa"));
211         joined = mfree(joined);
212         assert_se(set_strjoin(m, "", false, &joined) >= 0);
213         assert_se(streq(joined, "aaa"));
214         joined = mfree(joined);
215         assert_se(set_strjoin(m, " ", false, &joined) >= 0);
216         assert_se(streq(joined, "aaa"));
217         joined = mfree(joined);
218         assert_se(set_strjoin(m, "xxx", false, &joined) >= 0);
219         assert_se(streq(joined, "aaa"));
220         joined = mfree(joined);
221         assert_se(set_strjoin(m, NULL, true, &joined) >= 0);
222         assert_se(streq(joined, "aaa"));
223         joined = mfree(joined);
224         assert_se(set_strjoin(m, "", true, &joined) >= 0);
225         assert_se(streq(joined, "aaa"));
226         joined = mfree(joined);
227         assert_se(set_strjoin(m, " ", true, &joined) >= 0);
228         assert_se(streq(joined, " aaa "));
229         joined = mfree(joined);
230         assert_se(set_strjoin(m, "xxx", true, &joined) >= 0);
231         assert_se(streq(joined, "xxxaaaxxx"));
232 
233         /* Two entries */
234         assert_se(set_put_strdup(&m, "bbb") == 1);
235         assert_se(set_put_strdup(&m, "aaa") == 0);
236         joined = mfree(joined);
237         assert_se(set_strjoin(m, NULL, false, &joined) >= 0);
238         assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa"));
239         joined = mfree(joined);
240         assert_se(set_strjoin(m, "", false, &joined) >= 0);
241         assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa"));
242         joined = mfree(joined);
243         assert_se(set_strjoin(m, " ", false, &joined) >= 0);
244         assert_se(STR_IN_SET(joined, "aaa bbb", "bbb aaa"));
245         joined = mfree(joined);
246         assert_se(set_strjoin(m, "xxx", false, &joined) >= 0);
247         assert_se(STR_IN_SET(joined, "aaaxxxbbb", "bbbxxxaaa"));
248         joined = mfree(joined);
249         assert_se(set_strjoin(m, NULL, true, &joined) >= 0);
250         assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa"));
251         joined = mfree(joined);
252         assert_se(set_strjoin(m, "", true, &joined) >= 0);
253         assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa"));
254         joined = mfree(joined);
255         assert_se(set_strjoin(m, " ", true, &joined) >= 0);
256         assert_se(STR_IN_SET(joined, " aaa bbb ", " bbb aaa "));
257         joined = mfree(joined);
258         assert_se(set_strjoin(m, "xxx", true, &joined) >= 0);
259         assert_se(STR_IN_SET(joined, "xxxaaaxxxbbbxxx", "xxxbbbxxxaaaxxx"));
260 }
261 
TEST(set_equal)262 TEST(set_equal) {
263         _cleanup_set_free_ Set *a = NULL, *b = NULL;
264         void *p;
265         int r;
266 
267         assert_se(a = set_new(NULL));
268         assert_se(b = set_new(NULL));
269 
270         assert_se(set_equal(a, a));
271         assert_se(set_equal(b, b));
272         assert_se(set_equal(a, b));
273         assert_se(set_equal(b, a));
274         assert_se(set_equal(NULL, a));
275         assert_se(set_equal(NULL, b));
276         assert_se(set_equal(a, NULL));
277         assert_se(set_equal(b, NULL));
278         assert_se(set_equal(NULL, NULL));
279 
280         for (unsigned i = 0; i < 333; i++) {
281                 p = INT32_TO_PTR(1 + (random_u32() & 0xFFFU));
282 
283                 r = set_put(a, p);
284                 assert_se(r >= 0 || r == -EEXIST);
285         }
286 
287         assert_se(set_put(a, INT32_TO_PTR(0x1000U)) >= 0);
288 
289         assert_se(set_size(a) >= 2);
290         assert_se(set_size(a) <= 334);
291 
292         assert_se(!set_equal(a, b));
293         assert_se(!set_equal(b, a));
294         assert_se(!set_equal(a, NULL));
295 
296         SET_FOREACH(p, a)
297                 assert_se(set_put(b, p) >= 0);
298 
299         assert_se(set_equal(a, b));
300         assert_se(set_equal(b, a));
301 
302         assert_se(set_remove(a, INT32_TO_PTR(0x1000U)) == INT32_TO_PTR(0x1000U));
303 
304         assert_se(!set_equal(a, b));
305         assert_se(!set_equal(b, a));
306 
307         assert_se(set_remove(b, INT32_TO_PTR(0x1000U)) == INT32_TO_PTR(0x1000U));
308 
309         assert_se(set_equal(a, b));
310         assert_se(set_equal(b, a));
311 
312         assert_se(set_put(b, INT32_TO_PTR(0x1001U)) >= 0);
313 
314         assert_se(!set_equal(a, b));
315         assert_se(!set_equal(b, a));
316 
317         assert_se(set_put(a, INT32_TO_PTR(0x1001U)) >= 0);
318 
319         assert_se(set_equal(a, b));
320         assert_se(set_equal(b, a));
321 
322         set_clear(a);
323 
324         assert_se(!set_equal(a, b));
325         assert_se(!set_equal(b, a));
326 
327         set_clear(b);
328 
329         assert_se(set_equal(a, b));
330         assert_se(set_equal(b, a));
331 }
332 
TEST(set_fnmatch)333 TEST(set_fnmatch) {
334         _cleanup_set_free_ Set *match = NULL, *nomatch = NULL;
335 
336         assert_se(set_put_strdup(&match, "aaa") >= 0);
337         assert_se(set_put_strdup(&match, "bbb*") >= 0);
338         assert_se(set_put_strdup(&match, "*ccc") >= 0);
339 
340         assert_se(set_put_strdup(&nomatch, "a*") >= 0);
341         assert_se(set_put_strdup(&nomatch, "bbb") >= 0);
342         assert_se(set_put_strdup(&nomatch, "ccc*") >= 0);
343 
344         assert_se(set_fnmatch(NULL, NULL, ""));
345         assert_se(set_fnmatch(NULL, NULL, "hoge"));
346 
347         assert_se(set_fnmatch(match, NULL, "aaa"));
348         assert_se(set_fnmatch(match, NULL, "bbb"));
349         assert_se(set_fnmatch(match, NULL, "bbbXXX"));
350         assert_se(set_fnmatch(match, NULL, "ccc"));
351         assert_se(set_fnmatch(match, NULL, "XXXccc"));
352         assert_se(!set_fnmatch(match, NULL, ""));
353         assert_se(!set_fnmatch(match, NULL, "aaaa"));
354         assert_se(!set_fnmatch(match, NULL, "XXbbb"));
355         assert_se(!set_fnmatch(match, NULL, "cccXX"));
356 
357         assert_se(set_fnmatch(NULL, nomatch, ""));
358         assert_se(set_fnmatch(NULL, nomatch, "Xa"));
359         assert_se(set_fnmatch(NULL, nomatch, "bbbb"));
360         assert_se(set_fnmatch(NULL, nomatch, "XXXccc"));
361         assert_se(!set_fnmatch(NULL, nomatch, "a"));
362         assert_se(!set_fnmatch(NULL, nomatch, "aXXXX"));
363         assert_se(!set_fnmatch(NULL, nomatch, "bbb"));
364         assert_se(!set_fnmatch(NULL, nomatch, "ccc"));
365         assert_se(!set_fnmatch(NULL, nomatch, "cccXXX"));
366 
367         assert_se(set_fnmatch(match, nomatch, "bbbbb"));
368         assert_se(set_fnmatch(match, nomatch, "XXccc"));
369         assert_se(!set_fnmatch(match, nomatch, ""));
370         assert_se(!set_fnmatch(match, nomatch, "a"));
371         assert_se(!set_fnmatch(match, nomatch, "aaa"));
372         assert_se(!set_fnmatch(match, nomatch, "b"));
373         assert_se(!set_fnmatch(match, nomatch, "bbb"));
374         assert_se(!set_fnmatch(match, nomatch, "ccc"));
375         assert_se(!set_fnmatch(match, nomatch, "ccccc"));
376         assert_se(!set_fnmatch(match, nomatch, "cccXX"));
377 }
378 
379 DEFINE_TEST_MAIN(LOG_INFO);
380