Code

t/unit/: Create one test binary for each *_test.c file.
[sysdb.git] / t / unit / core / object_test.c
1 /*
2  * SysDB - t/unit/core/object_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 "core/object.h"
33 #include "testutils.h"
35 #include <check.h>
37 /*
38  * private data types
39  */
41 static int init_noop_called = 0;
42 static int init_noop_retval = 0;
43 static int
44 obj_init_noop(sdb_object_t *obj, va_list __attribute__((unused)) ap)
45 {
46         ++init_noop_called;
47         fail_unless(obj != NULL, "obj init function: received obj == NULL");
48         return init_noop_retval;
49 } /* obj_init_noop */
51 static int destroy_noop_called = 0;
52 static void
53 obj_destroy_noop(sdb_object_t *obj)
54 {
55         ++destroy_noop_called;
56         fail_unless(obj != NULL, "obj destroy function: received obj == NULL");
57 } /* obj_destroy_noop */
59 struct noop {
60         sdb_object_t super;
61         int data;
62 };
63 static sdb_type_t noop_type = {
64         /* size = */ sizeof(struct noop),
65         /* init = */ obj_init_noop,
66         /* destroy = */ obj_destroy_noop,
67 };
69 static void *wrapped = (void *)0x42;
71 static int destroy_wrapper_called = 0;
72 static void
73 wrapper_destroy(void *obj)
74 {
75         ++destroy_wrapper_called;
76         fail_unless(obj == wrapped,
77                         "wrapper_destroy received unexpected obj %p; expected: %p",
78                         obj, wrapped);
79 } /* wrapper_destroy */
81 START_TEST(test_obj_create)
82 {
83         sdb_object_t *obj;
84         sdb_type_t test_type = noop_type;
86         const char *name = "test-object";
88         init_noop_called = 0;
89         init_noop_retval = 0;
90         destroy_noop_called = 0;
91         obj = sdb_object_create(name, test_type);
92         fail_unless(obj != NULL,
93                         "sdb_object_create() = NULL; expected: a new object");
94         fail_unless(obj->type.size == test_type.size,
95                         "after sdb_object_create(): type size mismatch; got: %zu; "
96                         "expected: %zu", obj->type.size, test_type.size);
97         fail_unless(obj->type.init == obj_init_noop,
98                         "after sdb_object_create(): type init = %p; exptected: %p",
99                         obj->type.init, obj_init_noop);
100         fail_unless(obj->type.destroy == obj_destroy_noop,
101                         "after sdb_object_create(): type destroy = %p; exptected: %p",
102                         obj->type.destroy, obj_destroy_noop);
103         fail_unless(obj->ref_cnt == 1,
104                         "after sdb_object_create(): obj->ref_cnt = %d; expected: 1",
105                         obj->ref_cnt);
106         fail_unless(!strcmp(obj->name, "test-object"),
107                         "after sdb_object_create(): obj->name = '%s'; expected: '%s'",
108                         obj->name, name);
109         fail_unless(obj->name != name,
110                         "after sdb_object_create(): obj->name was not strdup()'ed");
112         fail_unless(init_noop_called == 1,
113                         "sdb_object_create() did not call object's init function");
114         fail_unless(destroy_noop_called == 0,
115                         "sdb_object_create() called object's destroy function");
116         fail_unless(((struct noop *)obj)->data == 0,
117                         "sdb_object_create() did not initialize data to zero");
119         sdb_object_deref(obj);
120         fail_unless(destroy_noop_called == 1,
121                         "sdb_object_deref() did not call object's destroy function");
123         init_noop_called = 0;
124         init_noop_retval = -1;
125         destroy_noop_called = 0;
126         obj = sdb_object_create(name, test_type);
127         fail_unless(obj == NULL,
128                         "sdb_object_create() = %p; expected NULL (init returned -1)",
129                         obj);
130         fail_unless(init_noop_called == 1,
131                         "sdb_object_create() did not call object's init function");
132         fail_unless(destroy_noop_called == 1,
133                         "sdb_object_create() did not call object's destroy function "
134                         "after init failure");
136         test_type.size = 1;
137         init_noop_called = 0;
138         init_noop_retval = 0;
139         destroy_noop_called = 0;
140         obj = sdb_object_create(name, test_type);
141         fail_unless(obj == NULL,
142                         "sdb_object_create() = %p; expected NULL (type's size too small)",
143                         obj);
144         fail_unless(init_noop_called == 0,
145                         "sdb_object_create() called object's init function "
146                         "when size was too small");
147         fail_unless(destroy_noop_called == 0,
148                         "sdb_object_create() called object's destroy function "
149                         "when size was too small");
151         test_type.size = sizeof(struct noop);
152         init_noop_retval = 0;
153         test_type.init = NULL;
154         obj = sdb_object_create(name, test_type);
155         fail_unless(obj != NULL,
156                         "sdb_object_create() fails without init callback");
157         sdb_object_deref(obj);
159         test_type.destroy = NULL;
160         obj = sdb_object_create(name, test_type);
161         fail_unless(obj != NULL,
162                         "sdb_object_create() fails without destroy callback");
163         sdb_object_deref(obj);
165         init_noop_called = 0;
166         obj = sdb_object_create_simple(name, sizeof(struct noop), NULL);
167         fail_unless(obj != NULL,
168                         "sdb_object_create_simple() = NULL; expected: <obj>");
169         fail_unless(obj->type.size == sizeof(struct noop),
170                         "sdb_object_create_simple() created object of size %zu; "
171                         "expected: %zu", obj->type.size, sizeof(struct noop));
172         fail_unless(obj->type.init == NULL,
173                         "sdb_object_create_simple() did not set init=NULL");
174         fail_unless(obj->type.destroy == NULL,
175                         "sdb_object_create_simple() did not set destroy=NULL");
176         fail_unless(init_noop_called == 0,
177                         "sdb_object_create_simple() unexpectedly called noop's init");
178         sdb_object_deref(obj);
180         obj = sdb_object_create_T(NULL, struct noop);
181         fail_unless(obj != NULL,
182                         "sdb_object_create_simple() = NULL; expected: <obj>");
183         fail_unless(obj->type.size == sizeof(struct noop),
184                         "sdb_object_create_simple() created object of size %zu; "
185                         "expected: %zu", obj->type.size, sizeof(struct noop));
186         fail_unless(obj->type.init == NULL,
187                         "sdb_object_create_simple() did not set init=NULL");
188         fail_unless(obj->type.destroy == NULL,
189                         "sdb_object_create_simple() did not set destroy=NULL");
190         fail_unless(init_noop_called == 0,
191                         "sdb_object_create_simple() unexpectedly called noop's init");
192         sdb_object_deref(obj);
194 END_TEST
196 START_TEST(test_obj_wrapper)
198         sdb_object_t *obj;
199         const char *name = "wrapped-object";
201         destroy_wrapper_called = 0;
202         obj = sdb_object_create_wrapper(name, wrapped, wrapper_destroy);
203         fail_unless(obj != NULL,
204                         "sdb_object_create_wrapper() = NULL; expected: wrapper object");
205         fail_unless(obj->ref_cnt == 1,
206                         "after sdb_object_create_wrapper(); obj->ref_cnt = %d; "
207                         "expected: 1", obj->ref_cnt);
208         fail_unless(!strcmp(obj->name, name),
209                         "after sdb_object_create_wrapper(); obj->name = %s; expected: %s",
210                         obj->name, name);
211         fail_unless(obj->name != name,
212                         "sdb_object_create_wrapper() did not copy object name");
213         fail_unless(SDB_OBJ_WRAPPER(obj)->data == wrapped,
214                         "wrapped object wraps unexpected data %p; expected: %p",
215                         SDB_OBJ_WRAPPER(obj)->data, wrapped);
217         fail_unless(destroy_wrapper_called == 0,
218                         "sdb_object_create_wrapper() called object's destructor");
220         sdb_object_deref(obj);
221         fail_unless(destroy_wrapper_called == 1,
222                         "sdb_object_deref() did not call wrapped object's destructor");
224 END_TEST
226 START_TEST(test_obj_ref)
228         sdb_object_t *obj;
229         sdb_type_t test_type = noop_type;
231         init_noop_called = 0;
232         init_noop_retval = 0;
233         destroy_noop_called = 0;
235         obj = sdb_object_create("test-object", test_type);
236         fail_unless(obj != NULL,
237                         "sdb_object_create() = NULL; expected: valid object");
239         sdb_object_ref(obj);
240         fail_unless(obj->ref_cnt == 2,
241                         "after db_object_ref(): obj->ref_cnt = %d; expected: 2",
242                         obj->ref_cnt);
244         sdb_object_ref(obj);
245         fail_unless(obj->ref_cnt == 3,
246                         "after db_object_ref(): obj->ref_cnt = %d; expected: 3",
247                         obj->ref_cnt);
249         obj->ref_cnt = 42;
250         sdb_object_ref(obj);
251         fail_unless(obj->ref_cnt == 43,
252                         "after db_object_ref(): obj->ref_cnt = %d; expected: 43",
253                         obj->ref_cnt);
255         fail_unless(init_noop_called == 1,
256                         "after some sdb_object_ref(); object's init called %d times; "
257                         "expected: 1", init_noop_called);
258         fail_unless(destroy_noop_called == 0,
259                         "after some sdb_object_ref(); object's destroy called %d time%s; "
260                         "expected: 0", destroy_noop_called == 1 ? "" : "2",
261                         destroy_noop_called);
263         sdb_object_deref(obj);
264         fail_unless(obj->ref_cnt == 42,
265                         "after db_object_deref(): obj->ref_cnt = %d; expected: 42",
266                         obj->ref_cnt);
268         obj->ref_cnt = 23;
269         sdb_object_deref(obj);
270         fail_unless(obj->ref_cnt == 22,
271                         "after db_object_deref(): obj->ref_cnt = %d; expected: 22",
272                         obj->ref_cnt);
274         fail_unless(init_noop_called == 1,
275                         "after some sdb_object_{de,}ref(); object's init called %d times; "
276                         "expected: 1", init_noop_called);
277         fail_unless(destroy_noop_called == 0,
278                         "after some sdb_object_{de,}ref(); object's destroy called "
279                         "%d time%s; expected: 0", destroy_noop_called == 1 ? "" : "2",
280                         destroy_noop_called);
282         obj->ref_cnt = 1;
283         sdb_object_deref(obj);
284         fail_unless(init_noop_called == 1,
285                         "after some sdb_object_{de,}ref(); object's init called %d times; "
286                         "expected: 1", init_noop_called);
287         fail_unless(destroy_noop_called == 1,
288                         "after some sdb_object_{de,}ref(); object's destroy called "
289                         "%d times; expected: 1", destroy_noop_called);
291         /* this should work */
292         sdb_object_deref(NULL);
294 END_TEST
296 START_TEST(test_obj_cmp)
298         sdb_object_t *obj1, *obj2, *obj3, *obj4;
299         int status;
301         obj1 = sdb_object_create("a", noop_type);
302         obj2 = sdb_object_create("b", noop_type);
303         obj3 = sdb_object_create("B", noop_type);
304         obj4 = sdb_object_create("c", noop_type);
306         status = sdb_object_cmp_by_name(obj1, obj2);
307         fail_unless(status == -1,
308                         "sdb_object_cmp_by_name('a', 'b') = %d; expected: -1", status);
309         status = sdb_object_cmp_by_name(obj2, obj3);
310         fail_unless(status == 0,
311                         "sdb_object_cmp_by_name('b', 'B') = %d; expected: 0", status);
312         status = sdb_object_cmp_by_name(obj4, obj3);
313         fail_unless(status == 1,
314                         "sdb_object_cmp_by_name('c', 'B') = %d; expected: 1", status);
315         status = sdb_object_cmp_by_name(obj1, obj1);
316         fail_unless(status == 0,
317                         "sdb_object_cmp_by_name('a', 'a') = %d; expected: 0", status);
319         sdb_object_deref(obj1);
320         sdb_object_deref(obj2);
321         sdb_object_deref(obj3);
322         sdb_object_deref(obj4);
324 END_TEST
326 TEST_MAIN("core::object")
328         TCase *tc = tcase_create("core");
329         tcase_add_test(tc, test_obj_create);
330         tcase_add_test(tc, test_obj_wrapper);
331         tcase_add_test(tc, test_obj_ref);
332         tcase_add_test(tc, test_obj_cmp);
333         ADD_TCASE(tc);
335 TEST_MAIN_END
337 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */