tests: add test running automatically on building 63/264863/6 accepted/tizen/unified/20211105.130505 submit/tizen/20211103.072537 submit/tizen/20211104.031932 submit/tizen/20211104.080231
authorYoungjae Cho <y0.cho@samsung.com>
Fri, 1 Oct 2021 09:10:18 +0000 (18:10 +0900)
committerYoungjae Cho <y0.cho@samsung.com>
Tue, 26 Oct 2021 08:31:07 +0000 (17:31 +0900)
If the test fails, the whole build will fail.

Change-Id: Ibb88e60d13bcec09567630d051372fbcfbbb79da
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
CMakeLists.txt
packaging/libsyscommon.spec
tests/CMakeLists.txt [new file with mode: 0644]
tests/libcommon/CMakeLists.txt [new file with mode: 0644]
tests/libcommon/test-common.c [new file with mode: 0644]
tests/libcommon/test.conf [new file with mode: 0644]
tests/test-main.c [new file with mode: 0644]
tests/test-main.h [new file with mode: 0644]
tests/test-mock.c [new file with mode: 0644]
tests/test-mock.h [new file with mode: 0644]

index 049a45b..bebdb2e 100644 (file)
@@ -68,3 +68,5 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_I
 FOREACH(hfile ${HEADERS})
        INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${hfile} DESTINATION include/${PROJECT_NAME})
 ENDFOREACH(hfile)
+
+ADD_SUBDIRECTORY(tests)
index 80e7db4..4ec8ea2 100644 (file)
@@ -11,6 +11,7 @@ BuildRequires:  pkgconfig(glib-2.0) >= 2.44
 BuildRequires:  pkgconfig(gio-2.0) >= 2.44
 BuildRequires:  pkgconfig(gio-unix-2.0)
 BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(cmocka)
 BuildRequires:  cmake
 
 Requires:       /bin/cp
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..bfd44ea
--- /dev/null
@@ -0,0 +1,20 @@
+SET(TEST_DRIVER "test-driver")
+
+FILE(GLOB SRCS "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
+
+SET(TEST_SUITE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+ADD_DEFINITIONS("-DTEST_SUITE_DIRECTORY=\"${TEST_SUITE_DIRECTORY}\"")
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(REQUIRED_PKGS REQUIRED
+       cmocka)
+
+ADD_EXECUTABLE(${TEST_DRIVER} ${SRCS})
+TARGET_LINK_LIBRARIES(${TEST_DRIVER} cmocka dl)
+SET_TARGET_PROPERTIES(${TEST_DRIVER} PROPERTIES LINK_FLAGS "-Wl,--export-dynamic")
+
+ADD_CUSTOM_TARGET(run-test ALL "./${TEST_DRIVER}")
+ADD_DEPENDENCIES(run-test ${TEST_DRIVER})
+
+# add test suites
+ADD_SUBDIRECTORY(libcommon)
diff --git a/tests/libcommon/CMakeLists.txt b/tests/libcommon/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9fe27d3
--- /dev/null
@@ -0,0 +1,16 @@
+SET(TEST_SUITE "test-driver-libcommon")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src)
+
+FILE(GLOB SRCS "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
+FILE(GLOB ORIG_SRCS "${CMAKE_SOURCE_DIR}/src/libcommon/*.c")
+
+ADD_LIBRARY(${TEST_SUITE} MODULE ${SRCS} ${ORIG_SRCS})
+SET_TARGET_PROPERTIES(${TEST_SUITE} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${TEST_SUITE_DIRECTORY})
+ADD_DEPENDENCIES(${TEST_DRIVER} ${TEST_SUITE})
+
+SET(WRAP_FLAGS "${WRAP_FLAGS} -Wl,--wrap=open")
+SET(WRAP_FLAGS "${WRAP_FLAGS} -Wl,--wrap=open64")
+SET_TARGET_PROPERTIES(${TEST_SUITE} PROPERTIES LINK_FLAGS ${WRAP_FLAGS})
+
+TARGET_LINK_LIBRARIES(${TEST_SUITE} cmocka glib-2.0)
diff --git a/tests/libcommon/test-common.c b/tests/libcommon/test-common.c
new file mode 100644 (file)
index 0000000..76e770c
--- /dev/null
@@ -0,0 +1,208 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <glib.h>
+
+#include "libcommon/file.h"
+#include "libcommon/list.h"
+#include "libcommon/ini-parser.h"
+#include "../test-main.h"
+#include "../test-mock.h"
+
+#define MOCK_FILE_PATH    "testfile"
+#define MOCK_FILE_LENGTH  100
+
+static int setup(void **state)
+{
+       FILE *fp;
+       char cwd[128] = {0, };
+       char path[256] = {0, };
+       char str[MOCK_FILE_LENGTH];
+
+       memset(str, 't', MOCK_FILE_LENGTH);
+
+       snprintf(path, sizeof(path), "%s/%s", getcwd(cwd, sizeof(cwd)), MOCK_FILE_PATH);
+
+       fp = fopen(path, "w+");
+
+       if (!fp) {
+               printf("Failed to setup mockfile, %m\n");
+               return -1;
+       }
+
+       fwrite(str, 1, MOCK_FILE_LENGTH, fp);
+       fclose(fp);
+
+       return 0;
+}
+
+static int teardown(void **state)
+{
+       char cwd[128] = {0, };
+       char path[256] = {0, };
+
+       snprintf(path, sizeof(path), "%s/%s", getcwd(cwd, sizeof(cwd)), MOCK_FILE_PATH);
+
+       unlink(path);
+
+       return 0;
+}
+
+static void test_sys_get_str_p1(void **state)
+{
+       char buffer[MOCK_FILE_LENGTH * 2];
+       int retval;
+
+       /* remove possible null character */
+       for (int i = 0; i < sizeof(buffer); ++i)
+               buffer[i] = 'x';
+
+       /* mocking open() syscall */
+       mock_open(MOCK_FILE_PATH, O_RDONLY);
+
+       /* this is example of how mock works */
+       retval = sys_get_str("the pathname will be replaced to mocked one",
+               buffer, sizeof(buffer));
+
+       assert_int_equal(retval, 0);
+}
+
+/* test small buffer */
+static void test_sys_get_str_n1(void **state)
+{
+       char buffer[MOCK_FILE_LENGTH / 2];
+       int retval;
+
+       /* remove possible null character */
+       for (int i = 0; i < sizeof(buffer); ++i)
+               buffer[i] = 'x';
+
+       /* mocking open() syscall */
+       mock_open(MOCK_FILE_PATH, O_RDONLY);
+
+       /* this is example of how mock works */
+       retval = sys_get_str("the pathname will be replaced to mocked one",
+               buffer, sizeof(buffer));
+
+       assert_int_equal(retval, -EIO);
+       assert_int_equal(buffer[0], 0);
+}
+
+/* test no-exist file */
+static void test_sys_get_str_n2(void **state)
+{
+       char buffer[MOCK_FILE_LENGTH * 2];
+       int retval;
+
+       mock_open(MOCK_FILE_PATH, O_RDONLY);
+
+       retval = sys_get_str("the pathname will be replaced to mocked one",
+               buffer, sizeof(buffer));
+
+       assert_int_equal(retval, -ENOENT);
+}
+
+static void test_list_append_p(void **state)
+{
+       GList *head = NULL;
+       GList *elem, *elem2;
+       int i;
+       int value;
+       int length;
+
+       for ( i = 0; i < 10; ++i)
+               SYS_G_LIST_APPEND(head, (intptr_t) i);
+
+       length = SYS_G_LIST_LENGTH(head);
+       assert_int_equal(length, 10);
+
+       i = 0;
+       SYS_G_LIST_FOREACH(head, elem, elem2) {
+               value = (int) elem2;
+               assert_int_equal(value, i++);
+       }
+}
+
+static void test_list_prepend_p(void **state)
+{
+       GList *head = NULL;
+       GList *elem, *elem2;
+       int i;
+       int value;
+       int length;
+
+       for ( i = 0; i < 10; ++i)
+               SYS_G_LIST_PREPEND(head, (intptr_t) i);
+
+       length = SYS_G_LIST_LENGTH(head);
+       assert_int_equal(length, 10);
+
+       i = 10;
+       SYS_G_LIST_FOREACH(head, elem, elem2) {
+               value = (int) elem2;
+               assert_int_equal(value, --i);
+       }
+}
+
+static int check_user_data = 0x443;
+static bool checked1;
+static bool checked2;
+static bool checked3;
+static bool garbage;
+static int test_parser(struct parse_result *result, void *data)
+{
+       assert_int_equal(data, check_user_data);
+
+       if (MATCH(result->section, "Section1") &&
+               MATCH(result->name, "Key1") &&
+               MATCH(result->value, "Value1"))
+               checked1 = true;
+       else if (MATCH(result->section, "Section2") &&
+               MATCH(result->name, "Key2") &&
+               MATCH(result->value, "Value2"))
+               checked2 = true;
+       else if (MATCH(result->section, "Section2") &&
+               MATCH(result->name, "Key3") &&
+               MATCH(result->value, "Value3"))
+               checked3 = true;
+       else
+               garbage = true;
+
+       return 0;
+}
+
+static void test_config_parse_p(void **state)
+{
+       char cwd[128];
+       char path[256];
+       int retval;
+
+       /* load predefined test.conf file */
+       retval = snprintf(path, sizeof(path), "%s/libcommon/test.conf", getcwd(cwd, sizeof(cwd)));
+       if (retval >= sizeof(path))
+               path[sizeof(path) - 1] = '\0';
+
+       config_parse(path, test_parser, (void *)(intptr_t) check_user_data);
+
+       assert_true(checked1);
+       assert_true(checked2);
+       assert_true(checked3);
+       assert_false(garbage);
+}
+
+int run_test_suite(void)
+{
+       const struct CMUnitTest testsuite[] = {
+               cmocka_unit_test_setup_teardown(test_sys_get_str_p1, setup, teardown),
+               cmocka_unit_test_setup_teardown(test_sys_get_str_n1, setup, teardown),
+               cmocka_unit_test(test_sys_get_str_n2),
+               cmocka_unit_test(test_list_append_p),
+               cmocka_unit_test(test_list_prepend_p),
+               cmocka_unit_test(test_config_parse_p),
+       };
+
+       return cmocka_run_group_tests(testsuite, NULL, NULL);
+}
diff --git a/tests/libcommon/test.conf b/tests/libcommon/test.conf
new file mode 100644 (file)
index 0000000..c915ae1
--- /dev/null
@@ -0,0 +1,8 @@
+[Section1]
+# this is comment
+Key1=Value1
+
+[Section2]
+# this is comment
+Key2=Value2
+Key3=Value3
diff --git a/tests/test-main.c b/tests/test-main.c
new file mode 100644 (file)
index 0000000..0451498
--- /dev/null
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test-main.h"
+
+int main(int argc, char *argv[])
+{
+       int fail = 0;
+       DIR *dir;
+       struct dirent *ent;
+
+       dir = opendir(TEST_SUITE_DIRECTORY);
+       if (!dir) {
+               printf("Failed to opendir, %m\n");
+               return 1;
+       }
+
+       while ((ent = readdir(dir))) {
+               void *handle;
+               char sopath[512] = {0, };
+               int (*run_test_suite) (void);
+
+               if (!strstr(ent->d_name, ".so"))
+                       continue;
+
+               snprintf(sopath, sizeof(sopath), "%s/%s", TEST_SUITE_DIRECTORY, ent->d_name);
+
+               handle = dlopen(sopath, RTLD_LAZY);
+               if (!handle) {
+                       printf("Failed to dlopen, %s\n", dlerror());
+                       continue;
+               }
+
+               run_test_suite = dlsym(handle, "run_test_suite");
+               if (!run_test_suite) {
+                       printf("Failed to dlsym, %s\n", dlerror());
+                       dlclose(handle);
+                       continue;
+               }
+
+               fail += run_test_suite();
+       }
+
+       closedir(dir);
+
+       return fail;
+}
diff --git a/tests/test-main.h b/tests/test-main.h
new file mode 100644 (file)
index 0000000..4b04a85
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __TEST_MAIN_H__
+#define __TEST_MAIN_H__
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#endif //__TEST_MAIN_H__
+
diff --git a/tests/test-mock.c b/tests/test-mock.c
new file mode 100644 (file)
index 0000000..4e7f260
--- /dev/null
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "test-main.h"
+#include "test-mock.h"
+
+//static FILE *__fp = NULL;
+
+int __wrap_open(const char *pathname, int flags)
+{
+       const char *mock_pathname;
+       int mock_flags;
+
+       mock_pathname = mock_ptr_type(char *);
+       if (mock_pathname == NULL) {
+               errno = -ENOENT;
+               return -1;
+       }
+
+       mock_flags = mock_type(int);
+
+       return open(mock_pathname, mock_flags);
+}
+
+int __wrap_open64(const char *pathname, int flags)
+{
+       return __wrap_open(pathname, flags);
+}
+
+
+void mock_open(const char *pathname, int flags)
+{
+       will_return(__wrap_open, pathname);
+       will_return(__wrap_open, flags);
+}
+
+/*
+FILE *__wrap_fopen(const char *pathname, const char *mode)
+{
+       const char *mock_pathname = mock_ptr_type(char *);
+       const char *mock_mode = mock_ptr_type(char *);
+
+       __fp = fopen(mock_pathname, mock_mode);
+
+       return __fp;
+}
+
+FILE *__wrap_fopen64(const char *pathname, const char *mode)
+{
+       return __wrap_fopen(pathname, mode);
+
+}
+
+int __wrap_fclose(FILE *stream)
+{
+       return 0;
+}
+
+int __wrap_fclose64(FILE *stream)
+{
+       return __wrap_fclose(stream);
+}
+*/
diff --git a/tests/test-mock.h b/tests/test-mock.h
new file mode 100644 (file)
index 0000000..22c7196
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __TEST_MOCK_H__
+#define __TEST_MOCK_H__
+
+#include <stdio.h>
+
+void mock_open(const char *pathname, int flags);
+
+#endif //__TEST_MOCK_H__