From ca0842416201a06fccea5f3b997a445c04a4729d Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Mon, 15 Jan 2018 20:43:35 +0300 Subject: [PATCH] Add test for event loop Change-Id: Icc7996dd317f9484839389a017f5a649efec63ab Signed-off-by: Vyacheslav Cherkashin --- packaging/swap-manager.spec | 8 +++ tests/CMakeLists.txt | 9 +++ tests/event_loop/CMakeLists.txt | 23 ++++++++ tests/event_loop/main.cpp | 120 ++++++++++++++++++++++++++++++++++++++++ tests/event_loop/swap_debug.h | 47 ++++++++++++++++ 5 files changed, 207 insertions(+) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/event_loop/CMakeLists.txt create mode 100644 tests/event_loop/main.cpp create mode 100644 tests/event_loop/swap_debug.h diff --git a/packaging/swap-manager.spec b/packaging/swap-manager.spec index 1a158c3..19a7b41 100644 --- a/packaging/swap-manager.spec +++ b/packaging/swap-manager.spec @@ -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 index 0000000..7b5ecc4 --- /dev/null +++ b/tests/CMakeLists.txt @@ -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 index 0000000..4f73dfd --- /dev/null +++ b/tests/event_loop/CMakeLists.txt @@ -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 index 0000000..4ddebbd --- /dev/null +++ b/tests/event_loop/main.cpp @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include "evloop_c.h" +#include + + +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(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(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 index 0000000..79882be --- /dev/null +++ b/tests/event_loop/swap_debug.h @@ -0,0 +1,47 @@ +#ifndef SWAP_DEBUG_H +#define SWAP_DEBUG_H + + +#include +#include + +#include +#include + + +#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 -- 2.7.4