Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / tests / Bug_1890_Regression_Test.cpp
blob0ca496a7c5a323f0c2f337bfaae5dfd5409bd81c
1 /**
2 * @file Bug_1890_Regression_Test.cpp
4 * Reproduces the problems reported in bug 1890
5 * http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=1890
7 * @author Carlos O'Ryan <coryan@atdesk.com>
8 * Based on a test provided by "Vadim" (no further details available)
9 */
11 #include "test_config.h"
13 #include "ace/Pipe.h"
14 #include "ace/Event_Handler.h"
15 #include "ace/Reactor.h"
16 #include "ace/Select_Reactor.h"
17 #include <memory>
19 int const nhandlers = 3;
21 /**
22 * This class is used to create real I/O in the test. To keep the I/O under
23 * control and keep the test to a single process we use ACE_Pipe. This class
24 * is known to work with the Reactor, in fact, that is its main function.
26 * Handler counts how many calls to handle_input() has the reactor performed.
27 * When bug 1890 is triggered the Reactor continues to call the timers, but it
28 * stops calling select() and the handle_input() functions.
30 class Handler : public ACE_Event_Handler
32 public:
33 Handler();
35 //FUZZ: disable check_for_lack_ACE_OS
36 /// Initialize the pipe and register with the reactor
37 int open(ACE_Reactor * reactor);
38 //FUZZ: enable check_for_lack_ACE_OS
40 /// Return the current count
41 size_t handle_input_count() const;
43 /// Write some data
44 void send_dummy_data();
46 /// Reactor callback
47 ACE_HANDLE get_handle() const override;
48 int handle_input(ACE_HANDLE) override;
50 private:
51 size_t handle_input_count_;
53 ACE_Pipe the_pipe_;
55 ACE_HANDLE handles_[2];
58 /**
59 * This is the main driver for the test. This timer is called by the reactor
60 * in a repeating interval. On the first @c initial_iterations the Timer
61 * writes data through all of its handlers. On iteration @c initial_iteration
62 * it triggers bug 1890 by removing all the handlers from the reactor, and
63 * then re-adding one handler.
65 class Timer : public ACE_Event_Handler
67 public:
68 Timer();
70 //FUZZ: disable check_for_lack_ACE_OS
71 int open(ACE_Reactor * reactor);
72 void close();
73 //FUZZ: enable check_for_lack_ACE_OS
75 bool check_expected_results() const;
77 int handle_timeout(ACE_Time_Value const &, void const*) override;
79 private:
80 void send_data_through_handlers();
81 void remove_some_handlers();
83 Handler & special_handler();
84 Handler const & special_handler() const;
86 private:
87 Handler handler_[nhandlers];
88 int iteration_;
90 size_t recorded_count_;
93 int
94 run_main (int, ACE_TCHAR *[])
96 ACE_START_TEST (ACE_TEXT ("Bug_1890_Regression_Test"));
98 bool success = true;
100 // Bug 1890 is all about ACE_Select_Reactor, so run it on that reactor
101 // regardless of platform.
102 ACE_Select_Reactor *impl_ptr = 0;
103 ACE_NEW_RETURN (impl_ptr, ACE_Select_Reactor, -1);
104 std::unique_ptr<ACE_Select_Reactor> auto_impl (impl_ptr);
106 ACE_Reactor reactor (impl_ptr);
108 // Create the timer, this is the main driver for the test
109 Timer * timer = new Timer;
111 // Initialize the timer and register with the reactor
112 if (-1 == timer->open (&reactor))
114 ACE_ERROR_RETURN ((LM_ERROR,
115 ACE_TEXT ("%p\n"),
116 ACE_TEXT ("Cannot initialize timer")),
117 -1);
120 reactor.run_reactor_event_loop ();
122 // Verify that the results are what we expect
123 if (!(success = timer->check_expected_results ()))
124 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Test failed\n")));
126 // Cleanup
127 timer->close ();
128 delete timer;
130 ACE_END_TEST;
132 return success ? 0 : -1;
135 Handler::Handler()
136 : handle_input_count_(0)
137 , the_pipe_()
142 Handler::open (ACE_Reactor * r)
144 if (-1 == the_pipe_.open (handles_))
146 return -1;
148 if (-1 == r->register_handler (this, ACE_Event_Handler::READ_MASK))
150 return -1;
152 return 0;
155 size_t
156 Handler::handle_input_count() const
158 return handle_input_count_;
161 void
162 Handler::send_dummy_data()
164 char buf[] = "dummy";
165 (void) the_pipe_.send (buf, sizeof (buf));
168 ACE_HANDLE
169 Handler::get_handle() const
171 return the_pipe_.read_handle ();
175 Handler::handle_input(ACE_HANDLE)
177 ++handle_input_count_;
178 // ACE_DEBUG((LM_DEBUG, "Handler::handle_input called for %d\n", h));
179 return 0;
182 int const initial_iterations = 5;
183 int const total_iterations = 10;
185 int const special_handler_index = nhandlers - 1;
187 Timer::Timer()
188 : iteration_(0)
189 , recorded_count_(0)
194 Timer::open (ACE_Reactor * r)
196 this->reactor (r);
198 // Initialize both handles and register them with the reactor for reading.
199 for (int i = 0; i != nhandlers; ++i)
201 if (-1 == handler_[i].open (r))
203 ACE_ERROR_RETURN ((LM_ERROR,
204 ACE_TEXT ("Could not open dummy handler %d %p\n"),
206 ACE_TEXT ("")),
207 -1);
211 ACE_Time_Value const interval(0, ACE_ONE_SECOND_IN_USECS / 10);
212 ACE_Time_Value const startup (0, ACE_ONE_SECOND_IN_USECS / 20);
214 if (-1 == r->schedule_timer (this, 0, startup, interval))
216 ACE_ERROR_RETURN ((LM_ERROR,
217 ACE_TEXT ("%p\n"),
218 ACE_TEXT ("Could not schedule timer")),
219 -1);
222 return 0;
225 void
226 Timer::close()
228 for (int i = 0; i != nhandlers; ++i)
230 this->reactor ()->remove_handler (&handler_[i],
231 ACE_Event_Handler::ALL_EVENTS_MASK |
232 ACE_Event_Handler::DONT_CALL);
234 this->reactor ()->cancel_timer (this);
237 bool
238 Timer::check_expected_results() const
240 if (this->recorded_count_ < this->special_handler ().handle_input_count ())
242 return true;
244 ACE_ERROR ((LM_ERROR,
245 ACE_TEXT ("recorded_count %B, special_handler count %B\n"),
246 this->recorded_count_,
247 this->special_handler ().handle_input_count ()));
248 return false;
252 Timer::handle_timeout(ACE_Time_Value const &, void const *)
254 if (iteration_ == 0)
256 send_data_through_handlers();
259 ++iteration_;
260 if (iteration_ < initial_iterations)
262 return 0;
265 if (iteration_ == initial_iterations)
267 remove_some_handlers();
268 recorded_count_ = special_handler().handle_input_count();
269 return 0;
272 if (iteration_ < total_iterations)
274 return 0;
277 reactor()->end_reactor_event_loop();
279 return 0;
282 void
283 Timer::send_data_through_handlers()
285 for (int i = 0; i != nhandlers; ++i)
287 handler_[i].send_dummy_data();
291 void
292 Timer::remove_some_handlers()
294 // The reactor may not get around to callbacks on deletion until the test
295 // is over.
296 ACE_Reactor_Mask mask =
297 ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL;
298 for (int i = 0; i != nhandlers; ++i)
300 if (-1 == reactor()->remove_handler(&handler_[i], mask))
302 ACE_ERROR ((LM_ERROR,
303 ACE_TEXT ("Cannot remove handler %d in %p\n"),
305 ACE_TEXT ("timeout")));
309 if (-1 == reactor()->register_handler(&special_handler(),
310 ACE_Event_Handler::ALL_EVENTS_MASK))
312 ACE_ERROR ((LM_ERROR,
313 ACE_TEXT ("Cannot add back special handler in %p\n"),
314 ACE_TEXT ("timeout")));
318 Handler & Timer::special_handler()
320 return handler_[special_handler_index];
323 Handler const & Timer::special_handler() const
325 return handler_[special_handler_index];