119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati#include <gtest/gtest.h>
219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati#include <pthread.h>
3fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati#include <sys/eventfd.h>
419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati#include <sys/time.h>
519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati#include <unistd.h>
619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
7384f8a948e9837475c4f504a626205334522df2aZach Johnson#include "AllocationTestHarness.h"
8384f8a948e9837475c4f504a626205334522df2aZach Johnson
919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatiextern "C" {
1019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati#include "reactor.h"
1119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati}
1219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
13384f8a948e9837475c4f504a626205334522df2aZach Johnsonclass ReactorTest : public AllocationTestHarness {};
14384f8a948e9837475c4f504a626205334522df2aZach Johnson
1519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatistatic pthread_t thread;
1619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatistatic volatile bool thread_running;
1719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
1819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatistatic void *reactor_thread(void *ptr) {
1919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_t *reactor = (reactor_t *)ptr;
2019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
2119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  thread_running = true;
2219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_start(reactor);
2319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  thread_running = false;
2419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
2519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  return NULL;
2619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati}
2719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
2819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatistatic void spawn_reactor_thread(reactor_t *reactor) {
2919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  int ret = pthread_create(&thread, NULL, reactor_thread, reactor);
3019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  EXPECT_EQ(ret, 0);
3119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati}
3219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
3319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavatistatic void join_reactor_thread() {
3419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  pthread_join(thread, NULL);
3519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati}
3619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
37384f8a948e9837475c4f504a626205334522df2aZach JohnsonTEST_F(ReactorTest, reactor_new) {
3819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_t *reactor = reactor_new();
3919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  EXPECT_TRUE(reactor != NULL);
4019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_free(reactor);
4119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati}
4219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
43384f8a948e9837475c4f504a626205334522df2aZach JohnsonTEST_F(ReactorTest, reactor_free_null) {
4419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_free(NULL);
4519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati}
4619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
47384f8a948e9837475c4f504a626205334522df2aZach JohnsonTEST_F(ReactorTest, reactor_stop_start) {
4819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_t *reactor = reactor_new();
4919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_stop(reactor);
5019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_start(reactor);
5119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_free(reactor);
5219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati}
5319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
54384f8a948e9837475c4f504a626205334522df2aZach JohnsonTEST_F(ReactorTest, reactor_repeated_stop_start) {
5519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_t *reactor = reactor_new();
5619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  for (int i = 0; i < 10; ++i) {
5719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati    reactor_stop(reactor);
5819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati    reactor_start(reactor);
5919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  }
6019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_free(reactor);
6119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati}
6219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
63384f8a948e9837475c4f504a626205334522df2aZach JohnsonTEST_F(ReactorTest, reactor_start_wait_stop) {
6419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_t *reactor = reactor_new();
6519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
6619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  spawn_reactor_thread(reactor);
6719084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  usleep(50 * 1000);
6819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  EXPECT_TRUE(thread_running);
6919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
7019084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_stop(reactor);
7119084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  join_reactor_thread();
7219084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  EXPECT_FALSE(thread_running);
7319084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
7419084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_free(reactor);
7519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati}
7619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
77fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavatitypedef struct {
78fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  reactor_t *reactor;
79fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  reactor_object_t *object;
80fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati} unregister_arg_t;
81fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati
82fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavatistatic void unregister_cb(void *context) {
83fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  unregister_arg_t *arg = (unregister_arg_t *)context;
84fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  reactor_unregister(arg->object);
85fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  reactor_stop(arg->reactor);
86fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati}
87fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati
88384f8a948e9837475c4f504a626205334522df2aZach JohnsonTEST_F(ReactorTest, reactor_unregister_from_callback) {
89fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  reactor_t *reactor = reactor_new();
90fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati
91fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  int fd = eventfd(0, 0);
92fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  unregister_arg_t arg;
93fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  arg.reactor = reactor;
94fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  arg.object = reactor_register(reactor, fd, &arg, unregister_cb, NULL);
95fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  spawn_reactor_thread(reactor);
96fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  eventfd_write(fd, 1);
97fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati
98fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  join_reactor_thread();
99fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati
100fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  close(fd);
101fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  reactor_free(reactor);
102fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati}
103fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati
104384f8a948e9837475c4f504a626205334522df2aZach JohnsonTEST_F(ReactorTest, reactor_unregister_from_separate_thread) {
10519084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_t *reactor = reactor_new();
10619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
107fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  int fd = eventfd(0, 0);
108fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati
109fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  reactor_object_t *object = reactor_register(reactor, fd, NULL, NULL, NULL);
110fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  spawn_reactor_thread(reactor);
111fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  usleep(50 * 1000);
112fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  reactor_unregister(object);
113fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati
114fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  reactor_stop(reactor);
115fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  join_reactor_thread();
11619084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati
117fbf89085bf308a98b00da77d1538539f6dd58604Sharvil Nanavati  close(fd);
11819084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati  reactor_free(reactor);
11919084c6242d8ddb366a52eba5084c974280cce0fSharvil Nanavati}
120