Compile fixes
[ACE_TAO.git] / ACE / tests / Bug_2540_Regression_Test.cpp
blob98129661703078c9d3228aa5e79af45cd1301d65
1 /**
2 * @file Bug_2540_Regression_Test.cpp
4 * Reproduces the problems reported in bug 2540
5 * http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=2540
7 * @author Carlos O'Ryan <coryan@atdesk.com>
8 * Based on Bug_1890_Regression_Test
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 "ace/Auto_Ptr.h"
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 2540 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 /// Removes itself from the reactor on the next call to handle_input()
47 void simulate_socket_closure();
49 /// Reactor callback
50 ACE_HANDLE get_handle() const override;
51 int handle_input(ACE_HANDLE) override;
53 private:
54 bool auto_remove_flag_;
56 size_t handle_input_count_;
58 ACE_Pipe the_pipe_;
60 ACE_HANDLE handles_[2];
63 /**
64 * This is the main driver for the test. This timer is called by the reactor
65 * in a repeating interval. On the first @c initial_iterations the Timer
66 * writes data through all of its handlers. On iteration @c initial_iteration
67 * it triggers bug 2540 by removing two handlers from the reactor.
69 class Timer : public ACE_Event_Handler
71 public:
72 Timer();
74 //FUZZ: disable check_for_lack_ACE_OS
75 int open(ACE_Reactor * reactor);
76 void close();
77 //FUZZ: enable check_for_lack_ACE_OS
79 bool check_expected_results() const;
81 int handle_timeout(ACE_Time_Value const &, void const*) override;
83 private:
84 void send_data_through_handlers();
85 void remove_some_handlers();
87 Handler & special_handler();
88 Handler const & special_handler() const;
90 private:
91 Handler handler_[nhandlers];
92 int iteration_;
94 size_t recorded_count_;
97 int
98 run_main (int, ACE_TCHAR *[])
100 ACE_START_TEST (ACE_TEXT ("Bug_2540_Regression_Test"));
102 // Bug 2540 is all about ACE_Select_Reactor, so run it on that reactor
103 // regardless of platform. In particular, this test relies on a handler
104 // that doesn't consume ready-to-read data being called back - this won't
105 // happen with ACE_WFMO_Reactor.
106 ACE_Select_Reactor *impl_ptr = 0;
107 ACE_NEW_RETURN (impl_ptr, ACE_Select_Reactor, -1);
108 std::unique_ptr<ACE_Select_Reactor> auto_impl (impl_ptr);
110 ACE_Reactor reactor (impl_ptr);
112 // Create the timer, this is the main driver for the test
113 Timer * timer = new Timer;
115 // Initialize the timer and register with the reactor
116 if (-1 == timer->open (&reactor))
118 ACE_ERROR_RETURN ((LM_ERROR, "Cannot initialize timer\n"), -1);
121 reactor.run_reactor_event_loop ();
123 // Verify that the results are what we expect
124 if (!timer->check_expected_results ())
126 ACE_ERROR_RETURN ((LM_ERROR, "Test failed\n"), -1);
129 // Cleanup
130 timer->close ();
131 delete timer;
133 ACE_END_TEST;
135 return 0;
138 Handler::Handler()
139 : auto_remove_flag_(false)
140 , handle_input_count_(0)
141 , the_pipe_()
145 int Handler::open(ACE_Reactor * r)
147 if(-1 == the_pipe_.open(handles_))
149 return -1;
151 if(-1 == r->register_handler(this, ACE_Event_Handler::READ_MASK))
153 return -1;
155 return 0;
158 size_t Handler::handle_input_count() const
160 return handle_input_count_;
163 void Handler::send_dummy_data()
165 char buf[] = "dummy";
166 (void) the_pipe_.send(buf, sizeof(buf));
169 void Handler::simulate_socket_closure()
171 auto_remove_flag_ = true;
174 ACE_HANDLE Handler::get_handle() const
176 return the_pipe_.read_handle();
179 int Handler::handle_input(ACE_HANDLE /* h */)
181 ++handle_input_count_;
182 // ACE_DEBUG((LM_DEBUG, "Handler::handle_input called for %d\n", h));
184 if(auto_remove_flag_)
186 auto_remove_flag_ = false;
187 return -1;
190 return 0;
193 int const initial_iterations = 5;
194 int const total_iterations = 10;
196 int const special_handler_index = nhandlers - 1;
198 Timer::Timer()
199 : iteration_(0)
200 , recorded_count_(0)
204 int Timer::open(ACE_Reactor * r)
206 this->reactor(r);
208 // Initialize both handles and register them with the reactor for reading.
209 for(int i = 0; i != nhandlers; ++i)
211 if (-1 == handler_[i].open(r))
213 ACE_ERROR_RETURN ((LM_ERROR, "Could not open dummy handler %d\n", i), -1);
217 ACE_Time_Value const interval(0, ACE_ONE_SECOND_IN_USECS / 10);
218 ACE_Time_Value const startup (0, ACE_ONE_SECOND_IN_USECS / 20);
220 if ( -1 == r->schedule_timer(this, 0, startup, interval))
222 ACE_ERROR_RETURN((LM_ERROR, "Could not schedule timer\n"), -1);
225 return 0;
228 void Timer::close()
230 for(int i = 0; i != nhandlers; ++i)
232 reactor()->remove_handler(&handler_[i], ACE_Event_Handler::ALL_EVENTS_MASK);
234 reactor()->cancel_timer(this);
237 bool Timer::check_expected_results() const
239 // We expect at least one more call after the other handlers are removed.
240 if(recorded_count_ + 1 < special_handler().handle_input_count() )
242 return true;
244 return false;
247 int Timer::handle_timeout(ACE_Time_Value const &, void const *)
249 if (iteration_ == 0)
251 // Sending data on the first iteration makes the handles always
252 // "ready" for reading because the Handler::handle_input() function
253 // never consumes the data.
254 send_data_through_handlers();
257 ++iteration_;
258 if (iteration_ < initial_iterations)
260 // The first iterations are there just to prime things.
261 return 0;
264 if (iteration_ == initial_iterations)
266 // We expect the special_handler() to work normally after this
267 // iteration, i.e., more calls to handle_input() should be delivered
268 // to it.
269 recorded_count_ = special_handler().handle_input_count();
271 // Remove the handlers the next time the loop runs
272 remove_some_handlers();
274 // Run the event loop, this causes the handlers to be removed from the
275 // reactor, except for special_handler()
276 ACE_Time_Value interval(0, ACE_ONE_SECOND_IN_USECS / 50);
277 reactor()->handle_events(&interval);
279 return 0;
282 if (iteration_ < total_iterations)
284 // Run a while more to make sure the special_handler() is used.
285 return 0;
288 reactor()->end_reactor_event_loop();
290 return 0;
293 void Timer::send_data_through_handlers()
295 for(int i = 0; i != nhandlers; ++i)
297 handler_[i].send_dummy_data();
301 void Timer::remove_some_handlers()
303 for(int i = 0; i != nhandlers - 1; ++i)
305 handler_[i].simulate_socket_closure();
309 Handler & Timer::special_handler()
311 return handler_[special_handler_index];
314 Handler const & Timer::special_handler() const
316 return handler_[special_handler_index];