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