Code

Merged branch 'master' of git://git.tokkee.org/sysdb.
authorSebastian Harl <sh@tokkee.org>
Sun, 1 Dec 2013 16:34:48 +0000 (17:34 +0100)
committerSebastian Harl <sh@tokkee.org>
Sun, 1 Dec 2013 16:34:48 +0000 (17:34 +0100)
Conflicts:
t/Makefile.am
t/libsysdb_test.c
t/libsysdb_test.h

.gitignore
src/core/object.c
src/include/core/object.h
t/Makefile.am
t/core/object_test.c [new file with mode: 0644]
t/libsysdb_test.c
t/libsysdb_test.h

index 943a4cab34e88489b1556ff99ec694410290a0ac..0318b30ed8338665792dceea67fe99b7a00bb20a 100644 (file)
@@ -44,4 +44,5 @@ sysdb.h
 # unit testing output
 t/libsysdb_test
 t/libsysdb_net_test
-
+t/*.log
+t/*.trs
index 0205ed588f1e58a8afd727a99443c8037add9604..43bb22a8fbf83ee39cb781beab8e34426f9505e9 100644 (file)
@@ -85,6 +85,7 @@ sdb_object_vcreate(const char *name, sdb_type_t type, va_list ap)
        if (! obj)
                return NULL;
        memset(obj, 0, type.size);
+       obj->type = type;
 
        if (name) {
                obj->name = strdup(name);
@@ -103,7 +104,6 @@ sdb_object_vcreate(const char *name, sdb_type_t type, va_list ap)
                }
        }
 
-       obj->type = type;
        obj->ref_cnt = 1;
        return obj;
 } /* sdb_object_vcreate */
index 3c00fb51abe807d00799d931278e2d5dddc8ffd6..9169c441383b292803a67efc35e91147528aa1e2 100644 (file)
@@ -78,7 +78,9 @@ typedef struct {
  *
  * The init function will be called with the remaining arguments passed to
  * sdb_object_create. If the init function fails (returns a non-zero value),
- * the object will be destructed and destroyed.
+ * the object will be destructed and destroyed. In this case, the 'destroy'
+ * callback may be called on objects that were only half-way initialized. The
+ * callback has to handle that case correctly.
  *
  * The reference count of the new object will be 1.
  *
index 1e4419dd7fcf053fae573e60278ce82520397ece..c31ac502de3f22757eb4d9a908934500be2219be 100644 (file)
@@ -6,6 +6,7 @@ check_PROGRAMS = libsysdb_test libsysdb_net_test
 
 libsysdb_test_SOURCES = \
                libsysdb_test.c libsysdb_test.h \
+               core/object_test.c \
                utils/channel_test.c \
                utils/dbi_test.c \
                utils/llist_test.c \
diff --git a/t/core/object_test.c b/t/core/object_test.c
new file mode 100644 (file)
index 0000000..f5b7bf6
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * SysDB - t/core/object_test.c
+ * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core/object.h"
+#include "libsysdb_test.h"
+
+#include <check.h>
+
+/*
+ * private data types
+ */
+
+static int init_noop_called = 0;
+static int init_noop_retval = 0;
+static int
+obj_init_noop(sdb_object_t *obj, va_list __attribute__((unused)) ap)
+{
+       ++init_noop_called;
+       fail_unless(obj != NULL, "obj init function: received obj == NULL");
+       return init_noop_retval;
+} /* obj_init_noop */
+
+static int destroy_noop_called = 0;
+static void
+obj_destroy_noop(sdb_object_t *obj)
+{
+       ++destroy_noop_called;
+       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;
+       };
+       sdb_type_t noop_type = {
+               /* size = */ sizeof(struct noop),
+               /* init = */ obj_init_noop,
+               /* destroy = */ obj_destroy_noop,
+       };
+
+       sdb_object_t *obj;
+       const char *name = "test-object";
+
+       init_noop_called = 0;
+       init_noop_retval = 0;
+       destroy_noop_called = 0;
+       obj = sdb_object_create(name, noop_type);
+       fail_unless(obj != NULL,
+                       "sdb_object_create() = NULL; expected: a new object");
+       fail_unless(obj->type.size == noop_type.size,
+                       "after sdb_object_create(): type size mismatch; got: %zu; "
+                       "expected: %zu", obj->type.size, noop_type.size);
+       fail_unless(obj->ref_cnt == 1,
+                       "after sdb_object_create(): obj->ref_cnt = %d; expected: 1",
+                       obj->ref_cnt);
+       fail_unless(!strcmp(obj->name, "test-object"),
+                       "after sdb_object_create(): obj->name = '%s'; expected: '%s'",
+                       obj->name, name);
+       fail_unless(obj->name != name,
+                       "after sdb_object_create(): obj->name was not strdup()'ed");
+
+       fail_unless(init_noop_called == 1,
+                       "sdb_object_create() did not call object's init function");
+       fail_unless(destroy_noop_called == 0,
+                       "sdb_object_create() called object's destroy function");
+       fail_unless(((struct noop *)obj)->data == 0,
+                       "sdb_object_create() did not initialize data to zero");
+
+       sdb_object_deref(obj);
+       /* the memory address at 'obj' is no longer valid but usually this check
+        * should still work */
+       fail_unless(obj->ref_cnt == 0,
+                       "after sdb_object_deref(): obj->ref_cnt = %d; expected: 0",
+                       obj->ref_cnt);
+       fail_unless(destroy_noop_called == 1,
+                       "sdb_object_deref() did not call object's destroy function");
+
+       init_noop_called = 0;
+       init_noop_retval = -1;
+       destroy_noop_called = 0;
+       obj = sdb_object_create(name, noop_type);
+       fail_unless(obj == NULL,
+                       "sdb_object_create() = %p; expected NULL (init returned -1)",
+                       obj);
+       fail_unless(init_noop_called == 1,
+                       "sdb_object_create() did not call object's init function");
+       fail_unless(destroy_noop_called == 1,
+                       "sdb_object_create() did not call object's destroy function "
+                       "after init failure");
+
+       noop_type.size = 1;
+       init_noop_called = 0;
+       init_noop_retval = 0;
+       destroy_noop_called = 0;
+       obj = sdb_object_create(name, noop_type);
+       fail_unless(obj == NULL,
+                       "sdb_object_create() = %p; expected NULL (type's size too small)",
+                       obj);
+       fail_unless(init_noop_called == 0,
+                       "sdb_object_create() called object's init function "
+                       "when size was too small");
+       fail_unless(destroy_noop_called == 0,
+                       "sdb_object_create() called object's destroy function "
+                       "when size was too small");
+
+       noop_type.size = sizeof(struct noop);
+       init_noop_retval = 0;
+       noop_type.init = NULL;
+       obj = sdb_object_create(name, noop_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);
+       fail_unless(obj != NULL,
+                       "sdb_object_create() fails without destroy callback");
+       sdb_object_deref(obj);
+}
+END_TEST
+
+Suite *
+core_object_suite(void)
+{
+       Suite *s = suite_create("core::object");
+       TCase *tc;
+
+       tc = tcase_create("core");
+       tcase_add_test(tc, test_obj_create);
+       suite_add_tcase(s, tc);
+
+       return s;
+} /* core_object_suite */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
index 7ce41247c679a8b9a2f636d5e9def467d8c1e311..91909b8448bd2ed7562af9a65055075b734b8e6f 100644 (file)
@@ -37,6 +37,7 @@ main(void)
        size_t i;
 
        suite_creator_t creators[] = {
+               { core_object_suite, NULL },
                { util_channel_suite, NULL },
                { util_dbi_suite, NULL },
                { util_llist_suite, NULL },
index da57246fe8f7e5fad93db503dea004b26fc5baf0..eadeca5d06716d4f29a5e466913ea36f292db0d7 100644 (file)
@@ -59,6 +59,10 @@ typedef struct {
  * test suites
  */
 
+/* t/core/object_test */
+Suite *
+core_object_suite(void);
+
 /* t/utils/channel_test */
 Suite *
 util_channel_suite(void);