summaryrefslogtreecommitdiff
path: root/ACE/tests/Refcounted_Event_Handler_Test_DevPoll.cpp
blob: 591581b8951a69617100e192db911e78bb9b596b (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

//=============================================================================
/**
 *  @file    Refcounted_Event_Handler_Test_DevPoll.cpp
 *
 *  This is a simple test that checks the order of dispatching of
 *  ACE Reactors.  Order should be: timeout, output, and then input.
 *
 *  @author Irfan Pyarali <irfan@cs.wustl.edu>
 */
//=============================================================================


#include "test_config.h"
#include "ace/OS_NS_string.h"
#include "ace/Reactor.h"
#include "ace/Select_Reactor.h"
#include "ace/WFMO_Reactor.h"
#include "ace/Dev_Poll_Reactor.h"
#include "ace/Pipe.h"
#include "ace/ACE.h"


#if defined (ACE_HAS_DEV_POLL) || defined (ACE_HAS_EVENT_POLL)

static const char *message =
"Hello there! Hope you get this message";

class Handler : public ACE_Event_Handler
{
public:
  Handler (ACE_Reactor &reactor);

  ~Handler() override;

  int handle_timeout (const ACE_Time_Value &tv,
                      const void *arg) override;

  int handle_input (ACE_HANDLE fd) override;

  int handle_output (ACE_HANDLE fd) override;

  ACE_HANDLE get_handle () const override;

  // We need to add MSG_OOB data transfer to this test to check the
  // order of when <handle_exception> gets called.  I tried with
  // Windows 2000 but only one byte of the message came across as
  // urgent data.  The rest of the data was treated as normal! There
  // was some explanation of Microsoft's TCP/IP deals with out-of-band
  // data in "Out-of-Band Data and Push Bit in TCP/IP" in the MSDN
  // library.  However, I did not comprehend that well enough.  If
  // someone can make this work, please check the order of
  // <handle_exception> getting called.
  // int handle_exception (ACE_HANDLE fd);

  ACE_Pipe pipe_;

  int dispatch_order_;
  bool ok_;           // Constructed and initialized ok
};

Handler::Handler (ACE_Reactor &reactor)
  : ACE_Event_Handler (&reactor),
    dispatch_order_ (1),
    ok_ (false)
{
  // Create the pipe.
  if (0 != this->pipe_.open ())
    ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("pipe")));
  else
    {
      // Register for all events.
      if (0 != this->reactor ()->register_handler
                 (this->pipe_.read_handle (),
                  this,
                  ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK))
        ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("register")));
      else
        this->ok_ = true;
    }
}


Handler::~Handler ()
{
  this->pipe_.close ();
}


ACE_HANDLE
Handler::get_handle () const
{
  return this->pipe_.read_handle ();
}

int
Handler::handle_timeout (const ACE_Time_Value &,
                         const void *)
{
  int me = this->dispatch_order_++;
  if (me != 1)
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("handle_timeout should be #1; it's %d\n"),
                me));
  else
    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Handler::handle_timeout\n")));

  return 0;
}

int
Handler::handle_output (ACE_HANDLE)
{
  int me = this->dispatch_order_++;
  if (me != 2)
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("handle_output should be #2; it's %d\n"),
                me));
  else
    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Handler::handle_output\n")));

  // Don't want to continually see writeable; only verify its relative order.
  this->reactor ()->mask_ops (this->pipe_.read_handle (),
                              ACE_Event_Handler::WRITE_MASK,
                              ACE_Reactor::CLR_MASK);

  return 0;
}

int
Handler::handle_input (ACE_HANDLE fd)
{
  int me = this->dispatch_order_++;
  if (me != 3)
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("handle_input should be #3; it's %d\n"),
                me));

  char buffer[BUFSIZ];
  ssize_t result = ACE::recv (fd, buffer, sizeof buffer);
  if (result != ssize_t (ACE_OS::strlen (message)))
    ACE_ERROR ((LM_ERROR, ACE_TEXT ("Handler recv'd %b bytes; expected %B\n"),
                result, ACE_OS::strlen (message)));
  buffer[result] = '\0';

  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Handler::handle_input: %C\n"), buffer));

  if (ACE_OS::strcmp (buffer, message) != 0)
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("Handler text mismatch; received \"%C\"; ")
                ACE_TEXT ("expected \"%C\"\n"),
                buffer, message));

  this->reactor ()->end_reactor_event_loop ();

  return 0;
}

static bool
test_reactor_dispatch_order (ACE_Reactor &reactor)
{
  Handler handler (reactor);
  if (!handler.ok_)
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Error initializing test; abort.\n")));
      return false;
    }

  bool ok_to_go = true;

  // This should trigger a call to <handle_input>.
  ssize_t result =
    ACE::send_n (handler.pipe_.write_handle (),
                 message,
                 ACE_OS::strlen (message));
  if (result != ssize_t (ACE_OS::strlen (message)))
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Handler sent %b bytes; should be %B\n"),
                  result, ACE_OS::strlen (message)));
      ok_to_go = false;
    }

  // This should trigger a call to <handle_timeout>.
  if (-1 == reactor.schedule_timer (&handler,
                                    0,
                                    ACE_Time_Value (0)))
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("schedule_timer")));
      ok_to_go = false;
    }

  // Suspend the handlers - only the timer should be dispatched
  ACE_Time_Value tv (1);
  reactor.suspend_handlers ();
  reactor.run_reactor_event_loop (tv);

  // only the timer should have fired
  if (handler.dispatch_order_ != 2)
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Incorrect number fired %d\n"),
                  handler.dispatch_order_));
      ok_to_go = false;
    }

  // Reset the dispatch_order_ count and schedule another timer
  handler.dispatch_order_ = 1;
  if (-1 == reactor.schedule_timer (&handler,
                                    0,
                                    ACE_Time_Value (0)))
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("schedule_timer")));
      ok_to_go = false;
    }

  // Resume the handlers - things should work now
  reactor.resume_handlers ();

  if (ok_to_go)
    {
      reactor.run_reactor_event_loop (tv);
    }

  if (0 != reactor.remove_handler (handler.pipe_.read_handle (),
                                   ACE_Event_Handler::ALL_EVENTS_MASK |
                                   ACE_Event_Handler::DONT_CALL))
    ACE_ERROR ((LM_ERROR,
                ACE_TEXT ("%p\n"),
                ACE_TEXT ("remover_handler pipe")));

  if (handler.dispatch_order_ != 4)
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Incorrect number fired %d\n"),
                  handler.dispatch_order_));
      ok_to_go = false;
    }

  return ok_to_go;
}

int
run_main (int, ACE_TCHAR *[])
{
  ACE_START_TEST (ACE_TEXT ("Refcounted_Event_Handler_Test_DevPoll"));
  int result = 0;

  ACE_Dev_Poll_Reactor dev_poll_reactor_impl;
  ACE_Reactor dev_poll_reactor (&dev_poll_reactor_impl);
  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Testing Dev Poll Reactor\n")));
  if (!test_reactor_dispatch_order (dev_poll_reactor))
    ++result;

  ACE_END_TEST;
  return result;
}
#else
int
run_main (int, ACE_TCHAR *[])
{
  ACE_START_TEST (ACE_TEXT ("Refcounted_Event_Handler_Test_DevPoll"));
  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Dev_Poll_Reactor is UNSUPPORTED on this platform\n")));
  ACE_END_TEST;
  return 0;
}
#endif /* ACE_HAS_DEV_POLL || ACE_HAS_EVENT_POLL */