first attempt towards covering the various special cases
the intention is to generate most combinations from generic template cases, but to define the difficult cases by explicit specialisation
This commit is contained in:
parent
eed2b0f320
commit
47afbbeab0
2 changed files with 323 additions and 38 deletions
|
|
@ -59,6 +59,7 @@
|
|||
#define LIB_TIME_CONTROL_H
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/meta/util.hpp"
|
||||
#include "lib/time/mutation.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
//#include "lib/symbol.hpp"
|
||||
|
|
@ -66,6 +67,7 @@
|
|||
//#include <boost/noncopyable.hpp>
|
||||
//#include <iostream>
|
||||
//#include <boost/operators.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <tr1/functional>
|
||||
#include <vector>
|
||||
//#include <string>
|
||||
|
|
@ -83,6 +85,9 @@ namespace time {
|
|||
|
||||
namespace mutation {
|
||||
|
||||
using boost::enable_if;
|
||||
using boost::disable_if;
|
||||
using lumiera::typelist::is_sameType;
|
||||
using std::tr1::placeholders::_1;
|
||||
using std::tr1::function;
|
||||
using std::tr1::bind;
|
||||
|
|
@ -110,6 +115,9 @@ namespace time {
|
|||
static TI imposeOffset (TimeValue& target, Offset const&);
|
||||
static TI imposeNudge (TimeValue& target, int);
|
||||
|
||||
static TI changeDuration (Duration& target, TI const&);
|
||||
// static TI nudgeDuration (Duration& target, int);
|
||||
|
||||
template<class SRC, class TAR>
|
||||
struct MutationPolicy;
|
||||
|
||||
|
|
@ -157,10 +165,88 @@ namespace time {
|
|||
return TI (Mutation::imposeChange (target, TimeVar(target)+Time(FSecs(off_by_steps))));
|
||||
}
|
||||
|
||||
// special cases...
|
||||
template<class TI>
|
||||
TI
|
||||
Mutator<TI>::changeDuration (Duration&, TI const&)
|
||||
{
|
||||
return TI (Time::ZERO);
|
||||
}
|
||||
template<>
|
||||
Duration
|
||||
Mutator<Duration>::changeDuration (Duration& target, Duration const& changedDur)
|
||||
{
|
||||
return Duration (Mutation::imposeChange (target,changedDur));
|
||||
}
|
||||
template<>
|
||||
TimeSpan
|
||||
Mutator<TimeSpan>::changeDuration (Duration& target, TimeSpan const& timeSpan_to_impose)
|
||||
{
|
||||
return TimeSpan (timeSpan_to_impose.start()
|
||||
,Duration(Mutation::imposeChange (target,timeSpan_to_impose.duration()))
|
||||
);
|
||||
}
|
||||
|
||||
template<>
|
||||
TimeSpan
|
||||
Mutator<TimeSpan>::imposeValueChange (TimeValue& target, TimeSpan const& newVal)
|
||||
{
|
||||
Mutation::imposeChange (target,newVal);
|
||||
return newVal;
|
||||
}
|
||||
template<>
|
||||
TimeSpan
|
||||
Mutator<TimeSpan>::imposeOffset (TimeValue& target, Offset const& off)
|
||||
{
|
||||
return TimeSpan (Mutation::imposeChange (target, TimeVar(target)+off), Duration::ZERO);
|
||||
}
|
||||
template<>
|
||||
TimeSpan
|
||||
Mutator<TimeSpan>::imposeNudge (TimeValue& target, int off_by_steps)
|
||||
{
|
||||
return TimeSpan (Mutation::imposeChange (target, TimeVar(target)+Time(FSecs(off_by_steps))), Duration::ZERO);
|
||||
}
|
||||
|
||||
|
||||
#ifdef LIB_TIME_TIMEQUQNT_H
|
||||
template<>
|
||||
QuTime
|
||||
Mutator<QuTime>::changeDuration (Duration&, QuTime const& irrelevantChange)
|
||||
{
|
||||
return QuTime (Time::ZERO, PQuant(irrelevantChange));
|
||||
}
|
||||
template<>
|
||||
QuTime
|
||||
Mutator<QuTime>::imposeValueChange (TimeValue& target, QuTime const& grid_aligned_Value_to_set)
|
||||
{
|
||||
PQuant quantiser (grid_aligned_Value_to_set);
|
||||
TimeValue appliedChange = quantiser->materialise(grid_aligned_Value_to_set);
|
||||
Mutation::imposeChange (target, appliedChange);
|
||||
return QuTime (target, quantiser);
|
||||
}
|
||||
template<>
|
||||
QuTime
|
||||
Mutator<QuTime>::imposeOffset (TimeValue&, Offset const&)
|
||||
{
|
||||
throw error::Logic ("can't deliver result of the change as grid-aligned time, "
|
||||
"because it's not evident which concrete grid to use"
|
||||
,LUMIERA_ERROR_UNKNOWN_GRID); //////////////////TODO: we could pick up a "default grid" from session?
|
||||
}
|
||||
template<>
|
||||
QuTime
|
||||
Mutator<QuTime>::imposeNudge (TimeValue&, int)
|
||||
{
|
||||
throw error::Logic ("can't deliver result of the change as grid-aligned time, "
|
||||
"because it's not evident which concrete grid to use"
|
||||
,LUMIERA_ERROR_UNKNOWN_GRID);
|
||||
}
|
||||
#endif //(End)quantisation special case
|
||||
|
||||
|
||||
|
||||
template<class TI>
|
||||
template<class TAR>
|
||||
struct Mutator<TI>::MutationPolicy<TI, TAR>
|
||||
struct Mutator<TI>::MutationPolicy<typename disable_if< is_sameType<TAR,Duration>, TI>::type, TAR>
|
||||
{
|
||||
static function<TI(TI const&)>
|
||||
buildChangeHandler (TAR& target)
|
||||
|
|
@ -192,6 +278,46 @@ namespace time {
|
|||
};
|
||||
|
||||
|
||||
//special cases for changing Durations....
|
||||
|
||||
template<class TI>
|
||||
template<class TAR>
|
||||
struct Mutator<TI>::MutationPolicy<typename enable_if< is_sameType<TAR,Duration>, TI>::type, TAR>
|
||||
{
|
||||
static function<TI(TI const&)>
|
||||
buildChangeHandler (Duration& target)
|
||||
{
|
||||
return bind (Mutator<TI>::changeDuration, ref(target), _1 );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// template<class TI>
|
||||
// template<class TAR>
|
||||
// struct Mutator<TI>::MutationPolicy<TI, TAR>
|
||||
// {
|
||||
// static function<TimeValue(TimeValue const&)>
|
||||
// buildChangeHandler (Duration& target)
|
||||
// {
|
||||
// return bind (Mutator<TI>::changeDuration, ref(target), _1 );
|
||||
// }
|
||||
// };
|
||||
|
||||
// template<class TI>
|
||||
// template<>
|
||||
// struct Mutator<TI>::MutationPolicy<int, Duration>
|
||||
// {
|
||||
// static function<TI(int)>
|
||||
// buildChangeHandler (Duration& target)
|
||||
// {
|
||||
// return bind (Mutator<TI>::nudgeDuration, ref(target), _1 );
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<class TI>
|
||||
template<class TAR>
|
||||
void
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include <boost/lexical_cast.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
using lib::test::showType;
|
||||
using boost::lexical_cast;
|
||||
|
|
@ -95,28 +96,6 @@ namespace test{
|
|||
return *received_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<class TAR, class SRC, class BASE>
|
||||
struct TestCase
|
||||
: BASE
|
||||
{
|
||||
void
|
||||
performTestCases(TimeValue const& o, TimeValue const& c)
|
||||
{
|
||||
cout << "Test-Case. Target=" << showType<TAR>()
|
||||
<<" <--feed--- " << showType<SRC>()
|
||||
<<endl;
|
||||
BASE::performTestCases(o,c);
|
||||
}
|
||||
};
|
||||
|
||||
struct IterationEnd
|
||||
{
|
||||
void performTestCases(TimeValue const&, TimeValue const&) { }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -150,11 +129,14 @@ namespace test{
|
|||
{
|
||||
TimeValue o (random_or_get (pop(arg)));
|
||||
TimeValue c (random_or_get (pop(arg)));
|
||||
CHECK (o != c, "unsuitable testdata");
|
||||
CHECK (c!=Time::ZERO && o != c, "unsuitable testdata");
|
||||
|
||||
// using a 25fps-grid, but with an time origin offset by 1/50sec
|
||||
// 25fps-grid, but with an time origin offset by 1/50sec
|
||||
TimeGrid::build("test_grid", FrameRate::PAL, Time(FSecs(1,50)));
|
||||
|
||||
// disjoint NTSC-framerate grid for grid aligned changes
|
||||
TimeGrid::build("test_grid_NTSC", FrameRate::NTSC);
|
||||
|
||||
QuTime qChange (c, "test_grid");
|
||||
FrameNr count(qChange);
|
||||
|
||||
|
|
@ -188,22 +170,199 @@ namespace test{
|
|||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
verifyMatrix_of_MutationCases (TimeValue const& o, TimeValue const& c)
|
||||
{
|
||||
typedef Types<Duration,TimeSpan,QuTime> KindsOfTarget;
|
||||
typedef Types<Time,Duration,TimeSpan,QuTime> KindsOfSource;
|
||||
typedef InstantiateChainedCombinations< KindsOfTarget
|
||||
, KindsOfSource
|
||||
, TestCase
|
||||
, IterationEnd > TestMatrix;
|
||||
|
||||
TestMatrix().performTestCases(o,c);
|
||||
}
|
||||
void verifyMatrix_of_MutationCases (TimeValue const& o, TimeValue const& c);
|
||||
};
|
||||
|
||||
|
||||
namespace { // Implementation: Matrix of individual test combinations
|
||||
|
||||
template<class TAR>
|
||||
struct TestTarget
|
||||
{
|
||||
static TAR
|
||||
build (TimeValue const& org)
|
||||
{
|
||||
return TAR(org);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TestTarget<TimeSpan>
|
||||
{
|
||||
static TimeSpan
|
||||
build (TimeValue const& org)
|
||||
{
|
||||
return TimeSpan (org, FSecs(3,2));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TestTarget<QuTime>
|
||||
{
|
||||
static QuTime
|
||||
build (TimeValue const& org)
|
||||
{
|
||||
return QuTime (org, "test_grid");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class SRC>
|
||||
struct TestChange
|
||||
{
|
||||
static SRC
|
||||
prepareChangeValue (TimeValue const& c)
|
||||
{
|
||||
return SRC(c);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TestChange<TimeSpan>
|
||||
{
|
||||
static TimeSpan
|
||||
prepareChangeValue (TimeValue const& c)
|
||||
{
|
||||
return TimeSpan (c, Duration(c));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TestChange<QuTime>
|
||||
{
|
||||
static QuTime
|
||||
prepareChangeValue (TimeValue const& c)
|
||||
{
|
||||
return QuTime (c, "test_grid_NTSC");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<class TAR, class SRC>
|
||||
void
|
||||
verify_wasChanged (TAR const& target, TimeValue const& org, SRC const& change)
|
||||
{
|
||||
CHECK (target != org);
|
||||
CHECK (target == change);
|
||||
}
|
||||
|
||||
template<class SRC>
|
||||
void
|
||||
verify_wasChanged (Duration const& target, TimeValue const& org, SRC const&)
|
||||
{
|
||||
CHECK (target == org, "Logic error: Duration was changed by time value");
|
||||
}
|
||||
void
|
||||
verify_wasChanged (Duration const& target, TimeValue const& org, Duration const& otherDuration)
|
||||
{
|
||||
CHECK (target != org);
|
||||
CHECK (target == otherDuration);
|
||||
}
|
||||
void
|
||||
verify_wasChanged (Duration const& target, TimeValue const& org, TimeSpan const& span)
|
||||
{
|
||||
CHECK (target != org);
|
||||
CHECK (target == span.duration());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class TAR>
|
||||
void
|
||||
verify_wasOffset (TAR const&, TimeValue const&, Offset const&)//(TAR const& target, TimeValue const& o, Offset const& offset)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<class TAR>
|
||||
void
|
||||
verify_zeroAlligned (TAR const&, TAR const&)//(TAR const& target, TAR const& oldState)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<class TAR>
|
||||
void
|
||||
verify_nudged (TAR const&, TAR const&, int64_t)//(TAR const& target, TAR const& oldState, int64_t offsetSteps)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<class TAR, class SRC, class BASE>
|
||||
struct TestCase
|
||||
: BASE
|
||||
{
|
||||
void
|
||||
performTestCases(TimeValue const& o, TimeValue const& c)
|
||||
{
|
||||
cout << "Test-Case. Target=" << showType<TAR>()
|
||||
<<" <--feed--- " << showType<SRC>()
|
||||
<<endl;
|
||||
|
||||
Control<SRC> controller;
|
||||
|
||||
TAR target = TestTarget<TAR>::build(o);
|
||||
target.accept (controller);
|
||||
|
||||
SRC change = TestChange<SRC>::prepareChangeValue(c);
|
||||
controller (change);
|
||||
verify_wasChanged (target, o, change);
|
||||
|
||||
Offset offset(c);
|
||||
controller (offset);
|
||||
verify_wasOffset (target, o, offset);
|
||||
|
||||
TAR oldState(target);
|
||||
controller (0);
|
||||
verify_zeroAlligned(target, oldState);
|
||||
|
||||
controller (+1);
|
||||
verify_nudged (target, oldState, +1);
|
||||
|
||||
controller (-2);
|
||||
verify_nudged (target, oldState, -1);
|
||||
|
||||
int maxInt = std::numeric_limits<int>::max();
|
||||
int minInt = std::numeric_limits<int>::min();
|
||||
|
||||
controller (maxInt);
|
||||
verify_nudged (target, oldState, -1LL + maxInt);
|
||||
|
||||
controller (minInt);
|
||||
verify_nudged (target, oldState, -1LL + maxInt+minInt);
|
||||
|
||||
|
||||
// tail recursion: further test combinations....
|
||||
BASE::performTestCases(o,c);
|
||||
}
|
||||
};
|
||||
|
||||
struct IterationEnd
|
||||
{
|
||||
void performTestCases(TimeValue const&, TimeValue const&) { }
|
||||
};
|
||||
|
||||
}//(End)Implementation Test-case matrix
|
||||
|
||||
|
||||
void
|
||||
TimeControl_test::verifyMatrix_of_MutationCases (TimeValue const& o, TimeValue const& c)
|
||||
{
|
||||
typedef Types<Duration,TimeSpan,QuTime> KindsOfTarget;
|
||||
typedef Types<Time,Duration,TimeSpan,QuTime> KindsOfSource;
|
||||
typedef InstantiateChainedCombinations< KindsOfTarget
|
||||
, KindsOfSource
|
||||
, TestCase
|
||||
, IterationEnd > TestMatrix;
|
||||
|
||||
TestMatrix().performTestCases(o,c);
|
||||
}
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (TimeControl_test, "unit common");
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue