1#include <gtest/gtest.h> 2#include <pthread.h> 3#include <sys/eventfd.h> 4#include <sys/time.h> 5#include <unistd.h> 6 7#include "AllocationTestHarness.h" 8 9extern "C" { 10#include "reactor.h" 11} 12 13class ReactorTest : public AllocationTestHarness {}; 14 15static pthread_t thread; 16static volatile bool thread_running; 17 18static void *reactor_thread(void *ptr) { 19 reactor_t *reactor = (reactor_t *)ptr; 20 21 thread_running = true; 22 reactor_start(reactor); 23 thread_running = false; 24 25 return NULL; 26} 27 28static void spawn_reactor_thread(reactor_t *reactor) { 29 int ret = pthread_create(&thread, NULL, reactor_thread, reactor); 30 EXPECT_EQ(ret, 0); 31} 32 33static void join_reactor_thread() { 34 pthread_join(thread, NULL); 35} 36 37TEST_F(ReactorTest, reactor_new) { 38 reactor_t *reactor = reactor_new(); 39 EXPECT_TRUE(reactor != NULL); 40 reactor_free(reactor); 41} 42 43TEST_F(ReactorTest, reactor_free_null) { 44 reactor_free(NULL); 45} 46 47TEST_F(ReactorTest, reactor_stop_start) { 48 reactor_t *reactor = reactor_new(); 49 reactor_stop(reactor); 50 reactor_start(reactor); 51 reactor_free(reactor); 52} 53 54TEST_F(ReactorTest, reactor_repeated_stop_start) { 55 reactor_t *reactor = reactor_new(); 56 for (int i = 0; i < 10; ++i) { 57 reactor_stop(reactor); 58 reactor_start(reactor); 59 } 60 reactor_free(reactor); 61} 62 63TEST_F(ReactorTest, reactor_start_wait_stop) { 64 reactor_t *reactor = reactor_new(); 65 66 spawn_reactor_thread(reactor); 67 usleep(50 * 1000); 68 EXPECT_TRUE(thread_running); 69 70 reactor_stop(reactor); 71 join_reactor_thread(); 72 EXPECT_FALSE(thread_running); 73 74 reactor_free(reactor); 75} 76 77typedef struct { 78 reactor_t *reactor; 79 reactor_object_t *object; 80} unregister_arg_t; 81 82static void unregister_cb(void *context) { 83 unregister_arg_t *arg = (unregister_arg_t *)context; 84 reactor_unregister(arg->object); 85 reactor_stop(arg->reactor); 86} 87 88TEST_F(ReactorTest, reactor_unregister_from_callback) { 89 reactor_t *reactor = reactor_new(); 90 91 int fd = eventfd(0, 0); 92 unregister_arg_t arg; 93 arg.reactor = reactor; 94 arg.object = reactor_register(reactor, fd, &arg, unregister_cb, NULL); 95 spawn_reactor_thread(reactor); 96 eventfd_write(fd, 1); 97 98 join_reactor_thread(); 99 100 close(fd); 101 reactor_free(reactor); 102} 103 104TEST_F(ReactorTest, reactor_unregister_from_separate_thread) { 105 reactor_t *reactor = reactor_new(); 106 107 int fd = eventfd(0, 0); 108 109 reactor_object_t *object = reactor_register(reactor, fd, NULL, NULL, NULL); 110 spawn_reactor_thread(reactor); 111 usleep(50 * 1000); 112 reactor_unregister(object); 113 114 reactor_stop(reactor); 115 join_reactor_thread(); 116 117 close(fd); 118 reactor_free(reactor); 119} 120