Add unit tests for serialization 07/141207/23
authorKonrad Kuchciak <k.kuchciak@samsung.com>
Thu, 10 Aug 2017 21:48:24 +0000 (23:48 +0200)
committerKrzysztof Opasiak <k.opasiak@samsung.com>
Thu, 10 Aug 2017 22:03:49 +0000 (00:03 +0200)
Change-Id: I7a3a22f808b9064ab85bfa1742a0e414539a8758
Signed-off-by: Konrad Kuchciak <k.kuchciak@samsung.com>
[Put actual test func into helper, remove copy-paste code]
Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
Makefile.am
src/event_types/decision_made_event.c
src/event_types/resource_violation_event.c
src/event_types/service_failed_event.c
src/event_types/system_booted_event.c
tests/unit/decision_made_event_tests.c [new file with mode: 0644]
tests/unit/helpers.c
tests/unit/helpers.h
tests/unit/resource_violation_event_tests.c [new file with mode: 0644]
tests/unit/service_failed_event_tests.c [new file with mode: 0644]
tests/unit/system_booted_event_tests.c [new file with mode: 0644]

index feb9134cc97e0ed871516d4eaa559c4cb3749f4b..a05c48c394d948c1cf43b468318824d3eb5ccc4c 100644 (file)
@@ -137,6 +137,10 @@ test_CFLAGS = -I${top_srcdir}/src/util \
 
 test_SOURCES = \
     tests/unit/ejdb_tests.c \
+    tests/unit/decision_made_event_tests.c \
+    tests/unit/resource_violation_event_tests.c \
+    tests/unit/service_failed_event_tests.c \
+    tests/unit/system_booted_event_tests.c \
     tests/unit/faultd_object_tests.c \
     tests/unit/runner.c \
     tests/unit/helpers.c \
@@ -148,7 +152,11 @@ test_SOURCES = \
     src/util/systemd_dbus.c \
     src/util/log.c \
     src/util/common.c \
-    src/database/ejdb.c
+    src/database/ejdb.c \
+    src/event_types/decision_made_event.c \
+    src/event_types/resource_violation_event.c \
+    src/event_types/service_failed_event.c \
+    src/event_types/system_booted_event.c
 
 TESTS = $(check_PROGRAMS)
 endif
index f177052378a82b961f180e130d127f8498a19615..d2a3d1722384bc67427b1dc189b9c6eebc3338ee 100644 (file)
@@ -107,6 +107,7 @@ static void dm_event_serialize(struct faultd_event *ev, struct faultd_object *ou
        faultd_object_append_string(out, DM_EV_ACTION, dm_ev->action);
        faultd_object_append_object(out, DM_EV_ACTION_DATA, dm_ev->action_data);
 }
+TEST_ENTRY_POINT(dm_event_serialize);
 
 static struct faultd_event_type decision_made_event_type = {
        .name = DECISION_MADE_EVENT_ID,
index 5934efb940417e5f8aa632d9fee479299a9dd504..a1f5b037579bc2a535f4d2edfae70c092d8e14fe 100644 (file)
@@ -147,6 +147,7 @@ static void rv_event_serialize(struct faultd_event *ev, struct faultd_object *ou
        faultd_object_append_int(out, RV_EV_RES_TYPE, rv_ev->resource_type);
        faultd_object_append_int(out, RV_EV_PID, rv_ev->pid);
 }
+TEST_ENTRY_POINT(rv_event_serialize);
 
 static struct faultd_event_type resource_violation_event_type = {
        .name = RESOURCE_VIOLATION_EVENT_ID,
index f0c73b032d29cd8b96f2e55a24f451301e4f362e..c0dacfbb4581e16143bfede9fbc54d1ac44faa90 100644 (file)
@@ -129,6 +129,7 @@ static void sf_event_serialize(struct faultd_event *ev, struct faultd_object *ou
        systemd_service_serialize(&sf_ev->service, out);
        faultd_object_append_time_t(out, SF_EV_DTIME, sf_ev->detection_time);
 }
+TEST_ENTRY_POINT(sf_event_serialize);
 
 static struct faultd_event_type service_failed_event_type = {
        .name = SERVICE_FAILED_EVENT_ID,
index 901b815a173f66a1b0f28eb068671e1995840e00..bf01d46c7e258119258ed424c8e25d9c058a16f2 100644 (file)
@@ -84,6 +84,7 @@ static void sb_event_serialize(struct faultd_event *ev, struct faultd_object *ou
        faultd_event_serialize_internal(ev, out);
        faultd_object_append_uuid(out, "prev_boot_id", &sb_ev->prev_boot_id);
 }
+TEST_ENTRY_POINT(sb_event_serialize);
 
 static struct faultd_event_type system_booted_event_type = {
        .name = SYSTEM_BOOTED_EVENT_ID,
diff --git a/tests/unit/decision_made_event_tests.c b/tests/unit/decision_made_event_tests.c
new file mode 100644 (file)
index 0000000..851f094
--- /dev/null
@@ -0,0 +1,86 @@
+#include "decision_made_event.h"
+#include "helpers.h"
+
+#define TESTED_MOD decision_made_event
+
+DECLARE_TEST_ENTRY_POINT(TESTED_MOD, dm_event_serialize, void);
+
+#define KEY1 "somekey"
+#define VAL1 "value"
+
+#define KEY2 "somekey2"
+#define VAL2 "value2"
+
+static struct faultd_event *alloc_event()
+{
+       struct decision_made_event *dm_ev;
+
+       dm_ev = calloc(1, sizeof(*dm_ev));
+       assert_non_null(dm_ev);
+
+       fill_event(&dm_ev->event);
+
+       dm_ev->reason = calloc(1, sizeof(*(dm_ev->reason)));
+       assert_non_null(dm_ev->reason);
+
+       dm_ev->reason->oid = generate_oid();
+       dm_ev->who_made = generate_string(STR_SIZE);
+       dm_ev->action = generate_string(STR_SIZE);
+
+       faultd_object_new(&dm_ev->action_data);
+       faultd_object_append_string(dm_ev->action_data, KEY1, VAL1);
+       faultd_object_append_string(dm_ev->action_data, KEY2, VAL2);
+
+       return &dm_ev->event;
+}
+
+static void generate_test_attrs(struct serialize_test_data *td)
+{
+       struct decision_made_event *dm_ev = to_decision_made_event(td->ev);
+       struct serialized_element action_data[] = {
+               S_ELEMENT(KEY1, TYPE_STRING, VAL1),
+               S_ELEMENT(KEY2, TYPE_STRING, VAL2)
+       };
+
+       struct serialized_element serialized_attrs[] = {
+               S_ELEMENT_EVENT(dm_ev->event),
+               S_ELEMENT(DM_EV_REASON, TYPE_OID, &dm_ev->reason->oid),
+               S_ELEMENT(DM_EV_WHO, TYPE_STRING, dm_ev->who_made),
+               S_ELEMENT(DM_EV_ACTION, TYPE_STRING, dm_ev->action),
+               S_ELEMENT_OBJ(DM_EV_ACTION_DATA, dm_ev->action_data,
+                                         action_data, ARRAY_SIZE(action_data))
+       };
+
+       td->test_data = serialized_elems_dup(serialized_attrs,
+                                                                                ARRAY_SIZE(serialized_attrs));
+       td->size = ARRAY_SIZE(serialized_attrs);
+}
+
+static int setup(void **state)
+{
+       return setup_event_serialization(state, alloc_event, generate_test_attrs,
+                                                                        (serialize_func_t)CALL_TEST_ENTRY_POINT(
+                                                                                TESTED_MOD, dm_event_serialize));
+}
+
+static int teardown(void **state)
+{
+       struct serialize_test_data *td = *state;
+       struct decision_made_event *dm_ev = to_decision_made_event(td->ev);
+
+       faultd_object_unref(dm_ev->action_data);
+       free_event(&dm_ev->event);
+       free(dm_ev->who_made);
+       free(dm_ev->action);
+       free(dm_ev->reason);
+       free(dm_ev);
+       serialized_elems_free(td->test_data, td->size);
+       free(td);
+
+       return 0;
+}
+
+FAULTD_TEST_GROUP(
+       FAULTD_TEST_CASE_NST("dm_ev_serialize_test", test_event_serialization,
+                                                setup, teardown)
+)
index 4bdf2e68bb3436f7c458bba4e8e651aaf78a0eec..0503b1a2cc32424eaaaeed8b9c47fd7f80f4c04f 100644 (file)
@@ -1,5 +1,66 @@
 #include "helpers.h"
 
+void test_serialization(struct serialized_element *data, int size, struct faultd_object *parent)
+{
+       for (int i = 0; i < size; ++i) {
+               switch (data[i].type) {
+                       case TYPE_OID:
+                               {
+                                       GET_FAULTD_OBJECT_VAL(faultd_oid_t, val, parent, data[i].key, data[i].type);
+                                       assert_oid_equal(&val, data[i].desired);
+                                       break;
+                               }
+                       case TYPE_STRING:
+                               {
+                                       GET_FAULTD_OBJECT_VAL(char*, val, parent, data[i].key, data[i].type);
+                                       assert_string_equal(val, data[i].desired);
+                                       break;
+                               }
+                       case TYPE_INT:
+                               {
+                                       GET_FAULTD_OBJECT_VAL(int, val, parent, data[i].key, data[i].type);
+                                       assert_int_equal(val, *(int*)(data[i].desired));
+                                       break;
+                               }
+                       case TYPE_TIMESPEC:
+                               {
+                                       GET_FAULTD_OBJECT_VAL(struct timespec, val, parent, data[i].key, data[i].type);
+                                       assert_timespec_equal(&val, data[i].desired);
+                                       break;
+                               }
+                       case TYPE_TIME_T:
+                               {
+                                       GET_FAULTD_OBJECT_VAL(time_t, val, parent, data[i].key, data[i].type);
+                                       assert_time_t_equal(val, *(time_t*)data[i].desired);
+                                       break;
+                               }
+                       case TYPE_UUID:
+                               {
+                                       GET_FAULTD_OBJECT_VAL(sd_id128_t, val, parent, data[i].key, data[i].type);
+                                       assert_uuid_equal(&val, data[i].desired);
+                                       break;
+                               }
+                       case TYPE_OBJECT:
+                               {
+                                       struct faultd_object *child;
+                                       int ret;
+
+                                       ret = faultd_object_get_object(parent, data[i].key, &child);
+                                       assert_int_equal(ret, 0);
+                                       test_serialization(data[i].child, data[i].children_num, child);
+                                       break;
+                               }
+                       default:
+                               fprintf(stderr, "Type '%d' is not supported (key: '%s')\n",
+                                               data[i].type, data[i].key);
+                               fail();
+                               break;
+               }
+       }
+
+       assert_int_equal(faultd_object_count_children(parent), size);
+}
+
 void assert_faultd_object_equal(struct faultd_object *actual,
                                                                struct faultd_object *desired)
 {
@@ -213,3 +274,70 @@ struct timespec generate_timespec()
        t.tv_nsec = generate_int();
        return t;
 }
+
+void test_event_serialization(void **state)
+{
+       struct serialize_test_data *td = *state;
+       struct faultd_object *parent;
+       int ret;
+
+       ret = faultd_object_new(&parent);
+       assert_int_equal(ret, 0);
+
+       td->serialize_func(td->ev, parent);
+
+       test_serialization(td->test_data, td->size, parent);
+
+       faultd_object_unref(parent);
+}
+
+struct serialized_element *serialized_elems_dup(
+       struct serialized_element *elems, size_t size)
+{
+       struct serialized_element *new_elems;
+       int i;
+
+       new_elems = calloc(size, sizeof(*elems));
+       assert_non_null(new_elems);
+
+       memcpy(new_elems, elems, sizeof(*elems)*size);
+
+       for (i = 0; i < size; ++i)
+               if (new_elems[i].type == TYPE_OBJECT)
+                       new_elems[i].child = serialized_elems_dup(new_elems[i].child,
+                                                                                                         new_elems[i].children_num);
+
+       return new_elems;
+}
+
+void serialized_elems_free(struct serialized_element *elems, size_t size)
+{
+       int i;
+
+       for (i = 0; i < size; ++i)
+               if (elems[i].type == TYPE_OBJECT)
+                       serialized_elems_free(elems[i].child, elems[i].children_num);
+}
+
+int setup_event_serialization(void **state,
+                                                         struct faultd_event *(*alloc_event)(),
+                                                         void (*generate_attrs)(
+                                                                 struct serialize_test_data *td),
+                                                         serialize_func_t serialize_func)
+{
+       struct serialize_test_data *td;
+
+       srand(time(NULL));
+
+       td = calloc(1, sizeof(*td));
+       assert_non_null(td);
+
+       td->ev = alloc_event();
+
+       generate_attrs(td);
+
+       td->serialize_func =  serialize_func;
+
+       *state = td;
+       return 0;
+}
index ffe7c9dcad0af4663f2f5a278b4f4d9cc4f68306..7d3a7f19f62b917094959d5246ffb073a658aaef 100644 (file)
@@ -2,12 +2,58 @@
 #define FAULTD_HELPERS_H
 
 #include "fdtf.h"
+#include "event.h"
+#include "service.h"
 
 #include <time.h>
 #include <stdio.h>
 #include <systemd/sd-id128.h>
 #include <systemd/sd-bus.h>
 
+#define STR_SIZE 20
+
+#define GET_FAULTD_OBJECT_VAL(TYPE, VAR, OBJ, KEY, TYPE2) \
+       TYPE VAR; \
+       assert_int_equal(faultd_object_get_val(OBJ, KEY, TYPE2, &VAR), 0);
+
+#define _S_ELEMENT(KEY, TYPE, DESIRED) \
+       .key = KEY, \
+       .type = TYPE, \
+       .desired = DESIRED
+
+#define S_ELEMENT(TYPE, DESIRED, KEY) { \
+       _S_ELEMENT(TYPE, DESIRED, KEY) \
+}
+
+#define S_ELEMENT_EVENT(EV) \
+       S_ELEMENT(EV_BOOT_ID, TYPE_UUID, &EV.boot_id), \
+       S_ELEMENT(EV_TYPE_NAME, TYPE_STRING, EV.type->name), \
+       S_ELEMENT(EV_TIMESTAMP, TYPE_TIMESPEC, &EV.timestamp)
+
+#define S_ELEMENT_SERVICE(srv) \
+       S_ELEMENT(SYSD_SERVICE_DBUS_PATH, TYPE_STRING, \
+                         srv.dbus_path), \
+       S_ELEMENT(SYSD_SERVICE_SERVICE_TYPE, TYPE_STRING, \
+                         srv.service_type), \
+       S_ELEMENT(SYSD_SERVICE_RECOVERY_UNIT, TYPE_STRING, \
+                         srv.recovery_unit)
+
+#define S_ELEMENT_OBJ(KEY, DESIRED, CHILD, CHILDREN_NUM) { \
+       _S_ELEMENT(KEY, TYPE_OBJECT, DESIRED), \
+       .child = CHILD, \
+       .children_num = CHILDREN_NUM \
+}
+
+struct serialized_element {
+       int type;
+       void *desired;
+       char *key;
+       struct serialized_element *child;
+       int children_num;
+};
+
+void test_serialization(struct serialized_element *data, int size,
+                                               struct faultd_object *parent);
 int faultd_object_count_children(struct faultd_object *obj);
 
 void assert_faultd_object_equal(struct faultd_object *actual,
@@ -29,4 +75,55 @@ sd_id128_t generate_uuid();
 faultd_oid_t generate_oid();
 struct timespec generate_timespec();
 
-#endif /* FAULTD_UNIT_H */
+typedef void (*serialize_func_t)(struct faultd_event *, struct faultd_object *);
+
+struct serialize_test_data {
+       struct faultd_event *ev;
+       struct serialized_element *test_data;
+       size_t size;
+       serialize_func_t serialize_func;
+};
+
+void test_event_serialization(void **state);
+
+struct serialized_element *serialized_elems_dup(
+       struct serialized_element *elems, size_t size);
+
+void serialized_elems_free(struct serialized_element *elems, size_t size);
+
+int setup_event_serialization(void **state,
+                                                          struct faultd_event *(*alloc_event)(),
+                                                          void (*generate_attrs)(
+                                                                  struct serialize_test_data *td),
+                                                          serialize_func_t serialize_func);
+
+static inline void fill_event(struct faultd_event *ev)
+{
+       ev->boot_id = generate_uuid();
+       ev->type = calloc(1, sizeof(*(ev->type)));
+       assert_non_null(ev->type);
+       ev->type->name = generate_string(STR_SIZE);
+       ev->timestamp = generate_timespec();
+}
+
+static inline void free_event(struct faultd_event *ev)
+{
+       free(ev->type->name);
+       free(ev->type);
+}
+
+static inline void fill_service(struct systemd_service *srv)
+{
+       srv->dbus_path = generate_string(STR_SIZE);
+       srv->service_type = generate_string(STR_SIZE);
+       srv->recovery_unit = generate_string(STR_SIZE);
+}
+
+static inline void free_service(struct systemd_service *srv)
+{
+       free(srv->dbus_path);
+       free(srv->service_type);
+       free(srv->recovery_unit);
+}
+
+#endif /* FAULTD_HELPERS_H */
diff --git a/tests/unit/resource_violation_event_tests.c b/tests/unit/resource_violation_event_tests.c
new file mode 100644 (file)
index 0000000..e4cea82
--- /dev/null
@@ -0,0 +1,68 @@
+#include "resource_violation_event.h"
+#include "helpers.h"
+
+#define TESTED_MOD resource_violation_event
+
+DECLARE_TEST_ENTRY_POINT(TESTED_MOD, rv_event_serialize, void);
+
+static struct faultd_event *alloc_event()
+{
+       struct resource_violation_event *rv_ev;
+
+       rv_ev = calloc(1, sizeof(*rv_ev));
+       assert_non_null(rv_ev);
+
+       fill_event(&rv_ev->event);
+       fill_service(&rv_ev->service);
+       rv_ev->detection_time = generate_time_t();
+       rv_ev->pid = generate_int();
+       rv_ev->resource_type = generate_int();
+
+       return &rv_ev->event;
+}
+
+static void generate_test_attrs(struct serialize_test_data *td)
+{
+       struct resource_violation_event *rv_ev = to_resource_violation_event(td->ev);
+       struct serialized_element service_data[] = {
+               S_ELEMENT_SERVICE(rv_ev->service)
+       };
+
+       struct serialized_element serialized_attrs[] = {
+               S_ELEMENT_EVENT(rv_ev->event),
+               S_ELEMENT_OBJ(SYSD_SERVICE, NULL,
+                                         service_data, ARRAY_SIZE(service_data)),
+               S_ELEMENT(RV_EV_DTIME, TYPE_TIME_T, &rv_ev->detection_time),
+               S_ELEMENT(RV_EV_RES_TYPE, TYPE_INT, &rv_ev->resource_type),
+               S_ELEMENT(RV_EV_PID, TYPE_INT, &rv_ev->pid)
+       };
+
+       td->test_data = serialized_elems_dup(serialized_attrs,
+                                                                                ARRAY_SIZE(serialized_attrs));
+       td->size = ARRAY_SIZE(serialized_attrs);
+}
+
+static int setup(void **state)
+{
+       return setup_event_serialization(state, alloc_event, generate_test_attrs,
+                                                                        (serialize_func_t)CALL_TEST_ENTRY_POINT(
+                                                                                TESTED_MOD, rv_event_serialize));
+}
+
+static int teardown(void **state)
+{
+       struct serialize_test_data *td = *state;
+       struct resource_violation_event *rv_ev = to_resource_violation_event(td->ev);
+
+       free_event(&rv_ev->event);
+       free_service(&rv_ev->service);
+       free(rv_ev);
+       serialized_elems_free(td->test_data, td->size);
+       free(td);
+       return 0;
+}
+
+FAULTD_TEST_GROUP(
+       FAULTD_TEST_CASE_NST("rv_ev_serialize_test", test_event_serialization,
+                                                setup, teardown)
+)
diff --git a/tests/unit/service_failed_event_tests.c b/tests/unit/service_failed_event_tests.c
new file mode 100644 (file)
index 0000000..3c78cd5
--- /dev/null
@@ -0,0 +1,64 @@
+#include "service_failed_event.h"
+#include "helpers.h"
+
+#define TESTED_MOD service_failed_event
+
+DECLARE_TEST_ENTRY_POINT(TESTED_MOD, sf_event_serialize, void);
+
+static struct faultd_event *alloc_event()
+{
+       struct service_failed_event *sf_ev;
+
+       sf_ev = calloc(1, sizeof(*sf_ev));
+       assert_non_null(sf_ev);
+
+       fill_event(&sf_ev->event);
+       fill_service(&sf_ev->service);
+       sf_ev->detection_time = generate_time_t();
+
+       return &sf_ev->event;
+}
+
+static void generate_test_attrs(struct serialize_test_data *td)
+{
+       struct service_failed_event *sf_ev = to_service_failed_event(td->ev);
+       struct serialized_element service_data[] = {
+               S_ELEMENT_SERVICE(sf_ev->service)
+       };
+
+       struct serialized_element serialized_attrs[] = {
+               S_ELEMENT_EVENT(sf_ev->event),
+               S_ELEMENT_OBJ(SYSD_SERVICE, NULL,
+                                         service_data, ARRAY_SIZE(service_data)),
+               S_ELEMENT(SF_EV_DTIME, TYPE_TIME_T, &sf_ev->detection_time)
+       };
+
+       td->test_data = serialized_elems_dup(serialized_attrs,
+                                                                                ARRAY_SIZE(serialized_attrs));
+       td->size = ARRAY_SIZE(serialized_attrs);
+}
+
+static int setup(void **state)
+{
+       return setup_event_serialization(state, alloc_event, generate_test_attrs,
+                                                                        (serialize_func_t)CALL_TEST_ENTRY_POINT(
+                                                                                TESTED_MOD, sf_event_serialize));
+}
+
+static int teardown(void **state)
+{
+       struct serialize_test_data *td = *state;
+       struct service_failed_event *sf_ev = to_service_failed_event(td->ev);
+
+       free_event(&sf_ev->event);
+       free_service(&sf_ev->service);
+       free(sf_ev);
+       serialized_elems_free(td->test_data, td->size);
+       free(td);
+       return 0;
+}
+
+FAULTD_TEST_GROUP(
+       FAULTD_TEST_CASE_NST("sf_ev_serialize_test", test_event_serialization,
+                                                setup, teardown)
+)
diff --git a/tests/unit/system_booted_event_tests.c b/tests/unit/system_booted_event_tests.c
new file mode 100644 (file)
index 0000000..d6b261d
--- /dev/null
@@ -0,0 +1,56 @@
+#include "system_booted_event.h"
+#include "helpers.h"
+
+#define TESTED_MOD system_booted_event
+
+DECLARE_TEST_ENTRY_POINT(TESTED_MOD, sb_event_serialize, void);
+
+static struct faultd_event *alloc_event()
+{
+       struct system_booted_event *sb_ev;
+
+       sb_ev = calloc(1, sizeof(*sb_ev));
+       assert_non_null(sb_ev);
+
+       fill_event(&sb_ev->event);
+       sb_ev->prev_boot_id = generate_uuid();
+
+       return &sb_ev->event;
+}
+
+static void generate_test_attrs(struct serialize_test_data *td)
+{
+       struct system_booted_event *sb_ev = to_system_booted_event(td->ev);
+       struct serialized_element serialized_attrs[] = {
+               S_ELEMENT_EVENT(sb_ev->event),
+               S_ELEMENT("prev_boot_id", TYPE_UUID, &sb_ev->prev_boot_id)
+       };
+
+       td->test_data = serialized_elems_dup(serialized_attrs,
+                                                                                ARRAY_SIZE(serialized_attrs));
+       td->size = ARRAY_SIZE(serialized_attrs);
+}
+
+static int setup(void **state)
+{
+       return setup_event_serialization(state, alloc_event, generate_test_attrs,
+                                                                        (serialize_func_t)CALL_TEST_ENTRY_POINT(
+                                                                                TESTED_MOD, sb_event_serialize));
+}
+
+static int teardown(void **state)
+{
+       struct serialize_test_data *td = *state;
+       struct system_booted_event *sb_ev = to_system_booted_event(td->ev);
+
+       free_event(&sb_ev->event);
+       free(sb_ev);
+       serialized_elems_free(td->test_data, td->size);
+       free(td);
+       return 0;
+}
+
+FAULTD_TEST_GROUP(
+       FAULTD_TEST_CASE_NST("sb_ev_serialize_test", test_event_serialization,
+                                                setup, teardown)
+)