source: tests/SystemQueue-tests.cc@ 12753

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

moved some (usually needed) code in the fixture

File size: 7.7 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 // check ordering
115 EXPECT_EQ( num, last_ordered_call + 1);
116
117 last_ordered_call = num;
118 }
119
120 /// like OrderedCall, but calls itself to test nested calls
121 void NestedOrderedCall(int from, int to)
122 {
123 // check ordering
124 OrderedCall(from);
125
126 // nested call
127 if ( from < to )
128 {
129 SystemQueue::instance().scheduleCall(
130 boost::bind(&SystemQueueTest::NestedOrderedCall,
131 this,
132 from+1,
133 to)
134 );
135 }
136 else
137 {
138 /// XXX because the current/old SystemQueue does not pass the Threading test,
139 /// we have to signal, that when all nested calls are finished,
140 /// so we need to set the checkmark here..
141
142 checkmark = true;
143 }
144 }
145
146 bool checkmark;
147 int last_ordered_call;
148};
149
150
151/**
152 * schedule a call and test whether it is actually performed by the SystemQueue
153 */
154TEST_F(SystemQueueTest, ScheduleCall)
155{
156 SystemQueue& sysq = SystemQueue::instance();
157 checkmark = false; // just to be sure..
158
159 // start
160 sysq.run();
161
162 // scheduleCall
163 sysq.scheduleCall(
164 boost::bind(&SystemQueueTest::Check, this)
165 );
166
167 // wait for the event to happen
168 wait_for_checkmark(MAX_WAIT);
169
170 // stop
171 sysq.cancel();
172
173 EXPECT_TRUE( checkmark ) << "Function was not called within " << MAX_WAIT << " microseconds.";
174}
175
176
177/**
178 * This test actually tests two things [sorry, but it's hard to test them separately!]
179 *
180 * - first: the SystemQueue should not consider itself empty, while an event is processed
181 * - second: SystemQueue events should be processed in parallel to the main thread
182 *
183 * NOTE: The timings here are not obvious, maybe they have to be adjusted on very slow machines
184 *
185 * NOTE: !! The current/old SystemQueue does NOT pass this test!!
186 *
187 * That's also why we need the unhandy wait_for_checkmark function,
188 * instead a wait_until_empty function.
189 */
190TEST_F(SystemQueueTest, DISABLED_Threading)
191{
192 SystemQueue& sysq = SystemQueue::instance();
193 checkmark = false; // just to be sure..
194
195 // start
196 sysq.run();
197
198 // scheduleCall
199 sysq.scheduleCall(
200 boost::bind(&SystemQueueTest::LongRunner, this)
201 );
202
203 // SystemQueue must not be empty as long as the event is not finished
204 if ( sysq.isEmpty() )
205 {
206 // assert that this test is actually meaningful
207 ASSERT_FALSE( checkmark )
208 << "NOTE: This is not necessarily a bug, maybe the timing just have to adjusted. Try to increase MAX_WAIT.";
209
210 EXPECT_TRUE( ! sysq.isEmpty() || checkmark );
211 }
212
213 // wait for the event to finish
214 wait_for_checkmark(MAX_WAIT);
215
216 // stop
217 sysq.cancel();
218
219 // even the long-runner should finally finish
220 EXPECT_TRUE( checkmark ) << "Function has not finished within " << MAX_WAIT << " microseconds.";
221}
222
223/**
224 * schedule multiple calls
225 *
226 * each call must be performed, in the correct order
227 *
228 * NOTE: The nested calls are not necessarily in order with calls scheduled from the main thread,
229 * that's fine, therefore we make sure the nested calls are done, before scheduling new ones.
230 */
231TEST_F(SystemQueueTest, MultipleCalls)
232{
233 SystemQueue& sysq = SystemQueue::instance();
234
235 // start
236 sysq.run();
237
238 sysq.scheduleCall( boost::bind(&SystemQueueTest::OrderedCall, this, 1) );
239 sysq.scheduleCall( boost::bind(&SystemQueueTest::OrderedCall, this, 2) );
240 sysq.scheduleCall( boost::bind(&SystemQueueTest::NestedOrderedCall, this, 3, 5) );
241
242 // make sure all nested calls are done
243 wait_for_checkmark(MAX_WAIT); // XXX should be "wait_until_empty() ...."
244
245 checkmark = false;
246 sysq.scheduleCall( boost::bind(&SystemQueueTest::OrderedCall, this, 6) );
247
248 // XXX same here... [ wait_until_empty() ]
249 sysq.scheduleCall( boost::bind(&SystemQueueTest::Check, this) );
250 wait_for_checkmark(MAX_WAIT);
251
252 // evaluation
253 EXPECT_EQ( 6, last_ordered_call);
254
255 // stop
256 sysq.cancel();
257}
258
259
260
261/**
262 * This subclass has some special member functions suitable for timing tests
263 */
264class SystemQueueTimingTest :
265 public SystemQueueTest
266{
267public:
268
269/**
270 * typical delay time
271 *
272 * should be long enough for meaningful tests,
273 * but should not lengthen the test excessivly
274 */
275#define DELAY_TIME 10 // ms
276#define DELAY_MARGIN 1000 // microseconds (1/1000 ms)
277
278
279 /// constructor
280 SystemQueueTimingTest() :
281 SystemQueueTest() /* super constructor */,
282 sysq( SystemQueue::instance() )
283 {
284 }
285
286 virtual void SetUp()
287 {
288 // start SystemQueue
289 sysq.run();
290 }
291
292
293 virtual void TearDown()
294 {
295 // stop SystemQueue
296 sysq.cancel();
297 }
298
299 SystemQueue& sysq;
300};
301
302
303/**
304 * schedules a delayed call and tests whether it is called (more or less timely..)
305 */
306TEST_F(SystemQueueTimingTest, DelayedCall)
307{
308 // scheduleCall
309 sysq.scheduleCall(
310 boost::bind(&SystemQueueTest::Check, this), DELAY_TIME
311 );
312
313 // noting to do until the delay is up..
314 usleep(DELAY_TIME + DELAY_MARGIN);
315
316 // wait for the event to happen
317 wait_for_checkmark(MAX_WAIT);
318
319 EXPECT_TRUE( checkmark ) << "Deleyed function was not called within delaytime ("
320 << DELAY_TIME << " ms) + " << (MAX_WAIT + DELAY_MARGIN) << " microseconds.";
321}
322
Note: See TracBrowser for help on using the repository browser.