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:
Fischlurch 2011-06-04 23:15:50 +02:00
parent eed2b0f320
commit 47afbbeab0
2 changed files with 323 additions and 38 deletions

View file

@ -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

View file

@ -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");