summaryrefslogtreecommitdiff
path: root/tests/Reactor_Dispatch_Order_Test.cpp
blob: d6263f091d33b021e4aa402175166e6998269926 (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
// $Id$

// ============================================================================
//
// = LIBRARY
//    tests
//
// = FILENAME
//    Reactor_Dispatch_Order_Test.cpp
//
// = DESCRIPTION
//    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/Pipe.h"
#include "ace/ACE.h"

ACE_RCSID(tests, Reactor_Dispatch_Order_Test, "$Id$")

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

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

  ~Handler();

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

  int handle_input (ACE_HANDLE fd);

  int handle_output (ACE_HANDLE fd);

  // 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_;
};

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

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

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")));

#if defined (__OpenBSD__) || defined (ACE_VXWORKS) || defined (__Lynx__)
  // All that we need written has been written, so don't
  // call handle_output again.
  this->reactor ()->mask_ops (this->pipe_.read_handle (),
                              ACE_Event_Handler::WRITE_MASK,
                              ACE_Reactor::CLR_MASK);
#endif /* __OpenBSD__ || ACE_VXWORKS || __Lynx__ */

  return 0;
}

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

  char buffer[BUFSIZ];
  ssize_t result = ACE::recv (fd, buffer, sizeof buffer);

  ACE_ASSERT (result == ssize_t (ACE_OS::strlen (message)));
  buffer[result] = '\0';

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

  ACE_ASSERT (ACE_OS::strcmp (buffer,
                              message) == 0);

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

  return 0;
}

static void
test_reactor_dispatch_order (ACE_Reactor &reactor)
{
  Handler handler (reactor);

  // This should trigger a call to <handle_input>.
  ssize_t result =
    ACE::send_n (handler.pipe_.write_handle (),
                 message,
                 ACE_OS::strlen (message));
  ACE_ASSERT (result == ssize_t (ACE_OS::strlen (message)));

  // This should trigger a call to <handle_timeout>.
  long retn =
    reactor.schedule_timer (&handler,
                            0,
                            ACE_Time_Value (0));
  ACE_ASSERT (retn != -1);

  reactor.run_reactor_event_loop ();

  result =
    reactor.remove_handler (handler.pipe_.read_handle (),
                            ACE_Event_Handler::ALL_EVENTS_MASK |
                            ACE_Event_Handler::DONT_CALL);
  ACE_ASSERT (result == 0);
}

int
run_main (int, ACE_TCHAR *[])
{
  ACE_START_TEST (ACE_TEXT ("Reactor_Dispatch_Order_Test"));

  ACE_Select_Reactor select_reactor_impl;
  ACE_Reactor select_reactor (&select_reactor_impl);
  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Testing ACE_Select_Reactor\n")));
  test_reactor_dispatch_order (select_reactor);

  // WinCE can't do the necessary Winsock 2 things for WFMO_Reactor.
#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)

  ACE_WFMO_Reactor wfmo_reactor_impl;
  ACE_Reactor wfmo_reactor (&wfmo_reactor_impl);
  ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Testing ACE_WFMO_Reactor\n")));
  test_reactor_dispatch_order (wfmo_reactor);

#endif /* ACE_WIN32 && !ACE_HAS_WINCE */

  ACE_END_TEST;
  return 0;
}