Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
dispatcher-looper-test.cpp
Go to the documentation of this file.
1/*
2 DispatcherLooper(Test) - verify loop control and timing functionality of SteamDispatcher
3
4 Copyright (C)
5 2016, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12* *****************************************************************/
13
14
15#include "lib/test/run.hpp"
17
18#include <chrono>
19#include <thread>
20
21
22namespace steam {
23namespace control {
24namespace test {
25
26 using std::this_thread::sleep_for;
27 using namespace std::chrono_literals;
28
29
30 namespace { // test fixture...
31
32 using Dur = std::chrono::duration<double, std::milli>;
33
39
40 bool
41 isFast (milliseconds timeoutDelay)
42 {
44 and 0ms < timeoutDelay;
45 }
46
47 bool
48 isSlow (milliseconds timeoutDelay)
49 {
51 }
52
53 bool
54 isDisabled (milliseconds timeoutDelay)
55 {
56 return 0ms == timeoutDelay;
57 }
58
59
66 struct Setup
67 {
68 bool has_commands_in_queue = false;
69
70 Looper
72 {
73 return Looper([&](){ return has_commands_in_queue; });
74 }
75 };
76
77 }//(End) test fixture
78
79
80
81
82
83
84
85 /******************************************************************************/
95 class DispatcherLooper_test : public Test
96 {
97
98
99 virtual void
109
110
111 void
113 {
114 Setup setup;
115 Looper looper = setup.install();
116
117 CHECK (not looper.isDying());
118 CHECK (looper.shallLoop());
119 CHECK (not looper.runBuild());
120 CHECK (isDisabled (looper.getTimeout()));
121
122 setup.has_commands_in_queue = true;
123 CHECK (looper.requireAction());
124
125 milliseconds timeout = looper.getTimeout();
126 CHECK (10ms < timeout, "configured idle timeout %2l to short", timeout.count());
127 CHECK (timeout < 800ms, "configured idle timeout %3l to long", timeout.count());
128 }
129
130
131 void
133 {
134 Setup setup;
135 Looper looper = setup.install();
136
137 CHECK (not looper.isDying());
138 CHECK (looper.shallLoop());
139
140 looper.triggerShutdown();
141 CHECK (looper.isDying());
142 CHECK (not looper.shallLoop());
143 }
144
145
146 void
148 {
149 Setup setup;
150 Looper looper = setup.install();
151
152 CHECK (not looper.isDying());
153 CHECK (looper.shallLoop());
154
155 CHECK (not looper.requireAction());
156 CHECK (not looper.isWorking());
157 CHECK ( looper.isIdle());
158
159 setup.has_commands_in_queue = true;
160
161 CHECK ( looper.requireAction());
162 CHECK ( looper.isWorking());
163 CHECK (not looper.isIdle());
164 CHECK (looper.shallLoop());
165
166 setup.has_commands_in_queue = false;
167 looper.markStateProcessed(); // after command processing
168 CHECK (not looper.requireAction()); // stops immediate work state
169 CHECK ( looper.useTimeout()); // but still performs timeout
170 CHECK (not looper.isWorking());
171 CHECK (not looper.isIdle()); // still need to run the builder
172
173 looper.markStateProcessed(); // second round-trip, after builder run
174
175 CHECK (not looper.requireAction());
176 CHECK (not looper.isWorking());
177 CHECK ( looper.isIdle());
178 CHECK (looper.shallLoop());
179
180 looper.triggerShutdown();
181
182 CHECK (not looper.shallLoop());
183
184 CHECK ( looper.requireAction());
185 CHECK (not looper.isWorking());
186 CHECK (not looper.isIdle());
187 }
188
189
190 void
192 {
193 Setup setup;
194 Looper looper = setup.install();
195
196 CHECK (not looper.isDying());
197 CHECK (looper.shallLoop());
198
199 CHECK (not looper.requireAction());
200 CHECK (not looper.isWorking());
201 CHECK ( looper.isIdle());
202
203 setup.has_commands_in_queue = true;
204
205 CHECK ( looper.requireAction());
206 CHECK ( looper.isWorking());
207 CHECK (not looper.isIdle());
208 CHECK ( looper.shallLoop());
209 CHECK (not looper.isDying());
210
211 looper.triggerShutdown();
212
213 CHECK ( looper.requireAction());
214 CHECK (not looper.isWorking());
215 CHECK (not looper.isIdle());
216 CHECK (not looper.shallLoop());
217 CHECK ( looper.isDying());
218
219 setup.has_commands_in_queue = false;
220
221 CHECK ( looper.requireAction());
222 CHECK (not looper.isWorking());
223 CHECK (not looper.isIdle());
224 CHECK (not looper.shallLoop());
225 CHECK ( looper.isDying());
226
227 setup.has_commands_in_queue = true;
228
229 CHECK ( looper.requireAction());
230 CHECK (not looper.isWorking());
231 CHECK (not looper.isIdle());
232 CHECK (not looper.shallLoop());
233 CHECK ( looper.isDying());
234 }
235
236
237 void
239 {
240 Setup setup;
241 Looper looper = setup.install();
242
243 CHECK (not looper.requireAction());
244 CHECK (not looper.isDisabled());
245 CHECK (not looper.isWorking());
246 CHECK ( looper.isIdle());
247 CHECK ( looper.shallLoop());
248 CHECK (not looper.isDying());
249
250 setup.has_commands_in_queue = true; // normal operation: pending commands will be processed
251
252 CHECK ( looper.requireAction()); // ..causes wake-up
253 CHECK (not looper.isDisabled());
254 CHECK ( looper.isWorking());
255 CHECK (not looper.isIdle());
256 CHECK ( looper.shallLoop());
257 CHECK (not looper.isDying());
258
259 looper.enableProcessing(false); // disable processing
260
261 CHECK (not looper.requireAction());
262 CHECK ( looper.isDisabled());
263 CHECK (not looper.isWorking());
264 CHECK (not looper.isIdle());
265 CHECK ( looper.shallLoop());
266 CHECK (not looper.isDying());
267
268 setup.has_commands_in_queue = false; // while disabled, state of the command queue has no effect
269
270 CHECK (not looper.requireAction());
271 CHECK ( looper.isDisabled());
272 CHECK (not looper.isWorking());
273 CHECK (not looper.isIdle());
274 CHECK ( looper.shallLoop());
275 CHECK (not looper.isDying());
276
277 setup.has_commands_in_queue = true;
278
279 CHECK (not looper.requireAction());
280 CHECK ( looper.isDisabled());
281 CHECK (not looper.isWorking());
282 CHECK (not looper.isIdle());
283 CHECK ( looper.shallLoop());
284 CHECK (not looper.isDying());
285
286 looper.enableProcessing(); // resume normal operation
287
288 CHECK ( looper.requireAction());
289 CHECK (not looper.isDisabled());
290 CHECK ( looper.isWorking());
291 CHECK (not looper.isIdle());
292 CHECK ( looper.shallLoop());
293 CHECK (not looper.isDying());
294
295 looper.enableProcessing(false); // disable again
296
297 CHECK (not looper.requireAction());
298 CHECK ( looper.isDisabled());
299 CHECK (not looper.isWorking());
300 CHECK (not looper.isIdle());
301 CHECK ( looper.shallLoop());
302 CHECK (not looper.isDying());
303
304 looper.triggerShutdown(); // wake-up for shutdown even from disabled state
305
306 CHECK ( looper.requireAction());
307 CHECK ( looper.isDisabled());
308 CHECK (not looper.isWorking());
309 CHECK (not looper.isIdle());
310 CHECK (not looper.shallLoop());
311 CHECK ( looper.isDying());
312 }
313
314
324 void
326 {
327 Setup setup;
328 Looper looper = setup.install();
329
330 CHECK (not looper.requireAction());
331 CHECK (not looper.isDisabled());
332 CHECK (not looper.isWorking());
333 CHECK (not looper.runBuild());
334 CHECK ( looper.isIdle());
335
336 setup.has_commands_in_queue = true; // regular command processing
337
338 CHECK ( looper.requireAction());
339 CHECK (not looper.isDisabled());
340 CHECK ( looper.isWorking());
341 CHECK (not looper.runBuild());
342 CHECK (not looper.isIdle());
343
344 looper.markStateProcessed(); // at least one command has been handled
345
346 CHECK ( looper.requireAction());
347 CHECK (not looper.isDisabled());
348 CHECK ( looper.isWorking());
349 CHECK (not looper.runBuild()); // ...note: build not yet triggered
350 CHECK (not looper.isIdle());
351
352 CHECK (isSlow (looper.getTimeout()));
353
354
355 looper.markStateProcessed(); // next processing round: further command(s) processed,
356 // yet still more commands pending...
357 CHECK ( looper.requireAction());
358 CHECK (not looper.isDisabled());
359 CHECK ( looper.isWorking());
360 CHECK (not looper.runBuild()); // ...build still postponed
361 CHECK (not looper.isIdle());
362
363 sleep_for (800ms); // let's assume we did command processing for a long time...
364
365 CHECK ( looper.requireAction());
366 CHECK (not looper.isDisabled());
367 CHECK ( looper.isWorking());
368 CHECK ( looper.runBuild()); // ...after some time of command processing, a build run is forced
369 CHECK (not looper.isIdle());
370
371 looper.markStateProcessed(); // and when the builder run is confirmed...
372
373 CHECK ( looper.requireAction());
374 CHECK (not looper.isDisabled());
375 CHECK ( looper.isWorking());
376 CHECK (not looper.runBuild()); // ...we are back to normal working state (build postponed)
377 CHECK (not looper.isIdle());
378
379
380 setup.has_commands_in_queue = false; // now emptied our queue
381
382 CHECK (not looper.requireAction());
383 CHECK (not looper.isDisabled());
384 CHECK (not looper.isWorking());
385 CHECK ( looper.runBuild()); // ...note: now build will be triggered
386 CHECK (not looper.isIdle());
387
388 CHECK (isFast (looper.getTimeout())); // ...but only after a short wait period,
389 // since not looper.requireAction()
390
391
392 looper.markStateProcessed(); // next processing round: invoked builder,
393 // and no more commands commands pending...
394 CHECK (not looper.requireAction());
395 CHECK (not looper.isDisabled());
396 CHECK (not looper.isWorking());
397 CHECK (not looper.runBuild()); // ...note: now done with building
398 CHECK ( looper.isIdle());
399
400 CHECK (isDisabled(looper.getTimeout())); // ...now Dispatcher is idle and goes to sleep
401
402
403 setup.has_commands_in_queue = true; // next command pending
404
405 CHECK ( looper.requireAction()); // return to work mode
406 CHECK (not looper.isDisabled());
407 CHECK ( looper.isWorking());
408 CHECK (not looper.runBuild());
409 CHECK (not looper.isIdle());
410
411 setup.has_commands_in_queue = false; // now let's assume command has been processed
412 looper.markStateProcessed(); // and queue is empty again
413
414 CHECK (not looper.requireAction());
415 CHECK (not looper.isDisabled());
416 CHECK (not looper.isWorking());
417 CHECK ( looper.runBuild());
418 CHECK (not looper.isIdle());
419
420 CHECK (isFast (looper.getTimeout())); // now build *would* be triggered after short timeout, but..
421
422
423 looper.enableProcessing(false); // disable processing
424
425 CHECK (not looper.requireAction());
426 CHECK ( looper.isDisabled());
427 CHECK (not looper.isWorking());
428 CHECK (not looper.runBuild()); // ...note: dirty state hidden by disabled state
429 CHECK (not looper.isIdle());
430
431 CHECK (isDisabled (looper.getTimeout()));
432
433
434 looper.enableProcessing(true); // enable back
435
436 CHECK (not looper.requireAction());
437 CHECK (not looper.isDisabled());
438 CHECK (not looper.isWorking());
439 CHECK ( looper.runBuild()); // ...note: dirty state revealed again
440 CHECK (not looper.isIdle());
441
442 CHECK (isFast (looper.getTimeout()));
443
444 looper.enableProcessing(false); // disable processing
445 looper.markStateProcessed(); // let's assume builder was running and is now finished
446
447 CHECK (not looper.requireAction());
448 CHECK ( looper.isDisabled());
449 CHECK (not looper.isWorking());
450 CHECK (not looper.runBuild()); // ...note: dirty state not obvious
451 CHECK (not looper.isIdle());
452
453 CHECK (isDisabled (looper.getTimeout()));
454
455
456 looper.enableProcessing(true); // enable back
457 // NOTE special twist: it's unclear, if builder was triggered before the disabled state...
458 CHECK (isFast (looper.getTimeout())); // ...and thus we remain in dirty state
459
460 CHECK (not looper.requireAction());
461 CHECK (not looper.isDisabled());
462 CHECK (not looper.isWorking());
463 CHECK ( looper.runBuild()); // so the builder will be triggered (possibly a second time) after a short timeout
464 CHECK (not looper.isIdle());
465
466 looper.markStateProcessed(); // and after one round-trip the builder was running and is now finished
467
468 CHECK (not looper.requireAction());
469 CHECK (not looper.isDisabled());
470 CHECK (not looper.isWorking());
471 CHECK (not looper.runBuild());
472 CHECK ( looper.isIdle()); // ...system is in idle state now and waits until triggered externally
473
474 CHECK (isDisabled (looper.getTimeout()));
475
476
477 setup.has_commands_in_queue = true; // more commands again -> wake up
478 looper.markStateProcessed(); // ...and let's assume one command has already been processed
479
480 CHECK ( looper.requireAction());
481 CHECK (not looper.isDisabled());
482 CHECK ( looper.isWorking());
483 CHECK (not looper.runBuild());
484 CHECK (not looper.isIdle());
485
486 looper.triggerShutdown(); // request shutdown...
487
488 CHECK ( looper.requireAction());
489 CHECK ( looper.isDisabled());
490 CHECK (not looper.isWorking());
491 CHECK (not looper.runBuild());
492 CHECK (not looper.isIdle());
493
494 CHECK (isDisabled (looper.getTimeout()));
495
496
497 setup.has_commands_in_queue = false; // and even when done with all commands...
498 looper.markStateProcessed();
499
500 CHECK (isDisabled (looper.getTimeout()));
501 CHECK (not looper.shallLoop()); // we remain disabled and break out of the loop
502
503 CHECK ( looper.requireAction());
504 CHECK ( looper.isDisabled());
505 CHECK (not looper.isWorking());
506 CHECK (not looper.runBuild()); // ...note: still no need for builder run, since in shutdown
507 CHECK (not looper.isIdle());
508
509 }
510 };
511
512
514 LAUNCHER (DispatcherLooper_test, "unit controller");
515
516
517}}} // namespace steam::control::test
Encapsulated control logic for the session thread loop.
Definition looper.hpp:106
unsigned int uint
Definition integral.hpp:29
Implementation building block of SteamDispatcher to control waiting and timing.
Definition Setup.py:1
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
Steam-Layer implementation namespace root.
Test runner and basic definitions for tests.
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116