summaryrefslogtreecommitdiffstats
path: root/osi/test/reactor_test.cpp
blob: 6e3a0092a0be3085a2fdf496ddbb9461229ffa13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <gtest/gtest.h>
#include <pthread.h>
#include <sys/eventfd.h>
#include <sys/time.h>
#include <unistd.h>

#include "AllocationTestHarness.h"

extern "C" {
#include "reactor.h"
}

class ReactorTest : public AllocationTestHarness {};

static pthread_t thread;
static volatile bool thread_running;

static void *reactor_thread(void *ptr) {
  reactor_t *reactor = (reactor_t *)ptr;

  thread_running = true;
  reactor_start(reactor);
  thread_running = false;

  return NULL;
}

static void spawn_reactor_thread(reactor_t *reactor) {
  int ret = pthread_create(&thread, NULL, reactor_thread, reactor);
  EXPECT_EQ(ret, 0);
}

static void join_reactor_thread() {
  pthread_join(thread, NULL);
}

TEST_F(ReactorTest, reactor_new) {
  reactor_t *reactor = reactor_new();
  EXPECT_TRUE(reactor != NULL);
  reactor_free(reactor);
}

TEST_F(ReactorTest, reactor_free_null) {
  reactor_free(NULL);
}

TEST_F(ReactorTest, reactor_stop_start) {
  reactor_t *reactor = reactor_new();
  reactor_stop(reactor);
  reactor_start(reactor);
  reactor_free(reactor);
}

TEST_F(ReactorTest, reactor_repeated_stop_start) {
  reactor_t *reactor = reactor_new();
  for (int i = 0; i < 10; ++i) {
    reactor_stop(reactor);
    reactor_start(reactor);
  }
  reactor_free(reactor);
}

TEST_F(ReactorTest, reactor_start_wait_stop) {
  reactor_t *reactor = reactor_new();

  spawn_reactor_thread(reactor);
  usleep(50 * 1000);
  EXPECT_TRUE(thread_running);

  reactor_stop(reactor);
  join_reactor_thread();
  EXPECT_FALSE(thread_running);

  reactor_free(reactor);
}

typedef struct {
  reactor_t *reactor;
  reactor_object_t *object;
} unregister_arg_t;

static void unregister_cb(void *context) {
  unregister_arg_t *arg = (unregister_arg_t *)context;
  reactor_unregister(arg->object);
  reactor_stop(arg->reactor);
}

TEST_F(ReactorTest, reactor_unregister_from_callback) {
  reactor_t *reactor = reactor_new();

  int fd = eventfd(0, 0);
  unregister_arg_t arg;
  arg.reactor = reactor;
  arg.object = reactor_register(reactor, fd, &arg, unregister_cb, NULL);
  spawn_reactor_thread(reactor);
  eventfd_write(fd, 1);

  join_reactor_thread();

  close(fd);
  reactor_free(reactor);
}

TEST_F(ReactorTest, reactor_unregister_from_separate_thread) {
  reactor_t *reactor = reactor_new();

  int fd = eventfd(0, 0);

  reactor_object_t *object = reactor_register(reactor, fd, NULL, NULL, NULL);
  spawn_reactor_thread(reactor);
  usleep(50 * 1000);
  reactor_unregister(object);

  reactor_stop(reactor);
  join_reactor_thread();

  close(fd);
  reactor_free(reactor);
}