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