source: tests/SystemQueue-tests.cc@ 12754

Last change on this file since 12754 was 12754, checked in by hock@…, 11 years ago

TEST_F(SystemQueueTimingTest, MultipleCalls)

which fails, every time.. (but should not)

File size: 8.9 KB
Line 
1#include "gtest/gtest.h"
2#include "ariba/utility/system/SystemQueue.h"
3
4#include <unistd.h> // usleep
5
6#include <ostream>
7
8using namespace ::testing;
9using namespace ariba::utility;
10using namespace std;
11
12/**
13 * Tests if the SystemQueue is initialized empty and not running.
14 */
15TEST(SystemQueue, Instantiation)
16{
17 SystemQueue& sysq = SystemQueue::instance();
18
19// cout << &sysq << endl;
20
21 EXPECT_FALSE( sysq.isRunning() );
22 EXPECT_TRUE( sysq.isEmpty() );
23}
24
25
26/**
27 * Tests whether calling the SystemQueue::instance() always returns the same object.
28 *
29 * NOTE: This is an easy case, since this is the same compile unit..
30 * But can't hurt to test it anyway.
31 */
32TEST(SystemQueue, Singleton)
33{
34 SystemQueue& sysq = SystemQueue::instance();
35 SystemQueue& sysq2 = SystemQueue::instance();
36
37// cout << &sysq << endl;
38
39 EXPECT_TRUE( &sysq == &sysq2 );
40}
41
42
43/**
44 * Start and stop the SystemQueue
45 */
46TEST(SystemQueue, StartStop)
47{
48 SystemQueue& sysq = SystemQueue::instance();
49
50 EXPECT_FALSE( sysq.isRunning() );
51
52 // start
53 sysq.run();
54
55 EXPECT_TRUE( sysq.isRunning() );
56
57 // stop
58 sysq.cancel();
59
60 EXPECT_FALSE( sysq.isRunning() );
61}
62
63
64/**
65 * Test fixture
66 *
67 * class that can be called by the SystemQueue
68 */
69// To use a test fixture, derive a class from testing::Test.
70class SystemQueueTest :
71 public testing::Test
72{
73public:
74
75// sleep time when waiting for the system queue (max total / each step)
76#define MAX_WAIT 100 // microseconds
77#define SLEEP_TIME 10 // microseconds
78
79 SystemQueueTest() :
80 checkmark(false),
81 last_ordered_call(0)
82 {
83 }
84
85 void Check()
86 {
87 checkmark = true;
88 }
89
90 void LongRunner()
91 {
92 usleep( MAX_WAIT / 2 );
93
94 checkmark = true;
95 }
96
97
98 /// wait for the checkmark to be set by a SystemQueue call, (but not too long!)
99 void wait_for_checkmark(int max_wait = MAX_WAIT)
100 {
101 for ( int i = 0; i < max_wait / SLEEP_TIME; i++)
102 {
103 if ( checkmark )
104 break;
105
106 cout << "/// sleeping for " << SLEEP_TIME << " microseconds ..." << endl;
107 usleep(SLEEP_TIME);
108 }
109 }
110
111 /// call that checks wheather it was performed in order
112 void OrderedCall(int num)
113 {
114 // XXX
115 cout << "### OrderedCall num: " << num << endl;
116
117 // check ordering
118 EXPECT_EQ( num, last_ordered_call + 1);
119
120 last_ordered_call = num;
121 }
122
123 /// like OrderedCall, but calls itself to test nested calls
124 void NestedOrderedCall(int from, int to)
125 {
126 // check ordering
127 OrderedCall(from);
128
129 // nested call
130 if ( from < to )
131 {
132 SystemQueue::instance().scheduleCall(
133 boost::bind(&SystemQueueTest::NestedOrderedCall,
134 this,
135 from+1,
136 to)
137 );
138 }
139 else
140 {
141 /// XXX because the current/old SystemQueue does not pass the Threading test,
142 /// we have to signal, that when all nested calls are finished,
143 /// so we need to set the checkmark here..
144
145 checkmark = true;
146 }
147 }
148
149 bool checkmark;
150 int last_ordered_call;
151};
152
153
154/**
155 * schedule a call and test whether it is actually performed by the SystemQueue
156 */
157TEST_F(SystemQueueTest, ScheduleCall)
158{
159 SystemQueue& sysq = SystemQueue::instance();
160 checkmark = false; // just to be sure..
161
162 // start
163 sysq.run();
164
165 // scheduleCall
166 sysq.scheduleCall(
167 boost::bind(&SystemQueueTest::Check, this)
168 );
169
170 // wait for the event to happen
171 wait_for_checkmark(MAX_WAIT);
172
173 // stop
174 sysq.cancel();
175
176 EXPECT_TRUE( checkmark ) << "Function was not called within " << MAX_WAIT << " microseconds.";
177}
178
179
180/**
181 * This test actually tests two things [sorry, but it's hard to test them separately!]
182 *
183 * - first: the SystemQueue should not consider itself empty, while an event is processed
184 * - second: SystemQueue events should be processed in parallel to the main thread
185 *
186 * NOTE: The timings here are not obvious, maybe they have to be adjusted on very slow machines
187 *
188 * NOTE: !! The current/old SystemQueue does NOT pass this test!!
189 *
190 * That's also why we need the unhandy wait_for_checkmark function,
191 * instead a wait_until_empty function.
192 */
193TEST_F(SystemQueueTest, DISABLED_Threading)
194{
195 SystemQueue& sysq = SystemQueue::instance();
196 checkmark = false; // just to be sure..
197
198 // start
199 sysq.run();
200
201 // scheduleCall
202 sysq.scheduleCall(
203 boost::bind(&SystemQueueTest::LongRunner, this)
204 );
205
206 // SystemQueue must not be empty as long as the event is not finished
207 if ( sysq.isEmpty() )
208 {
209 // assert that this test is actually meaningful
210 ASSERT_FALSE( checkmark )
211 << "NOTE: This is not necessarily a bug, maybe the timing just have to adjusted. Try to increase MAX_WAIT.";
212
213 EXPECT_TRUE( ! sysq.isEmpty() || checkmark );
214 }
215
216 // wait for the event to finish
217 wait_for_checkmark(MAX_WAIT);
218
219 // stop
220 sysq.cancel();
221
222 // even the long-runner should finally finish
223 EXPECT_TRUE( checkmark ) << "Function has not finished within " << MAX_WAIT << " microseconds.";
224}
225
226/**
227 * schedule multiple calls
228 *
229 * each call must be performed, in the correct order
230 *
231 * NOTE: The nested calls are not necessarily in order with calls scheduled from the main thread,
232 * that's fine, therefore we make sure the nested calls are done, before scheduling new ones.
233 */
234TEST_F(SystemQueueTest, MultipleCalls)
235{
236 SystemQueue& sysq = SystemQueue::instance();
237
238 // start
239 sysq.run();
240
241 sysq.scheduleCall( boost::bind(&SystemQueueTest::OrderedCall, this, 1) );
242 sysq.scheduleCall( boost::bind(&SystemQueueTest::OrderedCall, this, 2) );
243 sysq.scheduleCall( boost::bind(&SystemQueueTest::NestedOrderedCall, this, 3, 5) );
244
245 // make sure all nested calls are done
246 wait_for_checkmark(MAX_WAIT); // XXX should be "wait_until_empty() ...."
247
248 checkmark = false;
249 sysq.scheduleCall( boost::bind(&SystemQueueTest::OrderedCall, this, 6) );
250
251 // XXX same here... [ wait_until_empty() ]
252 sysq.scheduleCall( boost::bind(&SystemQueueTest::Check, this) );
253 wait_for_checkmark(MAX_WAIT);
254
255 // evaluation
256 EXPECT_EQ( 6, last_ordered_call);
257
258 // stop
259 sysq.cancel();
260}
261
262
263
264/**
265 * This subclass has some special member functions suitable for timing tests
266 */
267class SystemQueueTimingTest :
268 public SystemQueueTest
269{
270public:
271
272/**
273 * typical delay time
274 *
275 * should be long enough for meaningful tests,
276 * but should not lengthen the test excessivly
277 */
278#define DELAY_TIME 20 // ms
279#define DELAY_MARGIN 2000 // microseconds (1/1000 ms)
280
281
282 /// constructor
283 SystemQueueTimingTest() :
284 SystemQueueTest() /* super constructor */,
285 sysq( SystemQueue::instance() )
286 {
287 }
288
289 virtual void SetUp()
290 {
291 // start SystemQueue
292 sysq.run();
293 }
294
295
296 virtual void TearDown()
297 {
298 // stop SystemQueue
299 sysq.cancel();
300 }
301
302 SystemQueue& sysq;
303};
304
305
306/**
307 * schedules a delayed call and tests whether it is called (more or less timely..)
308 */
309TEST_F(SystemQueueTimingTest, DelayedCall)
310{
311 // scheduleCall
312 sysq.scheduleCall(
313 boost::bind(&SystemQueueTimingTest::Check, this), DELAY_TIME
314 );
315
316 // noting to do until the delay is up..
317 usleep(DELAY_TIME + DELAY_MARGIN*10); // XXX margin too high (TODO lower when SysQ is reimplemented)
318
319 // wait for the event to happen
320 wait_for_checkmark(MAX_WAIT);
321
322 EXPECT_TRUE( checkmark ) << "Delayed function was not called within delaytime ("
323 << DELAY_TIME << " ms) + " << (MAX_WAIT + DELAY_MARGIN) << " microseconds.";
324}
325
326
327/**
328 * schedules a delayed call and tests whether it is called (more or less timely..)
329 */
330TEST_F(SystemQueueTimingTest, MultipleCalls)
331{
332 // schedule 4th call
333 sysq.scheduleCall(
334 boost::bind(&SystemQueueTest::OrderedCall, this, 4),
335 DELAY_TIME*3
336 );
337
338 // schedule 2nd call
339 sysq.scheduleCall(
340 boost::bind(&SystemQueueTest::OrderedCall, this, 2),
341 DELAY_TIME*1
342 );
343
344 // schedule 3rd call
345 sysq.scheduleCall(
346 boost::bind(&SystemQueueTest::OrderedCall, this, 3),
347 DELAY_TIME*2
348 );
349
350 // schedule 1st call (without delay)
351 sysq.scheduleCall(
352 boost::bind(&SystemQueueTest::OrderedCall, this, 1)
353 );
354
355
356 // XXX the usual bug..
357 sysq.scheduleCall(
358 boost::bind(&SystemQueueTest::Check, this),
359 DELAY_TIME*4
360 );
361
362 // noting to do until the delay is up..
363 usleep(DELAY_TIME*4 + DELAY_MARGIN*100); // XXX margin too high
364
365 // wait for the event to happen
366 wait_for_checkmark(MAX_WAIT);
367
368 // evaluation
369 EXPECT_EQ( 4, last_ordered_call);
370}
Note: See TracBrowser for help on using the repository browser.