Code

85e95c3a8b121cf590f6eee1e0de55a70ed703da
[sysdb.git] / t / core / object_test.c
1 /*
2  * SysDB - t/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 #include "core/object.h"
29 #include "libsysdb_test.h"
31 #include <check.h>
33 /*
34  * private data types
35  */
37 static int init_noop_called = 0;
38 static int init_noop_retval = 0;
39 static int
40 obj_init_noop(sdb_object_t *obj, va_list __attribute__((unused)) ap)
41 {
42         ++init_noop_called;
43         fail_unless(obj != NULL, "obj init function: received obj == NULL");
44         return init_noop_retval;
45 } /* obj_init_noop */
47 static int destroy_noop_called = 0;
48 static void
49 obj_destroy_noop(sdb_object_t *obj)
50 {
51         ++destroy_noop_called;
52         fail_unless(obj != NULL, "obj destroy function: received obj == NULL");
53 } /* obj_destroy_noop */
55 struct noop {
56         sdb_object_t super;
57         int data;
58 };
59 static sdb_type_t noop_type = {
60         /* size = */ sizeof(struct noop),
61         /* init = */ obj_init_noop,
62         /* destroy = */ obj_destroy_noop,
63 };
65 static void *wrapped = (void *)0x42;
67 static int destroy_wrapper_called = 0;
68 static void
69 wrapper_destroy(void *obj)
70 {
71         ++destroy_wrapper_called;
72         fail_unless(obj == wrapped,
73                         "wrapper_destroy received unexpected obj %p; expected: %p",
74                         obj, wrapped);
75 } /* wrapper_destroy */
77 START_TEST(test_obj_create)
78 {
79         sdb_object_t *obj;
80         sdb_type_t test_type = noop_type;
82         const char *name = "test-object";
84         init_noop_called = 0;
85         init_noop_retval = 0;
86         destroy_noop_called = 0;
87         obj = sdb_object_create(name, test_type);
88         fail_unless(obj != NULL,
89                         "sdb_object_create() = NULL; expected: a new object");
90         fail_unless(obj->type.size == test_type.size,
91                         "after sdb_object_create(): type size mismatch; got: %zu; "
92                         "expected: %zu", obj->type.size, test_type.size);
93         fail_unless(obj->type.init == obj_init_noop,
94                         "after sdb_object_create(): type init = %p; exptected: %p",
95                         obj->type.init, obj_init_noop);
96         fail_unless(obj->type.destroy == obj_destroy_noop,
97                         "after sdb_object_create(): type destroy = %p; exptected: %p",
98                         obj->type.destroy, obj_destroy_noop);
99         fail_unless(obj->ref_cnt == 1,
100                         "after sdb_object_create(): obj->ref_cnt = %d; expected: 1",
101                         obj->ref_cnt);
102         fail_unless(!strcmp(obj->name, "test-object"),
103                         "after sdb_object_create(): obj->name = '%s'; expected: '%s'",
104                         obj->name, name);
105         fail_unless(obj->name != name,
106                         "after sdb_object_create(): obj->name was not strdup()'ed");
108         fail_unless(init_noop_called == 1,
109                         "sdb_object_create() did not call object's init function");
110         fail_unless(destroy_noop_called == 0,
111                         "sdb_object_create() called object's destroy function");
112         fail_unless(((struct noop *)obj)->data == 0,
113                         "sdb_object_create() did not initialize data to zero");
115         sdb_object_deref(obj);
116         fail_unless(destroy_noop_called == 1,
117                         "sdb_object_deref() did not call object's destroy function");
119         init_noop_called = 0;
120         init_noop_retval = -1;
121         destroy_noop_called = 0;
122         obj = sdb_object_create(name, test_type);
123         fail_unless(obj == NULL,
124                         "sdb_object_create() = %p; expected NULL (init returned -1)",
125                         obj);
126         fail_unless(init_noop_called == 1,
127                         "sdb_object_create() did not call object's init function");
128         fail_unless(destroy_noop_called == 1,
129                         "sdb_object_create() did not call object's destroy function "
130                         "after init failure");
132         test_type.size = 1;
133         init_noop_called = 0;
134         init_noop_retval = 0;
135         destroy_noop_called = 0;
136         obj = sdb_object_create(name, test_type);
137         fail_unless(obj == NULL,
138                         "sdb_object_create() = %p; expected NULL (type's size too small)",
139                         obj);
140         fail_unless(init_noop_called == 0,
141                         "sdb_object_create() called object's init function "
142                         "when size was too small");
143         fail_unless(destroy_noop_called == 0,
144                         "sdb_object_create() called object's destroy function "
145                         "when size was too small");
147         test_type.size = sizeof(struct noop);
148         init_noop_retval = 0;
149         test_type.init = NULL;
150         obj = sdb_object_create(name, test_type);
151         fail_unless(obj != NULL,
152                         "sdb_object_create() fails without init callback");
153         sdb_object_deref(obj);
155         test_type.destroy = NULL;
156         obj = sdb_object_create(name, test_type);
157         fail_unless(obj != NULL,
158                         "sdb_object_create() fails without destroy callback");
159         sdb_object_deref(obj);
161         init_noop_called = 0;
162         obj = sdb_object_create_simple(name, sizeof(struct noop), NULL);
163         fail_unless(obj != NULL,
164                         "sdb_object_create_simple() = NULL; expected: <obj>");
165         fail_unless(obj->type.size == sizeof(struct noop),
166                         "sdb_object_create_simple() created object of size %zu; "
167                         "expected: %zu", obj->type.size, sizeof(struct noop));
168         fail_unless(obj->type.init == NULL,
169                         "sdb_object_create_simple() did not set init=NULL");
170         fail_unless(obj->type.destroy == NULL,
171                         "sdb_object_create_simple() did not set destroy=NULL");
172         fail_unless(init_noop_called == 0,
173                         "sdb_object_create_simple() unexpectedly called noop's init");
174         sdb_object_deref(obj);
176         obj = sdb_object_create_T(NULL, struct noop);
177         fail_unless(obj != NULL,
178                         "sdb_object_create_simple() = NULL; expected: <obj>");
179         fail_unless(obj->type.size == sizeof(struct noop),
180                         "sdb_object_create_simple() created object of size %zu; "
181                         "expected: %zu", obj->type.size, sizeof(struct noop));
182         fail_unless(obj->type.init == NULL,
183                         "sdb_object_create_simple() did not set init=NULL");
184         fail_unless(obj->type.destroy == NULL,
185                         "sdb_object_create_simple() did not set destroy=NULL");
186         fail_unless(init_noop_called == 0,
187                         "sdb_object_create_simple() unexpectedly called noop's init");
188         sdb_object_deref(obj);
190 END_TEST
192 START_TEST(test_obj_wrapper)
194         sdb_object_t *obj;
195         const char *name = "wrapped-object";
197         destroy_wrapper_called = 0;
198         obj = sdb_object_create_wrapper(name, wrapped, wrapper_destroy);
199         fail_unless(obj != NULL,
200                         "sdb_object_create_wrapper() = NULL; expected: wrapper object");
201         fail_unless(obj->ref_cnt == 1,
202                         "after sdb_object_create_wrapper(); obj->ref_cnt = %d; "
203                         "expected: 1", obj->ref_cnt);
204         fail_unless(!strcmp(obj->name, name),
205                         "after sdb_object_create_wrapper(); obj->name = %s; expected: %s",
206                         obj->name, name);
207         fail_unless(obj->name != name,
208                         "sdb_object_create_wrapper() did not copy object name");
209         fail_unless(SDB_OBJ_WRAPPER(obj)->data == wrapped,
210                         "wrapped object wraps unexpected data %p; expected: %p",
211                         SDB_OBJ_WRAPPER(obj)->data, wrapped);
213         fail_unless(destroy_wrapper_called == 0,
214                         "sdb_object_create_wrapper() called object's destructor");
216         sdb_object_deref(obj);
217         fail_unless(destroy_wrapper_called == 1,
218                         "sdb_object_deref() did not call wrapped object's destructor");
220 END_TEST
222 START_TEST(test_obj_ref)
224         sdb_object_t *obj;
225         sdb_type_t test_type = noop_type;
227         init_noop_called = 0;
228         init_noop_retval = 0;
229         destroy_noop_called = 0;
231         obj = sdb_object_create("test-object", test_type);
232         fail_unless(obj != NULL,
233                         "sdb_object_create() = NULL; expected: valid object");
235         sdb_object_ref(obj);
236         fail_unless(obj->ref_cnt == 2,
237                         "after db_object_ref(): obj->ref_cnt = %d; expected: 2",
238                         obj->ref_cnt);
240         sdb_object_ref(obj);
241         fail_unless(obj->ref_cnt == 3,
242                         "after db_object_ref(): obj->ref_cnt = %d; expected: 3",
243                         obj->ref_cnt);
245         obj->ref_cnt = 42;
246         sdb_object_ref(obj);
247         fail_unless(obj->ref_cnt == 43,
248                         "after db_object_ref(): obj->ref_cnt = %d; expected: 43",
249                         obj->ref_cnt);
251         fail_unless(init_noop_called == 1,
252                         "after some sdb_object_ref(); object's init called %d times; "
253                         "expected: 1", init_noop_called);
254         fail_unless(destroy_noop_called == 0,
255                         "after some sdb_object_ref(); object's destroy called %d time%s; "
256                         "expected: 0", destroy_noop_called == 1 ? "" : "2",
257                         destroy_noop_called);
259         sdb_object_deref(obj);
260         fail_unless(obj->ref_cnt == 42,
261                         "after db_object_deref(): obj->ref_cnt = %d; expected: 42",
262                         obj->ref_cnt);
264         obj->ref_cnt = 23;
265         sdb_object_deref(obj);
266         fail_unless(obj->ref_cnt == 22,
267                         "after db_object_deref(): obj->ref_cnt = %d; expected: 22",
268                         obj->ref_cnt);
270         fail_unless(init_noop_called == 1,
271                         "after some sdb_object_{de,}ref(); object's init called %d times; "
272                         "expected: 1", init_noop_called);
273         fail_unless(destroy_noop_called == 0,
274                         "after some sdb_object_{de,}ref(); object's destroy called "
275                         "%d time%s; expected: 0", destroy_noop_called == 1 ? "" : "2",
276                         destroy_noop_called);
278         /* test_obj_create already checks the ref_cnt == 1 case */
279         obj->ref_cnt = 0;
280         sdb_object_deref(obj);
281         fail_unless(init_noop_called == 1,
282                         "after some sdb_object_{de,}ref(); object's init called %d times; "
283                         "expected: 1", init_noop_called);
284         fail_unless(destroy_noop_called == 1,
285                         "after some sdb_object_{de,}ref(); object's destroy called "
286                         "%d times; expected: 1", destroy_noop_called);
288         /* this should work */
289         sdb_object_deref(NULL);
291 END_TEST
293 START_TEST(test_obj_cmp)
295         sdb_object_t *obj1, *obj2, *obj3, *obj4;
296         int status;
298         obj1 = sdb_object_create("a", noop_type);
299         obj2 = sdb_object_create("b", noop_type);
300         obj3 = sdb_object_create("B", noop_type);
301         obj4 = sdb_object_create("c", noop_type);
303         status = sdb_object_cmp_by_name(obj1, obj2);
304         fail_unless(status == -1,
305                         "sdb_object_cmp_by_name('a', 'b') = %d; expected: -1", status);
306         status = sdb_object_cmp_by_name(obj2, obj3);
307         fail_unless(status == 0,
308                         "sdb_object_cmp_by_name('b', 'B') = %d; expected: 0", status);
309         status = sdb_object_cmp_by_name(obj4, obj3);
310         fail_unless(status == 1,
311                         "sdb_object_cmp_by_name('c', 'B') = %d; expected: 1", status);
312         status = sdb_object_cmp_by_name(obj1, obj1);
313         fail_unless(status == 0,
314                         "sdb_object_cmp_by_name('a', 'a') = %d; expected: 0", status);
316         sdb_object_deref(obj1);
317         sdb_object_deref(obj2);
318         sdb_object_deref(obj3);
319         sdb_object_deref(obj4);
321 END_TEST
323 Suite *
324 core_object_suite(void)
326         Suite *s = suite_create("core::object");
327         TCase *tc;
329         tc = tcase_create("core");
330         tcase_add_test(tc, test_obj_create);
331         tcase_add_test(tc, test_obj_wrapper);
332         tcase_add_test(tc, test_obj_ref);
333         tcase_add_test(tc, test_obj_cmp);
334         suite_add_tcase(s, tc);
336         return s;
337 } /* core_object_suite */
339 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */