Home | History | Annotate | Download | only in test
      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 
     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 
     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 
     31 static void join_reactor_thread() { pthread_join(thread, NULL); }
     32 
     33 TEST_F(ReactorTest, reactor_new) {
     34   reactor_t* reactor = reactor_new();
     35   EXPECT_TRUE(reactor != NULL);
     36   reactor_free(reactor);
     37 }
     38 
     39 TEST_F(ReactorTest, reactor_free_null) { reactor_free(NULL); }
     40 
     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 
     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 
     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 
     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 
     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 
     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