Add test for event loop 88/167288/2
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Mon, 15 Jan 2018 17:43:35 +0000 (20:43 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Wed, 17 Jan 2018 15:36:45 +0000 (18:36 +0300)
Change-Id: Icc7996dd317f9484839389a017f5a649efec63ab
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
packaging/swap-manager.spec
tests/CMakeLists.txt [new file with mode: 0644]
tests/event_loop/CMakeLists.txt [new file with mode: 0644]
tests/event_loop/main.cpp [new file with mode: 0644]
tests/event_loop/swap_debug.h [new file with mode: 0644]

index 1a158c3..19a7b41 100644 (file)
@@ -9,6 +9,7 @@ License:    Apache-2.0, MIT
 Source:    %{name}_%{version}.tar.gz
 
 # setup config
+%define SET_TESTING 0
 %define SWAP_MODULES_SUPPORT 1
 %define NSP_SUPPORT 0
 %define WSP_SUPPORT 0
@@ -137,6 +138,13 @@ cd daemon && make && cd - || false
 # build ui_viewer
 cd ui_viewer && make %{?ARCH:ARCH=%{ARCH}} && cd - || false
 
+# run tests
+%if %{SET_TESTING}
+  mkdir build_tests && cd build_tests
+  cmake ../tests/ && make && make test || false
+  cd -
+%endif
+
 %install
 rm -rf ${RPM_BUILD_ROOT}
 
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7b5ecc4
--- /dev/null
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8)
+
+enable_testing()
+
+# set PROJECT_SRC
+get_filename_component(PROJECT_SRC ".." ABSOLUTE)
+
+# tests list
+add_subdirectory(event_loop)
diff --git a/tests/event_loop/CMakeLists.txt b/tests/event_loop/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4f73dfd
--- /dev/null
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(event_loop CXX)
+set(BIN_NAME event_loop)
+
+set(CMAKE_CXX_FLAGS "-Wall -Werror -std=c++0x")
+
+set(EVENT_LOOP_SRC_DIR ${PROJECT_SRC}/daemon/cpp/events)
+include_directories(
+  .
+  ${EVENT_LOOP_SRC_DIR}
+  ${PROJECT_SRC}/src
+)
+
+set(EVENT_LOOP_SRC
+  ${EVENT_LOOP_SRC_DIR}/evloop.cpp
+  ${EVENT_LOOP_SRC_DIR}/evloop_c.cpp
+)
+
+add_executable(${BIN_NAME} main.cpp ${EVENT_LOOP_SRC})
+target_link_libraries(${BIN_NAME} pthread)
+
+add_test(event_loop ${BIN_NAME})
diff --git a/tests/event_loop/main.cpp b/tests/event_loop/main.cpp
new file mode 100644 (file)
index 0000000..4ddebbd
--- /dev/null
@@ -0,0 +1,120 @@
+#include <thread>
+#include <cassert>
+#include <unistd.h>
+#include <chrono>
+#include "evloop_c.h"
+#include <sys/eventfd.h>
+
+
+class EvHandler {
+public:
+    using CallBack = void (*)(const struct evloop_handler *handler, void *data);
+    EvHandler(CallBack callback, void *data) :
+        data_(data), callback_(callback)
+    {
+        fd_ = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+    }
+
+    ~EvHandler()
+    {
+        ::close(fd_);
+    }
+
+    int fd()
+    {
+        return fd_;
+    }
+
+    void touch()
+    {
+        eventfd_t ev_val = 1;
+        ::eventfd_write(fd_, ev_val);
+    }
+
+    static void callback(const struct evloop_handler *handler, void *data)
+    {
+        EvHandler *self = static_cast<EvHandler *>(data);
+        assert(self->fd_ >= 0 && self->fd_ < 100);    // 100 - small value
+
+        eventfd_t ev_val;
+        ::eventfd_read(self->fd_, &ev_val);
+
+        self->callback_(handler, self->data_);
+    }
+
+private:
+    int fd_;
+
+    void *data_;
+    CallBack callback_;
+};
+
+
+static void handler(const struct evloop_handler *handler, void *data)
+{
+    int *val = static_cast<int *>(data);
+
+    *val += 1;
+}
+
+static void do_run()
+{
+    int val0 = 0;
+    int val1 = 0;
+    int val2 = 0;
+
+    EvHandler eh0(handler, &val0);
+    EvHandler eh1(handler, &val1);
+    EvHandler eh2(handler, &val2);
+
+    evloop *loop = evloop_create();
+    std::thread worker(evloop_run, loop);
+    auto ev0 = evloop_handler_add(loop, eh0.fd(), &eh0, eh0.callback);
+
+    // case 1:
+    eh0.touch();
+    eh1.touch();
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    assert(val0 == 1 && val1 == 0 && val2 == 0);
+
+    // case 2:
+    auto ev1 = evloop_handler_add(loop, eh1.fd(), &eh1, eh1.callback);
+    eh1.touch();
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    eh1.touch();
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    assert(val0 == 1 && val1 == 2 && val2 == 0);
+
+    // case 3:
+    evloop_handler_del(loop, ev0);
+    auto ev2 = evloop_handler_add(loop, eh2.fd(), &eh2, eh2.callback);
+    eh0.touch();
+    eh2.touch();
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    assert(val0 == 1 && val1 == 2 && val2 == 1);
+
+    // case 4:
+    evloop_stop(loop);
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    eh0.touch();
+    eh1.touch();
+    eh2.touch();
+    assert(val0 == 1 && val1 == 2 && val2 == 1);
+
+    // case 5:
+    eh0.touch();
+    eh1.touch();
+    eh2.touch();
+    evloop_handler_del(loop, ev1);
+    worker.join();
+    evloop_handler_del(loop, ev2);
+    evloop_destroy(loop);
+    assert(val0 == 1 && val1 == 2 && val2 == 1);
+}
+
+int main()
+{
+    do_run();
+
+    return 0;
+}
diff --git a/tests/event_loop/swap_debug.h b/tests/event_loop/swap_debug.h
new file mode 100644 (file)
index 0000000..79882be
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef SWAP_DEBUG_H
+#define SWAP_DEBUG_H
+
+
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#include <stdarg.h>
+#include <time.h>
+
+
+#define LOGI(...) do_log("INF", __func__, __LINE__, __VA_ARGS__)
+#define LOGW(...) do_log("WRN", __func__, __LINE__, __VA_ARGS__)
+#define LOGE(...) do_log("ERR", __func__, __LINE__, __VA_ARGS__)
+
+
+
+static float get_uptime(void)
+{
+        int ret;
+        struct timespec ts;
+        float uptime = 0.0;
+
+        ret = clock_gettime(CLOCK_BOOTTIME, &ts);
+        if (!ret)
+                uptime = ((float)ts.tv_sec + (ts.tv_nsec / 1000000000.0));
+
+        return uptime;
+}
+
+static inline void do_log(const char *prefix, const char *funcname, int line, ...)
+{
+        va_list ap;
+        const char *fmt;
+        fprintf(stderr, "[%s][%f] PID %u:%u (%s:%d):", prefix, get_uptime(),
+                (unsigned int)getpid(),
+                (unsigned int)syscall(SYS_gettid),
+                funcname, line);
+
+        va_start(ap, line);
+        fmt = va_arg(ap, const char *);
+        vfprintf(stderr, fmt, ap);
+        va_end(ap);
+}
+
+
+#endif // SWAP_DEBUG_H