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