Code

t/unit/: Create one test binary for each *_test.c file.
[sysdb.git] / t / unit / utils / llist_test.c
1 /*
2  * SysDB - t/unit/utils/llist_test.c
3  * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
28 #if HAVE_CONFIG_H
29 #       include "config.h"
30 #endif
32 #include "utils/llist.h"
33 #include "testutils.h"
35 #include <check.h>
37 /*
38  * private data types
39  */
41 static sdb_object_t golden_data[] = {
42         SDB_OBJECT_STATIC("abc"),
43         SDB_OBJECT_STATIC("bcd"),
44         SDB_OBJECT_STATIC("cde"),
45         SDB_OBJECT_STATIC("def"),
46         SDB_OBJECT_STATIC("efg"),
47         SDB_OBJECT_STATIC("fgh"),
48         SDB_OBJECT_STATIC("ghi")
49 };
51 static char *unused_names[] = {
52         "xyz",
53         "yza",
54         "zab"
55 };
57 static sdb_llist_t *list;
59 static void
60 setup(void)
61 {
62         list = sdb_llist_create();
63         fail_unless(list != NULL,
64                         "sdb_llist_create() = NULL; expected list object");
65 } /* setup */
67 static void
68 teardown(void)
69 {
70         sdb_llist_destroy(list);
71         list = NULL;
72 } /* teardown */
74 /* populate the list with the golden data in the specified order */
75 static void
76 populate(void)
77 {
78         size_t i;
79         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
80                 int check = sdb_llist_append(list, &golden_data[i]);
81                 fail_unless(check == 0,
82                                 "sdb_llist_append(%s) = %i; expected: 0",
83                                 golden_data[i].name, check);
84         }
85 } /* populate */
87 START_TEST(test_clone)
88 {
89         sdb_llist_t *clone;
90         size_t i;
92         populate();
94         clone = sdb_llist_clone(list);
95         fail_unless(clone != NULL,
96                         "sdb_llist_clone() = NULL; expected: cloned list object");
98         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
99                 fail_unless(golden_data[i].ref_cnt == 3,
100                                 "sdb_llist_clone() did not take ownership");
101         }
103         sdb_llist_destroy(clone);
105 END_TEST
107 START_TEST(test_destroy)
109         size_t i;
110         populate();
111         sdb_llist_destroy(list);
112         list = NULL;
114         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
115                 fail_unless(golden_data[i].ref_cnt == 1,
116                                 "sdb_llist_destroy() did not deref element %s",
117                                 golden_data[i].name);
118         }
120 END_TEST
122 START_TEST(test_clear)
124         size_t i;
125         populate();
126         sdb_llist_clear(list);
128         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
129                 fail_unless(golden_data[i].ref_cnt == 1,
130                                 "sdb_llist_clear() did not deref element %s",
131                                 golden_data[i].name);
132         }
134         i = sdb_llist_len(list);
135         fail_unless(i == 0,
136                         "sdb_llist_clear() left %zu elements in the list; "
137                         "expected: 0", i);
139 END_TEST
141 START_TEST(test_append)
143         size_t i;
145         fail_unless(sdb_llist_len(list) == 0,
146                         "sdb_llist_len(<empty list>) = %zu; expected: 0",
147                         sdb_llist_len(list));
149         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
150                 int check = sdb_llist_append(list, &golden_data[i]);
151                 fail_unless(check == 0,
152                                 "sdb_llist_append(%s) = %i; expected: 0",
153                                 golden_data[i].name, check);
154                 fail_unless(golden_data[i].ref_cnt == 2,
155                                 "sdb_llist_append(%s) did not take ownership",
156                                 golden_data[i].name);
157                 fail_unless(sdb_llist_len(list) == i + 1,
158                                 "sdb_llist_len(<empty list>) = %zu; expected: zu",
159                                 sdb_llist_len(list), i + 1);
160         }
162 END_TEST
164 START_TEST(test_insert)
166         size_t i;
167         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
168                 int check = sdb_llist_insert(list, &golden_data[i], 0);
169                 fail_unless(check == 0,
170                                 "sdb_llist_insert(%s, 0) = %i; expected: 0",
171                                 golden_data[i].name, check);
172                 fail_unless(golden_data[i].ref_cnt == 2,
173                                 "sdb_llist_insert(%s, 0) did not take ownership",
174                                 golden_data[i].name);
175         }
177 END_TEST
179 START_TEST(test_validate_insert)
181         size_t i;
182         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
183                 /* none of these operations will succeed
184                  * => 1 is invalid for each case */
185                 int check = sdb_llist_insert(list, &golden_data[i], 1);
186                 fail_unless(check == -1,
187                                 "sdb_llist_insert(%s, 1) = %i; expected: -1",
188                                 golden_data[i].name, check);
189                 fail_unless(golden_data[i].ref_cnt == 1,
190                                 "sdb_llist_insert(%s, 1) took ownership",
191                                 golden_data[i].name);
192         }
194 END_TEST
196 START_TEST(test_get)
198         size_t i;
199         populate();
200         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
201                 sdb_object_t *check = sdb_llist_get(list, i);
202                 fail_unless(check == &golden_data[i],
203                                 "sdb_llist_get() = %p; expected: %p",
204                                 check, &golden_data[i]);
205                 fail_unless(check->ref_cnt == 3,
206                                 "sdb_llist_get() didn't increment reference count; got: %i; "
207                                 "expected: 3", check->ref_cnt);
208                 sdb_object_deref(check);
209         }
211 END_TEST
213 START_TEST(test_remove_by_name)
215         /* "random" indexes */
216         int indexes[] = { 4, 5, 3, 6, 2, 0, 1 };
217         size_t i;
219         populate();
221         for (i = 0; i < SDB_STATIC_ARRAY_LEN(indexes); ++i) {
222                 sdb_object_t *check;
224                 fail_unless((size_t)indexes[i] < SDB_STATIC_ARRAY_LEN(golden_data),
225                                 "INTERNAL ERROR: invalid index %i", indexes[i]);
227                 check = sdb_llist_remove_by_name(list, golden_data[indexes[i]].name);
228                 fail_unless(check == &golden_data[indexes[i]],
229                                 "sdb_llist_remove_by_name() = %p; expected: %p",
230                                 check, &golden_data[indexes[i]]);
231                 fail_unless(check->ref_cnt == 2,
232                                 "sdb_llist_remove_by_name() returned unexpected reference "
233                                 "count; got: %i; expected: 2", check->ref_cnt);
235                 check = sdb_llist_remove_by_name(list, golden_data[indexes[i]].name);
236                 fail_unless(check == NULL,
237                                 "sdb_llist_remove_by_name() did not remove the element");
238         }
240 END_TEST
242 static int
243 dummy_lookup(const sdb_object_t __attribute__((unused)) *obj,
244                 const void __attribute__((unused)) *user_data)
246         return 0;
247 } /* dummy_lookup */
249 START_TEST(test_search)
251         size_t i;
252         populate();
253         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
254                 sdb_object_t *check = sdb_llist_search_by_name(list,
255                                 golden_data[i].name);
256                 fail_unless(check == &golden_data[i],
257                                 "sdb_llist_search_by_name(%s) = NULL; expected: %p",
258                                 golden_data[i].name, &golden_data[i]);
259         }
261         for (i = 0; i < SDB_STATIC_ARRAY_LEN(unused_names); ++i) {
262                 sdb_object_t *check = sdb_llist_search_by_name(list,
263                                 unused_names[i]);
264                 fail_unless(check == NULL,
265                                 "sdb_llist_search_by_name(%s) = %p; expected: NULL",
266                                 unused_names[i], check);
267         }
269         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
270                 /* dummy_lookup always return 0, thus, this will always return the
271                  * first element */
272                 sdb_object_t *check = sdb_llist_search(list, dummy_lookup, NULL);
273                 fail_unless(check == &golden_data[i],
274                                 "sdb_llist_search() = %p (%s); expected: %p (%s)",
275                                 check, check->name, &golden_data[i], golden_data[i].name);
277                 /* => remove the first element */
278                 check = sdb_llist_remove(list, dummy_lookup, NULL);
279                 fail_unless(check == &golden_data[i],
280                                 "sdb_llist_remove() = %p (%s); expected: %p (%s)",
281                                 check, check->name, &golden_data[i], golden_data[i].name);
282                 fail_unless(check->ref_cnt == 2,
283                                 "sdb_llist_remove() changed reference count; got: %i; "
284                                 "expected: 2", check->ref_cnt);
285         }
286         /* should now be empty */
287         fail_unless(sdb_llist_len(list) == 0,
288                         "Still have %i elements in the list; expected: 0",
289                         sdb_llist_len(list));
291 END_TEST
293 START_TEST(test_shift)
295         size_t i;
296         populate();
297         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
298                 sdb_object_t *check = sdb_llist_shift(list);
299                 fail_unless(check == &golden_data[i],
300                                 "sdb_llist_shift() = NULL; expected: %p",
301                                 &golden_data[i]);
302                 fail_unless(check->ref_cnt == 2,
303                                 "sdb_llist_shift() changed reference count; got: %i; "
304                                 "expected: 2", check->ref_cnt);
305         }
307         /* must be empty now */
308         fail_unless(sdb_llist_shift(list) == NULL,
309                         "sdb_llist_shift() returned value; expected: NULL");
311 END_TEST
313 START_TEST(test_iter)
315         sdb_llist_iter_t *iter;
316         size_t i;
318         populate();
320         iter = sdb_llist_get_iter(list);
321         fail_unless(iter != NULL,
322                         "sdb_llist_get_iter() did not return an iterator");
324         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
325                 sdb_object_t *check;
326                 fail_unless(sdb_llist_iter_has_next(iter),
327                                 "sdb_llist_iter_has_next() = FALSE; expected: TRUE");
328                 check = sdb_llist_iter_get_next(iter);
329                 fail_unless(check == &golden_data[i],
330                                 "sdb_llist_iter_get_next() = %p; expected: %p",
331                                 check, &golden_data[i]);
332         }
334         fail_unless(!sdb_llist_iter_has_next(iter),
335                         "sdb_llist_iter_has_next() = TRUE; expected: FALSE");
336         fail_unless(sdb_llist_iter_get_next(iter) == NULL,
337                         "sdb_llist_iter_get_next() returned value; expected: NULL");
338         sdb_llist_iter_destroy(iter);
340 END_TEST
342 START_TEST(test_iter_remove)
344         sdb_llist_iter_t *iter;
345         sdb_object_t *check;
346         size_t i;
348         populate();
350         iter = sdb_llist_get_iter(list);
351         fail_unless(iter != NULL,
352                         "sdb_llist_get_iter() did not return an iterator");
354         i = 0;
355         while (sdb_llist_iter_has_next(iter)) {
356                 check = sdb_llist_iter_get_next(iter);
357                 fail_unless(check == &golden_data[i],
358                                 "sdb_llist_iter_get_next() = %p; expected: %p",
359                                 check, &golden_data[i]);
361                 sdb_llist_iter_remove_current(iter);
362                 ++i;
363         }
364         sdb_llist_iter_destroy(iter);
366         fail_unless(i == (size_t)SDB_STATIC_ARRAY_LEN(golden_data),
367                         "iterated for %zu steps; expected: %i",
368                         i, SDB_STATIC_ARRAY_LEN(golden_data));
370         /* all elements should be removed */
371         check = sdb_llist_shift(list);
372         fail_unless(check == NULL,
373                         "sdb_llist_shift() = %p; expected: NULL", check);
375 END_TEST
377 TEST_MAIN("utils::llist")
379         TCase *tc = tcase_create("core");
380         tcase_add_checked_fixture(tc, setup, teardown);
381         tcase_add_test(tc, test_clone);
382         tcase_add_test(tc, test_destroy);
383         tcase_add_test(tc, test_clear);
384         tcase_add_test(tc, test_append);
385         tcase_add_test(tc, test_insert);
386         tcase_add_test(tc, test_validate_insert);
387         tcase_add_test(tc, test_get);
388         tcase_add_test(tc, test_remove_by_name);
389         tcase_add_test(tc, test_search);
390         tcase_add_test(tc, test_shift);
391         tcase_add_test(tc, test_iter);
392         tcase_add_test(tc, test_iter_remove);
393         ADD_TCASE(tc);
395 TEST_MAIN_END
397 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */