From 73afd2f7e198df3a19ad7fbdfd0cc6dee88bdfcf Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sat, 7 Dec 2013 14:56:14 +0100 Subject: [PATCH] object_test: Added tests for wrapped object and memory management. --- t/core/object_test.c | 163 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 142 insertions(+), 21 deletions(-) diff --git a/t/core/object_test.c b/t/core/object_test.c index f5b7bf6..f39819c 100644 --- a/t/core/object_test.c +++ b/t/core/object_test.c @@ -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,127 @@ 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 + Suite * core_object_suite(void) { @@ -153,6 +272,8 @@ 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); suite_add_tcase(s, tc); return s; -- 2.30.2