Code

Merged branch 'master' of git://git.tokkee.org/sysdb.
[sysdb.git] / t / core / object_test.c
index f5b7bf68a4cb5cddfb7c9cec1907b7a12f4a6d2b..e00d300177b4694a5fd2b6d90a1ee9d9a3e72c84 100644 (file)
@@ -52,30 +52,44 @@ obj_destroy_noop(sdb_object_t *obj)
        fail_unless(obj != NULL, "obj destroy function: received obj == NULL");
 } /* obj_destroy_noop */
 
-START_TEST(test_obj_create)
+struct noop {
+       sdb_object_t super;
+       int data;
+};
+static sdb_type_t noop_type = {
+       /* size = */ sizeof(struct noop),
+       /* init = */ obj_init_noop,
+       /* destroy = */ obj_destroy_noop,
+};
+
+static void *wrapped = (void *)0x42;
+
+static int destroy_wrapper_called = 0;
+static void
+wrapper_destroy(void *obj)
 {
-       struct noop {
-               sdb_object_t super;
-               int data;
-       };
-       sdb_type_t noop_type = {
-               /* size = */ sizeof(struct noop),
-               /* init = */ obj_init_noop,
-               /* destroy = */ obj_destroy_noop,
-       };
+       ++destroy_wrapper_called;
+       fail_unless(obj == wrapped,
+                       "wrapper_destroy received unexpected obj %p; expected: %p",
+                       obj, wrapped);
+} /* wrapper_destroy */
 
+START_TEST(test_obj_create)
+{
        sdb_object_t *obj;
+       sdb_type_t test_type = noop_type;
+
        const char *name = "test-object";
 
        init_noop_called = 0;
        init_noop_retval = 0;
        destroy_noop_called = 0;
-       obj = sdb_object_create(name, noop_type);
+       obj = sdb_object_create(name, test_type);
        fail_unless(obj != NULL,
                        "sdb_object_create() = NULL; expected: a new object");
-       fail_unless(obj->type.size == noop_type.size,
+       fail_unless(obj->type.size == test_type.size,
                        "after sdb_object_create(): type size mismatch; got: %zu; "
-                       "expected: %zu", obj->type.size, noop_type.size);
+                       "expected: %zu", obj->type.size, test_type.size);
        fail_unless(obj->ref_cnt == 1,
                        "after sdb_object_create(): obj->ref_cnt = %d; expected: 1",
                        obj->ref_cnt);
@@ -104,7 +118,7 @@ START_TEST(test_obj_create)
        init_noop_called = 0;
        init_noop_retval = -1;
        destroy_noop_called = 0;
-       obj = sdb_object_create(name, noop_type);
+       obj = sdb_object_create(name, test_type);
        fail_unless(obj == NULL,
                        "sdb_object_create() = %p; expected NULL (init returned -1)",
                        obj);
@@ -114,11 +128,11 @@ START_TEST(test_obj_create)
                        "sdb_object_create() did not call object's destroy function "
                        "after init failure");
 
-       noop_type.size = 1;
+       test_type.size = 1;
        init_noop_called = 0;
        init_noop_retval = 0;
        destroy_noop_called = 0;
-       obj = sdb_object_create(name, noop_type);
+       obj = sdb_object_create(name, test_type);
        fail_unless(obj == NULL,
                        "sdb_object_create() = %p; expected NULL (type's size too small)",
                        obj);
@@ -129,22 +143,157 @@ START_TEST(test_obj_create)
                        "sdb_object_create() called object's destroy function "
                        "when size was too small");
 
-       noop_type.size = sizeof(struct noop);
+       test_type.size = sizeof(struct noop);
        init_noop_retval = 0;
-       noop_type.init = NULL;
-       obj = sdb_object_create(name, noop_type);
+       test_type.init = NULL;
+       obj = sdb_object_create(name, test_type);
        fail_unless(obj != NULL,
                        "sdb_object_create() fails without init callback");
        sdb_object_deref(obj);
 
-       noop_type.destroy = NULL;
-       obj = sdb_object_create(name, noop_type);
+       test_type.destroy = NULL;
+       obj = sdb_object_create(name, test_type);
        fail_unless(obj != NULL,
                        "sdb_object_create() fails without destroy callback");
        sdb_object_deref(obj);
 }
 END_TEST
 
+START_TEST(test_obj_wrapper)
+{
+       sdb_object_t *obj;
+       const char *name = "wrapped-object";
+
+       destroy_wrapper_called = 0;
+       obj = sdb_object_create_wrapper(name, wrapped, wrapper_destroy);
+       fail_unless(obj != NULL,
+                       "sdb_object_create_wrapper() = NULL; expected: wrapper object");
+       fail_unless(obj->ref_cnt == 1,
+                       "after sdb_object_create_wrapper(); obj->ref_cnt = %d; "
+                       "expected: 1", obj->ref_cnt);
+       fail_unless(!strcmp(obj->name, name),
+                       "after sdb_object_create_wrapper(); obj->name = %s; expected: %s",
+                       obj->name, name);
+       fail_unless(obj->name != name,
+                       "sdb_object_create_wrapper() did not copy object name");
+       fail_unless(SDB_OBJ_WRAPPER(obj)->data == wrapped,
+                       "wrapped object wraps unexpected data %p; expected: %p",
+                       SDB_OBJ_WRAPPER(obj)->data, wrapped);
+
+       fail_unless(destroy_wrapper_called == 0,
+                       "sdb_object_create_wrapper() called object's destructor");
+
+       sdb_object_deref(obj);
+       fail_unless(destroy_wrapper_called == 1,
+                       "sdb_object_deref() did not call wrapped object's destructor");
+}
+END_TEST
+
+START_TEST(test_obj_ref)
+{
+       sdb_object_t *obj;
+       sdb_type_t test_type = noop_type;
+
+       init_noop_called = 0;
+       init_noop_retval = 0;
+       destroy_noop_called = 0;
+
+       obj = sdb_object_create("test-object", test_type);
+       fail_unless(obj != NULL,
+                       "sdb_object_create() = NULL; expected: valid object");
+
+       sdb_object_ref(obj);
+       fail_unless(obj->ref_cnt == 2,
+                       "after db_object_ref(): obj->ref_cnt = %d; expected: 2",
+                       obj->ref_cnt);
+
+       sdb_object_ref(obj);
+       fail_unless(obj->ref_cnt == 3,
+                       "after db_object_ref(): obj->ref_cnt = %d; expected: 3",
+                       obj->ref_cnt);
+
+       obj->ref_cnt = 42;
+       sdb_object_ref(obj);
+       fail_unless(obj->ref_cnt == 43,
+                       "after db_object_ref(): obj->ref_cnt = %d; expected: 43",
+                       obj->ref_cnt);
+
+       fail_unless(init_noop_called == 1,
+                       "after some sdb_object_ref(); object's init called %d times; "
+                       "expected: 1", init_noop_called);
+       fail_unless(destroy_noop_called == 0,
+                       "after some sdb_object_ref(); object's destroy called %d time%s; "
+                       "expected: 0", destroy_noop_called == 1 ? "" : "2",
+                       destroy_noop_called);
+
+       sdb_object_deref(obj);
+       fail_unless(obj->ref_cnt == 42,
+                       "after db_object_deref(): obj->ref_cnt = %d; expected: 42",
+                       obj->ref_cnt);
+
+       obj->ref_cnt = 23;
+       sdb_object_deref(obj);
+       fail_unless(obj->ref_cnt == 22,
+                       "after db_object_deref(): obj->ref_cnt = %d; expected: 22",
+                       obj->ref_cnt);
+
+       fail_unless(init_noop_called == 1,
+                       "after some sdb_object_{de,}ref(); object's init called %d times; "
+                       "expected: 1", init_noop_called);
+       fail_unless(destroy_noop_called == 0,
+                       "after some sdb_object_{de,}ref(); object's destroy called "
+                       "%d time%s; expected: 0", destroy_noop_called == 1 ? "" : "2",
+                       destroy_noop_called);
+
+       /* test_obj_create already checks the ref_cnt == 1 case */
+       obj->ref_cnt = 0;
+       sdb_object_deref(obj);
+       fail_unless(obj->ref_cnt <= 0,
+                       "after db_object_deref(): obj->ref_cnt = %d; expected: <= 0",
+                       obj->ref_cnt);
+
+       fail_unless(init_noop_called == 1,
+                       "after some sdb_object_{de,}ref(); object's init called %d times; "
+                       "expected: 1", init_noop_called);
+       fail_unless(destroy_noop_called == 1,
+                       "after some sdb_object_{de,}ref(); object's destroy called "
+                       "%d times; expected: 1", destroy_noop_called);
+
+       /* this should work */
+       sdb_object_deref(NULL);
+}
+END_TEST
+
+START_TEST(test_obj_cmp)
+{
+       sdb_object_t *obj1, *obj2, *obj3, *obj4;
+       int status;
+
+       obj1 = sdb_object_create("a", noop_type);
+       obj2 = sdb_object_create("b", noop_type);
+       obj3 = sdb_object_create("B", noop_type);
+       obj4 = sdb_object_create("c", noop_type);
+
+       status = sdb_object_cmp_by_name(obj1, obj2);
+       fail_unless(status == -1,
+                       "sdb_object_cmp_by_name('a', 'b') = %d; expected: -1", status);
+       status = sdb_object_cmp_by_name(obj2, obj3);
+       fail_unless(status == 0,
+                       "sdb_object_cmp_by_name('b', 'B') = %d; expected: 0", status);
+       status = sdb_object_cmp_by_name(obj4, obj3);
+       fail_unless(status == 1,
+                       "sdb_object_cmp_by_name('c', 'B') = %d; expected: 1", status);
+       status = sdb_object_cmp_by_name(obj1, obj1);
+       fail_unless(status == 0,
+                       "sdb_object_cmp_by_name('a', 'a') = %d; expected: 0", status);
+
+       sdb_object_deref(obj1);
+       sdb_object_deref(obj2);
+       sdb_object_deref(obj3);
+       sdb_object_deref(obj4);
+}
+END_TEST
+
 Suite *
 core_object_suite(void)
 {
@@ -153,6 +302,9 @@ core_object_suite(void)
 
        tc = tcase_create("core");
        tcase_add_test(tc, test_obj_create);
+       tcase_add_test(tc, test_obj_wrapper);
+       tcase_add_test(tc, test_obj_ref);
+       tcase_add_test(tc, test_obj_cmp);
        suite_add_tcase(s, tc);
 
        return s;