Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
time-mutation-test.cpp
Go to the documentation of this file.
1/*
2 TimeMutation(Test) - explicitly changing time specifications
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/mutation.hpp"
25#include "lib/util.hpp"
26
27#include <boost/lexical_cast.hpp>
28#include <string>
29
30using boost::lexical_cast;
31using util::isnil;
32using std::string;
33
34
35namespace lib {
36namespace time{
37namespace test{
38
40
41 namespace {
42 inline string
43 pop (Arg arg)
44 {
45 if (isnil (arg)) return "";
46 string entry = arg[0];
47 arg.erase (arg.begin());
48 return entry;
49 }
50 }
51
52
53
54
55 /************************************************************/
62 class TimeMutation_test : public Test
63 {
65 random_or_get (string arg)
66 {
67 if (isnil(arg))
68 return raw_time_64(1 + rani (100000)) * TimeValue::SCALE;
69 else
70 return lexical_cast<raw_time_64> (arg);
71 }
72
74 {
79
81 : var(o)
82 , dur(o)
83 , span(o, Offset(o))
84 , quant(o, "test_grid")
85 { }
86 };
87
88
89 virtual void
90 run (Arg arg)
91 {
92 if (isnil(arg))
93 seedRand();
94 TimeValue o (random_or_get (pop(arg)));
95 TimeValue c (random_or_get (pop(arg)));
96 CHECK (o != c, "unsuitable testdata");
97
98 // using a 25fps-grid, but with an time origin offset by 1/50sec
99 TimeGrid::build("test_grid", FrameRate::PAL, Time(FSecs(1,50)));
100
101 QuTime qChange (c, "test_grid");
102 FrameNr count(qChange);
103
104 mutate_by_Value (o, Time(c));
105 mutate_by_Offset (o, Offset(c));
106 mutate_quantised (o, qChange);
107 mutate_by_Increment(o, count);
108 }
109
110
111 void
112 mutate_by_Value(TimeValue original, Time newStart)
113 {
114 TestValues t(original);
115
116 CHECK (t.span.start() == original);
117 t.span.accept (Mutation::changeTime (newStart));
118 CHECK (t.span.start() != original);
119 CHECK (t.span.start() == newStart);
120
121 // instead of invoking directly, we can store and copy mutation messages
122 EncapsulatedMutation change_back(Mutation::changeTime (Time(original)));
123 t.span.accept (change_back);
124 CHECK (t.span.start() == original);
125
126 CHECK (t.quant == original);
127 t.quant.accept (Mutation::changeTime (newStart));
128 CHECK (t.quant != original);
129 CHECK (t.quant == newStart);
130
131 // Durations have no start time...
132 VERIFY_ERROR (INVALID_MUTATION, t.dur.accept(change_back));
133 VERIFY_ERROR (INVALID_MUTATION, t.span.duration().accept(change_back));
134
135 CHECK (t.dur == original);
137 CHECK (t.dur != original);
138 CHECK (t.dur == t.var*2);
139
140 CHECK (t.span.start() == original);
141 CHECK (t.span.duration() == original);
143 CHECK (t.span.duration() != original);
144 CHECK (t.span.duration() == t.var*3); // affects the duration,
145 CHECK (t.span.start() == original); // while the start time remains unaltered
146
147 // can't change the 'duration' of a quantised time point...
148 VERIFY_ERROR (INVALID_MUTATION, t.quant.accept(Mutation::changeDuration (Duration(t.var))));
149 }
150
151
152 void
154 {
155 TestValues t(original);
156 TimeValue& should_be(t.var+=change); // use as ref for verification
157
158 CHECK (t.span == original);
159 CHECK (t.span != should_be);
160 t.span.accept (Mutation::adjust (change));
161 CHECK (t.span == should_be);
162
163 t.dur.accept (Mutation::adjust (change));
164 CHECK (t.dur == should_be);
165
166 t.quant.accept (Mutation::adjust (change));
167 CHECK (t.quant == should_be);
168
169 // adjustment is cumulative
170 EncapsulatedMutation back_off = Mutation::adjust (-change);
171 t.span.accept (back_off);
172 CHECK (t.span == original);
173 t.span.accept (back_off);
174 t.span.accept (back_off);
175 t.span.accept (back_off);
176 CHECK (t.span == Time(original) - 3*change);
177 }
178
179
180 void
182 {
183 TestValues t(original);
184 t.var = change;
185 CHECK (Time(change) == t.var); // the underlying raw time value
186
187 CHECK (t.span == original);
188 t.span.accept (Mutation::materialise (change));
189 CHECK (t.span != original);
190 CHECK (t.span != t.var); // really materialised (grid-aligned)
191
192 // simulate what happened by explicit operations...
193 Secs seconds = change.formatAs<format::Seconds>();
194 PQuant quantiser(change);
195 Time materialised (quantiser->materialise(change));
196 CHECK (t.span == materialised);
197
198 CHECK (t.span.duration() == original); // not affected by mutation as usual
199 VERIFY_ERROR (INVALID_MUTATION, t.dur.accept (Mutation::materialise (change)));
200 // not surprising, a time point has no duration!!
201
202 CHECK (t.quant == original);
204 CHECK (t.quant != original);
205 CHECK (t.quant == materialised);
206 // but note, here we checked the underlying raw value.
207 // because t.quant is itself quantised, this might
208 // result in a second, chained quantisation finally
209
210 // Here accidentally both the change and t.quant use the same grid.
211 // For a more contrived example, we try to use a different grid...
212 TimeGrid::build("special_funny_grid", 1, Time(0,-10)); // (1 frame per second, zero point at -10s)
213 QuTime funny (original, "special_funny_grid");
214 funny.accept (Mutation::materialise (change));
215 CHECK (funny == t.quant); // leading to the same raw value this far
216
217 Time doublyQuantised (PQuant(funny)->materialise(funny));
218 CHECK (doublyQuantised != materialised);
219 }
220
221
222 void
223 mutate_by_Increment (TimeValue original, int change)
224 {
225 TestValues t(original);
226
227 // without any additional specification,
228 // the nudge-Mutation uses a 'natural grid'
229 t.span.accept (Mutation::nudge (change));
230 t.dur.accept (Mutation::nudge (change));
231
232 t.var += Time(FSecs(change)); // natural grid is in seconds
233 CHECK (t.span.start() == t.var);
234 CHECK (t.dur == t.var);
235
236 // any other grid can be specified explicitly
237 t.dur.accept (Mutation::nudge (change, "test_grid"));
238 CHECK (t.dur != t.var);
239 CHECK (t.dur == t.var + change * FrameRate::PAL.duration());
240 // ....this time the change was measured in grid units,
241 // taken relative to the origin of the specified grid
242 PQuant testGrid = Quantiser::retrieve("test_grid");
243 Offset distance (testGrid->timeOf(0), testGrid->timeOf(change));
244 CHECK (distance == change * FrameRate::PAL.duration());
245 CHECK (t.dur - t.var == distance);
246
247
248
249 // To the contrary, *quantised* values behave quite differently...
250 long frameNr = t.quant.formatAs<format::Frames>();
251
252 t.quant.accept (Mutation::nudge (change));
253 CHECK (t.quant != original);
254 long frameNr_after = t.quant.formatAs<format::Frames>();
255 CHECK (frameNr_after == frameNr + change);
256 //i.e. the quantised time's own grid is used
257 }
258 };
259
260
262 LAUNCHER (TimeMutation_test, "unit common");
263
264
265
266}}} // namespace lib::time::test
Template to build polymorphic value objects.
Duration is the internal Lumiera time metric.
void accept(Mutation const &)
Definition mutation.hpp:122
A frame counting timecode value.
Definition timecode.hpp:99
Duration duration() const
duration of one frame
Definition time.cpp:286
static const FrameRate PAL
predefined constant for PAL framerate
static EncapsulatedMutation changeDuration(Duration)
Convenience factory: simple Mutation to adjust the duration or length of a timespan.
Definition mutation.cpp:296
static EncapsulatedMutation materialise(QuTime const &)
Convenience factory: materialise the given quantised time into an explicit fixed internal time value,...
Definition mutation.cpp:319
static EncapsulatedMutation nudge(int adjustment)
build a time mutation to nudge the target time value by an offset, defined as number of steps on an i...
Definition mutation.cpp:336
static EncapsulatedMutation adjust(Offset)
Convenience factory: simple Mutation to adjust the duration or length of a timespan.
Definition mutation.cpp:307
static EncapsulatedMutation changeTime(Time)
Convenience factory to yield a simple Mutation changing the absolute start time.
Definition mutation.cpp:285
Offset measures a distance in time.
grid aligned time specification, referring to a specific scale.
Definition timequant.hpp:91
void accept(Mutation const &)
receive change message, which might cause re-quantisation
format::Traits< FMT >::TimeCode formatAs() const
create new time code instance, then castInto
static PQuant retrieve(Symbol gridID)
Access an existing grid definition or quantiser, known by the given symbolic ID.
A time interval anchored at a specific point in time.
Time start() const
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.
a mutable time value, behaving like a plain number, allowing copy and re-accessing
Lumiera's internal time value datatype.
void mutate_quantised(TimeValue original, QuTime change)
void mutate_by_Increment(TimeValue original, int change)
void mutate_by_Value(TimeValue original, Time newStart)
void mutate_by_Offset(TimeValue original, Offset change)
Interface: a grid and scale definition for time quantisation.
Definition time-grid.hpp:80
static PGrid build(FrameRate frames_per_second)
Modifying time and timecode values.
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
Frame count as timecode format.
Definition formats.hpp:77
Simple timecode specification as fractional seconds.
Definition formats.hpp:128
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...