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 extern "C" { 10 #include "osi/include/reactor.h" 11 } 12 13 class ReactorTest : public AllocationTestHarness {}; 14 15 static pthread_t thread; 16 static volatile bool thread_running; 17 18 static 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 28 static void spawn_reactor_thread(reactor_t *reactor) { 29 int ret = pthread_create(&thread, NULL, reactor_thread, reactor); 30 EXPECT_EQ(ret, 0); 31 } 32 33 static void join_reactor_thread() { 34 pthread_join(thread, NULL); 35 } 36 37 TEST_F(ReactorTest, reactor_new) { 38 reactor_t *reactor = reactor_new(); 39 EXPECT_TRUE(reactor != NULL); 40 reactor_free(reactor); 41 } 42 43 TEST_F(ReactorTest, reactor_free_null) { 44 reactor_free(NULL); 45 } 46 47 TEST_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 54 TEST_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 63 TEST_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 77 typedef struct { 78 reactor_t *reactor; 79 reactor_object_t *object; 80 } unregister_arg_t; 81 82 static 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 88 TEST_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 104 TEST_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