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