Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
time-control-test.cpp
Go to the documentation of this file.
1/*
2 TimeControl(Test) - mutating time entities with life connection and feedback
3
4 Copyright (C)
5 2011, 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
19#include "lib/test/run.hpp"
23#include "lib/time/control.hpp"
24
27#include "lib/item-wrapper.hpp"
28#include "lib/format-cout.hpp"
29#include "lib/util.hpp"
30
31#include <boost/lexical_cast.hpp>
32#include <string>
33#include <limits>
34
35using boost::lexical_cast;
36using util::typeStr;
37using util::isnil;
38using std::string;
39
40
41namespace lib {
42namespace time{
43namespace test{
44
45 namespace error = lumiera::error;
46
49 using lib::meta::Types;
51 using LERR_(UNCONNECTED);
52
53
54
55 namespace { // Test setup and helpers....
56
57 inline string
58 pop (Arg arg)
59 {
60 if (isnil (arg)) return "";
61 string entry = arg[0];
62 arg.erase (arg.begin());
63 return entry;
64 }
65
66
73 template<class TI>
76 {
77 mutable
79
80 public:
82 : received_{TI{Time::ZERO}}
83 { }
84
85 TestListener(TI const& initialValue)
86 : received_{initialValue}
87 { }
88
89 void
90 operator() (TI const& changeValue) const
91 {
92 received_ = changeValue;
93 }
94
95 TI const&
97 {
98 return *received_;
99 }
100 };
101
102 }//(End)Test helpers
103
104
105
106
107 /*******************************************************************/
121 class TimeControl_test : public Test
122 {
124 random_or_get (string arg)
125 {
126 if (isnil(arg))
127 return raw_time_64(1 + rani (100000)) * TimeValue::SCALE;
128 else
129 return lexical_cast<raw_time_64> (arg);
130 }
131
132
133 virtual void
134 run (Arg arg)
135 {
136 if (isnil(arg))
137 seedRand();
138 TimeValue o (random_or_get (pop(arg)));
139 TimeValue c (random_or_get (pop(arg)));
140 CHECK (c!=Time::ZERO and o != c, "unsuitable testdata");
141
142 // 25fps-grid, but with an time origin offset by 1/50sec
143 TimeGrid::build("test_grid_PAL", FrameRate::PAL, Time(FSecs(1,50)));
144
145 // disjoint NTSC-framerate grid for grid aligned changes
146 TimeGrid::build("test_grid_NTSC", FrameRate::NTSC);
147
148 verifyBasics();
150 }
151
152
153 void
155 {
156 TimeSpan target(Time(0,10), FSecs(5));
157
158 Control<Time> controller;
159 TestListener<Time> follower;
160
161 VERIFY_ERROR (UNCONNECTED, controller(Time::ZERO) );
162
163 target.accept (controller);
164 CHECK (Time(0,10) == target);
165 controller (Time(FSecs(21,2)));
166 CHECK (Time(500,10) == target);
167
168 CHECK (follower.receivedValue() == Time::ZERO);
169 controller.connectChangeNotification (follower);
170 CHECK (follower.receivedValue() == Time(500,10));
171
172 controller (Offset(-Time(500,1)));
173 CHECK (Time(0,9) == target);
174 CHECK (Time(0,9) == follower.receivedValue());
175 }
176
177
183 void verifyMatrix_of_MutationCases (TimeValue const& o, TimeValue const& c);
184 };
185
186
187 namespace { // Implementation: Matrix of individual test combinations
188
189
190 template<class T>
191 inline bool
192 isDuration()
193 {
194 return std::is_same<T,Duration>::value;
195 }
196
197 template<class T>
198 inline bool
200 {
201 return std::is_same<T,QuTime>::value;
202 }
203
204 template<class T>
205 inline TimeValue
206 materialise (T const& someTime)
207 {
208 return someTime;
209 }
210 inline TimeValue
211 materialise (QuTime const& alignedTime)
212 {
213 PQuant grid(alignedTime);
214 return grid->materialise (alignedTime);
215 }
216
217
218 template<class TAR>
220 {
221 static TAR
222 build (TimeValue const& org)
223 {
224 return TAR(org);
225 }
226 };
227
228 template<>
230 {
231 static TimeSpan
232 build (TimeValue const& org)
233 {
234 return TimeSpan (org, FSecs(3,2));
235 }
236 };
237
238 template<>
240 {
241 static QuTime
242 build (TimeValue const& org)
243 {
244 return QuTime (org, "test_grid_PAL");
245 }
246 };
247
248
249 template<class SRC>
251 {
252 static SRC
254 {
255 return SRC(c);
256 }
257 };
258
259 template<>
261 {
262 static TimeSpan
264 {
265 return TimeSpan (c, Duration(c));
266 }
267 };
268
269 template<>
271 {
272 static QuTime
274 {
275 return QuTime (c, "test_grid_NTSC");
276 }
277 };
278
279
280
281 template<class TAR, class SRC>
282 void
283 ____verify_wasChanged (TAR const& target, TimeValue const& org, SRC const& change)
284 {
285 if (isDuration<TAR>())
286 {
287 CHECK (target == org, "Logic error: Duration was changed by time value");
288 }
289 else
290 if (isDuration<SRC>())
291 {
292 CHECK (target == org, "Logic error: Duration used to change time value");
293 }
294 else
295 if (isQuTime<SRC>())
296 {
297 CHECK (target != org);
298 CHECK (target == materialise(change));
299 }
300 else
301 {
302 CHECK (target != org);
303 CHECK (target == change);
304 }
305 }
306
307 void
308 ____verify_wasChanged (Duration const& target, TimeValue const& org, Duration const& otherDuration)
309 {
310 CHECK (target != org);
311 CHECK (target == otherDuration);
312 }
313 void
314 ____verify_wasChanged (Duration const& target, TimeValue const& org, TimeSpan const& span_as_change)
315 {
316 CHECK (target != org);
317 CHECK (target == span_as_change.duration());
318 }
319 void
320 ____verify_wasChanged (TimeSpan const& target, TimeValue const& org, Duration const& changedDur)
321 {
322 CHECK (target == org, "Logic error: Duration was used as start point of the target TimeSpan");
323 CHECK (target.duration() != Time(FSecs(3,2)), "length of the timespan should have been changed");
324 CHECK (target.duration() == changedDur);
325 }
326
327
328
329 template<class TAR>
330 void
331 ____verify_wasOffset (TAR const& target, TAR const& refState, Offset const& offset)
332 {
333 CHECK (target != refState);
334 CHECK (target == Time(refState)+offset);
335 }
336
337 template<class TAR>
338 void
339 ____verify_wasOffsetBack (TAR const& target, TAR const& refState)
340 {
341 CHECK (target == refState);
342 }
343
344
345 template<class TAR>
346 void
347 ____verify_nudged (TAR const& target, TAR const& refState, FrameCnt offsetSteps)
348 {
349 CHECK (target != refState or not offsetSteps);
350 CHECK (target == Time(refState)+Time(FSecs(offsetSteps)));
351 }
352 template<>
353 void
354 ____verify_nudged (QuTime const& target, QuTime const& refState, FrameCnt offsetSteps)
355 {
356 CHECK (target != refState or not offsetSteps);
357 CHECK (target == Time (materialise(refState))
358 + Offset(offsetSteps, FrameRate::PAL));
359 }
360
361
362 template<class TAR, class SRC>
363 void
364 ____verify_notification (TAR const& target, TestListener<SRC> const& follower)
365 {
366 if (isDuration<SRC>())
367 {
368 CHECK (materialise(target) == follower.receivedValue()
369 or Duration::NIL == follower.receivedValue() );
370 }
371 else
372 if (isQuTime<TAR>())
373 {
374 CHECK (materialise (target) == follower.receivedValue());
375 }
376 else
377 {
378 CHECK (target == follower.receivedValue());
379 }
380 }
381 void
382 ____verify_notification (TimeSpan const& targetTimeSpan, TestListener<Duration> const& follower)
383 {
384 CHECK (follower.receivedValue() == targetTimeSpan.duration());
385 }
386 void
388 {
389 CHECK (target == follower.receivedValue());
390 }
391 void
392 ____verify_notification (Duration const& targetDuration, TestListener<TimeSpan> const& follower)
393 {
394 CHECK (Time::ZERO == follower.receivedValue());
395 CHECK (targetDuration == follower.receivedValue().duration());
396 }
397
398
399
400
401 template< class TAR
402 , class SRC
403 , class BASE
404 >
405 struct TestCase
406 : BASE
407 {
408 void
410 {
411 cout << "Test-Case. Target=" << typeStr<TAR>()
412 << "\t <--feed--- " << typeStr<SRC>()
413 << endl;
414
415 // test subject
416 Control<SRC> controller;
417
418 TAR target = TestTarget<TAR>::build(org);
420 TestListener<SRC> follower(change);
421
422 controller.connectChangeNotification(follower);
423 target.accept (controller);
424
425 controller (change);
426 ____verify_wasChanged (target, org, change);
427 ____verify_notification(target,follower);
428
429 TAR refState(target);
430
431 Offset offset(c);
432 controller (offset);
433 ____verify_wasOffset (target, refState, offset);
434 controller (-offset);
435 ____verify_wasOffsetBack (target, refState);
436 ____verify_notification(target,follower);
437
438 controller (0);
439 ____verify_nudged (target, refState, 0);
440 ____verify_notification(target,follower);
441
442 controller (+1);
443 ____verify_nudged (target, refState, +1);
444 ____verify_notification(target,follower);
445
446 controller (-2);
447 ____verify_nudged (target, refState, -1);
448 ____verify_notification(target,follower);
449
450 int maxInt = std::numeric_limits<int>::max();
451 int minInt = std::numeric_limits<int>::min();
452
453 controller (maxInt);
454 ____verify_nudged (target, refState, -1LL + maxInt);
455 ____verify_notification(target,follower);
456
457 controller (minInt);
458 ____verify_nudged (target, refState, -1LL + maxInt+minInt);
459 ____verify_notification(target,follower);
460
461
462 // tail recursion: further test combinations....
463 BASE::performTestSequence(org,c);
464 }
465 };
466
468 {
469 void performTestSequence(TimeValue const&, TimeValue const&) { }
470 };
471
472 }//(End)Implementation Test-case matrix
473
474
475 void
477 {
478 using KindsOfTarget = Types<Duration,TimeSpan,QuTime> ; // time entities to receive value changes
479 using KindsOfSource = Types<TimeValue,Time,Duration,TimeSpan,QuTime>; // time entities to be used as change values
480 using TestMatrix = InstantiateChainedCombinations< KindsOfTarget
481 , KindsOfSource
482 , TestCase // template to be instantiated for each type
483 , IterationEnd >;
484
485 TestMatrix().performTestSequence(origVal, change);
486 }
487
488
489
490
491
493 LAUNCHER (TimeControl_test, "unit common");
494
495
496
497}}} // namespace lib::time::test
Frontend/Interface: controller-element to retrieve and change running time values.
Definition control.hpp:127
void connectChangeNotification(SIG const &toNotify)
install a callback functor to be invoked as notification for any changes imposed onto the observed ti...
Definition control.hpp:215
Duration is the internal Lumiera time metric.
static const Duration NIL
constant to indicate "no duration"
static const FrameRate PAL
predefined constant for PAL framerate
static const FrameRate NTSC
Offset measures a distance in time.
grid aligned time specification, referring to a specific scale.
Definition timequant.hpp:91
A time interval anchored at a specific point in time.
Duration & duration()
void accept(Mutation const &)
may change start / duration
Definition mutation.hpp:123
basic constant internal time value.
static const raw_time_64 SCALE
Number of micro ticks (µs) per second as basic time scale.
Lumiera's internal time value datatype.
static const Time ZERO
void verifyMatrix_of_MutationCases(TimeValue const &o, TimeValue const &c)
Universal value/ref wrapper accessible similar to a pointer.
Interface: a grid and scale definition for time quantisation.
Definition time-grid.hpp:80
static PGrid build(FrameRate frames_per_second)
Any copy and copy construction prohibited.
Definition nocopy.hpp:38
Manipulating and monitoring time entities with life changes.
#define LERR_(_NAME_)
Definition error.hpp:45
Automatically use custom string conversion in C++ stream output.
Metaprogramming facilities to generate combination cases.
Adapter to store and hold an element of arbitrary type in local storage.
variadic sequence of types
Definition typelist.hpp:102
void ____verify_notification(TAR const &target, TestListener< SRC > const &follower)
void ____verify_nudged(TAR const &target, TAR const &refState, FrameCnt offsetSteps)
void ____verify_wasChanged(TAR const &target, TimeValue const &org, SRC const &change)
void ____verify_wasOffset(TAR const &target, TAR const &refState, Offset const &offset)
void ____verify_wasOffsetBack(TAR const &target, TAR const &refState)
int64_t FrameCnt
relative framecount or frame number.
Definition digxel.hpp:310
std::shared_ptr< const Quantiser > PQuant
Definition formats.hpp:58
int64_t raw_time_64
Raw µ-tick time representation used in Lumiera.
boost::rational< int64_t > FSecs
rational representation of fractional seconds
Implementation namespace for support and library code.
int rani(uint bound=_iBOUND())
Definition random.hpp:135
Test runner and basic definitions for tests.
bool isnil(lib::time::Duration const &dur)
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
void performTestSequence(TimeValue const &org, TimeValue const &c)
A collection of frequently used helper functions to support unit testing.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
To establish a reference scale for quantised time values.
Support library to represent grid-aligned time specifications This is part of Lumiera's time and time...
a family of time value like entities and their relationships.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...