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