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