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 
reactor_thread(void * ptr)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 
spawn_reactor_thread(reactor_t * reactor)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 
join_reactor_thread()33 static void join_reactor_thread() {
34   pthread_join(thread, NULL);
35 }
36 
TEST_F(ReactorTest,reactor_new)37 TEST_F(ReactorTest, reactor_new) {
38   reactor_t *reactor = reactor_new();
39   EXPECT_TRUE(reactor != NULL);
40   reactor_free(reactor);
41 }
42 
TEST_F(ReactorTest,reactor_free_null)43 TEST_F(ReactorTest, reactor_free_null) {
44   reactor_free(NULL);
45 }
46 
TEST_F(ReactorTest,reactor_stop_start)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 
TEST_F(ReactorTest,reactor_repeated_stop_start)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 
TEST_F(ReactorTest,reactor_start_wait_stop)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 
unregister_cb(void * context)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 
TEST_F(ReactorTest,reactor_unregister_from_callback)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 
TEST_F(ReactorTest,reactor_unregister_from_separate_thread)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