ArgumentHolder finished, low-level integration test pass

This commit is contained in:
Fischlurch 2009-07-20 07:03:18 +02:00
parent 63bad834c1
commit c85d1d3cd8
7 changed files with 106 additions and 75 deletions

View file

@ -128,7 +128,7 @@ namespace typelist{
template<typename SIG>
function<SIG>&
getFun ()
getFun () const
{
return get<function<SIG> >();
}
@ -157,7 +157,7 @@ namespace typelist{
template<typename SIG>
SIG&
getFun ()
getFun () const
{
SIG *fun = get<SIG*>();
REQUIRE (fun);

View file

@ -22,18 +22,17 @@
/** @file command-argument-holder.hpp
** A simple container record holding the actual command arguments.
** A passive container record holding the actual command arguments & UNDO state.
** While all command objects themselves have a common type (type erasure),
** the actual argument tuple and the state memento for undo can't. Especially,
** the actual argument tuple and the state memento for UNDO can't. Especially,
** the size of arguments and memento will depend on their respective types.
** Thus, to manage somehow the storage of this data, we create a common holder,
** to be managed by a custom allocator.
** which can than be managed by a custom allocator / object pool.
**
** @todo doing just plain heap allocation for now :-P
**
** @see Command
** @see UndoMutation
** @see MementoTie
** @see CmdClosure storage of command arguments
** @see MementoTie wiring of UNDO functions & memento
** @see UndoMutation execution of UNDO
** @see command-argument-test.cpp
**
*/
@ -43,20 +42,17 @@
#ifndef CONTROL_COMMAND_ARGUMENT_HOLDER_H
#define CONTROL_COMMAND_ARGUMENT_HOLDER_H
//#include "pre.hpp"
#include "proc/control/argument-tuple-accept.hpp"
#include "proc/control/command-closure.hpp"
#include "proc/control/memento-tie.hpp"
#include "lib/opaque-holder.hpp"
#include <boost/noncopyable.hpp>
#include <string>
namespace control {
using boost::noncopyable;
using lib::InPlaceBuffer;
using std::string;
@ -96,14 +92,14 @@ namespace control {
/**
* Specifically typed CmdClosure, which serves for
* Specifically typed CmdClosure, which serves for
* actually allocating storage to hold the command arguments
* and the undo state (memento) for Proc-Layer commands.
* Both the contained components within ArgumentHolder
* and the UNDO state (memento) for Proc-Layer commands.
* Both the contained components within ArgumentHolder
* can be in \em empty state; there are no distinct
* lifecycle limitations. ArgumentHolder is part
* of Proc-Layer command's implementation
* and should not be used standalone.
* and should not be used standalone.
*/
template<typename SIG, typename MEM>
class ArgumentHolder
@ -111,8 +107,10 @@ namespace control {
, ArgumentHolder<SIG,MEM> // target class providing the implementation
, CmdClosure // base class to inherit from
>
, private noncopyable
{
/** copy construction allowed(but no assignment)*/
ArgumentHolder& operator= (ArgumentHolder const&);
typedef Closure<SIG> ArgHolder;
typedef MementoTie<SIG,MEM> MemHolder;
@ -132,13 +130,14 @@ namespace control {
/* ==== proxied CmdClosure interface ==== */
public:
virtual bool isValid () const
{
return arguments_->isValid();
}
virtual CmdFunctor bindArguments (CmdFunctor& func)
virtual CmdFunctor bindArguments (CmdFunctor const& func)
{
if (!isValid())
throw lumiera::error::State ("Lifecycle error: can't bind functor, "
@ -158,7 +157,7 @@ namespace control {
}
public:
/** per default, all data within ArgumentHolder
* is set up in \em empty state. Later on, the
* command arguments are to be provided by #bind ,
@ -169,6 +168,16 @@ namespace control {
, memento_()
{ }
/** copy construction allowed(but no assignment) */
ArgumentHolder (ArgumentHolder const& oAh)
: arguments_()
, memento_()
{
arguments_.template create<ArgHolder> (*oAh.arguments_);
memento_.template create<MemHolder> (*oAh.memento_);
}
/** has undo state capturing been invoked? */
bool canUndo () const { return memento_->isValid(); }
bool empty () const { return !arguments_->isValid(); }

View file

@ -100,7 +100,7 @@ namespace control {
virtual bool isValid () const =0;
virtual CmdFunctor bindArguments (CmdFunctor&) =0;
virtual CmdFunctor bindArguments (CmdFunctor const&) =0;
};
@ -207,7 +207,7 @@ namespace control {
* can't be const.
*/
CmdFunctor
bindArguments (CmdFunctor& unboundFunctor)
bindArguments (CmdFunctor const& unboundFunctor)
{
return CmdFunctor (TupleApplicator<SIG> (params_)
.bind ( unboundFunctor.getFun<SIG>()) );
@ -221,7 +221,7 @@ namespace control {
params_.dump (buff << "Closure(" );
string dumped (buff.str());
if (1 < dumped.length())
if (8 < dumped.length())
// remove trailing comma...
return dumped.substr (0, dumped.length()-1) +")";
else

View file

@ -7,11 +7,35 @@ PLANNED "CommandBasic_test" CommandBasic_test <<END
END
PLANNED "CommandArgument_test" CommandArgument_test <<END
TEST "Argument & Memento handling" CommandArgument_test <<END
out: Command-State. arguments=unbound, ·noUNDO·.
out: capture state...
out: Command-State. arguments=Closure\(\), ·noUNDO·.
out: Command-State. arguments=Closure\(.\), ·noUNDO·.
out: Command-State. arguments=Closure\(.,00:..:....00\), ·noUNDO·.
out: Command-State. arguments=Closure\(00:..:....00,glorious,..\), <mem: destruction>.
out: would be serialised.....Command-State. arguments=Closure\(\), ·noUNDO·.
out: would be serialised.....Command-State. arguments=Closure\(.\), ·noUNDO·.
out: would be serialised.....Command-State. arguments=Closure\(.,00:..:....00\), ·noUNDO·.
out: would be serialised.....Command-State. arguments=Closure\(00:..:....00,glorious,..\), <mem: destruction>.
out: sizeof\( .+control1.ArgumentHolder.+ \) = .+
out: Command-State. arguments=Closure\(00:..:....00,Lumiera rocks,..\), ·noUNDO·.
out: capture state...
out: captured state: START...Lumiera rocks
out: Command-State. arguments=Closure\(00:..:....00,Lumiera rocks,..\), <mem: START...Lumiera rocks>.
out: invoke operation...
out: START...doIt\( Time=00:..:....00 "Lumiera rocks" rand=.. \)
out: undo... memento=START...Lumiera rocks
out: START...doIt\( Time=00:..:....00 "Lumiera rocks" rand=.. \)undoIt\(time=00:..:....00\)----memento-:START...Lumiera rocks
out: capture state...
out: modified: Command-State. arguments=Closure\(00:00:00.123,unbelievable,..\), <mem: START...doIt\( Time=00:..:....00 "Lumiera rocks" rand=.. \)undoIt\(time=00:..:....00\)----memento-:START...Lumiera rocksLumiera rocks>.
out: copied : Command-State. arguments=Closure\(00:..:....00,Lumiera rocks,..\), <mem: START...Lumiera rocks>.
out: undo... memento=START...doIt\( Time=00:..:....00 "Lumiera rocks" rand=.. \)undoIt\(time=00:..:....00\)----memento-:START...Lumiera rocksLumiera rocks
out: RESET...undoIt\(time=00:..:....00\)----memento-:START...doIt\( Time=00:..:....00 "Lumiera rocks" rand=.. \)undoIt\(time=00:..:....00\)----memento-:START...Lumiera rocksLumiera rocks
END
TEST "Command functor" CommandMutation_test <<END
TEST "Command functor and UNDO functor" CommandMutation_test <<END
out: Mutation\(untied\)
out: param values: Closure\(23\)
out: Mutation\(Closure\(23\)\)
@ -27,6 +51,6 @@ return: 0
END
TEST "Memento binding" MementoTie_test <<END
TEST "Memento wiring and storage" MementoTie_test <<END
return: 0
END

View file

@ -23,43 +23,25 @@
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
//#include "proc/asset/media.hpp"
//#include "proc/mobject/session.hpp"
//#include "proc/mobject/session/edl.hpp"
//#include "proc/mobject/session/testclip.hpp"
//#include "proc/mobject/test-dummy-mobject.hpp"
//#include "lib/p.hpp"
//#include "proc/mobject/placement.hpp"
//#include "proc/mobject/placement-index.hpp"
//#include "proc/mobject/explicitplacement.hpp"
#include "proc/control/command-argument-holder.hpp"
#include "lib/scoped-ptrvect.hpp"
#include "lib/lumitime-fmt.hpp"
//#include "lib/meta/typelist.hpp"
//#include "lib/meta/tuple.hpp"
#include "lib/util.hpp"
//#include <tr1/functional>
#include <boost/format.hpp>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <string>
//using std::tr1::bind;
//using std::tr1::placeholders::_1;
//using std::tr1::placeholders::_2;
//using std::tr1::function;
using util::isnil;
//using util::and_all;
using util::for_each;
using boost::format;
using lumiera::Time;
//using util::contains;
using boost::format;
using std::string;
using std::rand;
using std::ostream;
using std::ostringstream;
using std::rand;
using std::cout;
using std::endl;
@ -70,13 +52,6 @@ namespace test {
using lib::test::showSizeof;
using lib::test::randTime;
// using session::test::TestClip;
// using lumiera::P;
// using namespace lumiera::typelist;
// using lumiera::typelist::Tuple;
// using control::CmdClosure;
@ -87,6 +62,10 @@ namespace test {
ostringstream protocol; ///< used to verify the test function calls
/**
* watching the instance creation
* of some parameter values
*/
template<typename TY>
struct Tracker
{
@ -116,26 +95,32 @@ namespace test {
int Tracker<TY>::instanceCnt (0);
/* === functions to implement test-"operation" & UNDO === */
void
doIt (Tracker<Time> time, Tracker<string> str, int rand)
{
static format fmt ("doIt( Time=%s \"%s\" rand=%2d )");
cout << "invoke operation..." << endl;
protocol << fmt % *time % *str % rand;
}
Tracker<string>
captureState (Tracker<Time>, Tracker<string> xstr, int)
{
cout << "capture state..." << endl;
return protocol.str() + *xstr;
}
void
undoIt (Tracker<Time> time, Tracker<string>, int, Tracker<string> memento)
{
protocol << "undoIt(time="<<time<<")---state-was-:"<< *memento;
cout << "undo... memento=" << memento << endl;
protocol << "undoIt(time="<<time<<")----memento-:"<< *memento;
}
/// another dummy-UNDO function
void dummyU (int,int,int) { }
int dummyC (int u,int o) { return u + rand() % (o-u+1); }
@ -163,11 +148,12 @@ namespace test {
typedef lib::ScopedPtrVect<CmdClosure> ArgTuples;
/***************************************************************************
* @test Check storage handling of the command parameters and state memento.
*
*
* @see control::CommandArgumentHolder
* @see command-basic-test.hpp
*/
@ -186,16 +172,20 @@ namespace test {
serialiseArgTuples (testTuples);
testTuples.clear();
// simulateCmdLifecycle();
simulateCmdLifecycle();
// verify all dtors properly called...
ASSERT (0 == Tracker<Time>::instanceCnt);
ASSERT (0 == Tracker<string>::instanceCnt);
}
typedef Tracker<Time> TTime;
typedef Tracker<string> Tstr;
typedef struct{ int i[5]; } Sint5;
/** @test create various argument tuples and re-access their contents */
void
@ -234,7 +224,7 @@ namespace test {
arg5->tie(undoIt, captureState)
.tieCaptureFunc() // bind capturing function to memento storage,
(TTime(), Tstr("destruction"), 11); // then invoke the bound capturing mechanism
(TTime(), Tstr("destruction"), 11); // then invoke the bound capturing mechanism
ASSERT (arg5->canUndo());
ASSERT (*arg5->memento() == "destruction");
@ -245,6 +235,7 @@ namespace test {
}
/** @test serialise and de-serialise each tuple and check validity
* @todo unimplemented, waiting on Serialiser
*/
@ -255,6 +246,7 @@ namespace test {
}
/** @test verify the comparison operators */
void
checkArgumentComparison ()
@ -298,37 +290,43 @@ namespace test {
}
#if false ////////////////////////////////////////////////////////////////////////////TODO.....
/** @test simulate a complete command lifecycle with regards to
* the storage handling of the command parameters and state memento.
/** @test simulate a complete command lifecycle with regards to the
* storage handling of the command parameters and state memento.
*/
void
simulateCmdLifecycle()
{
typedef void SIG_do(Tracker<Time>, Tracker<string>, int);
typedef ArgumentHolder<SIG_do, Tracker<string> > Args;
typedef MementoTie<SIG_do, Tracker<string> > MemHolder;
typedef ArgumentHolder<SIG_do, Tracker<string> > Args;
typedef MementoTie<SIG_do, Tracker<string> > MemHolder;
Args args;
ASSERT (isnil (args));
cout << showSizeof(args) << endl;
args.bind (randTime(), "Lumiera rocks". rand() % 100);
// store a set of parameter values, later to be used on invocation
args.bind (TTime(randTime()), Tstr("Lumiera rocks"), rand() % 100);
ASSERT (!isnil (args));
cout << args << endl;
ASSERT (!args.canUndo());
ASSERT (isnil (args.memento()));
VERIFY_ERROR(MISSING_MEMENTO, args.memento() );
MemHolder& memHolder = args.tie(undoIt,captureState);
ASSERT (!memHolder); // no stored memento....
ASSERT (!args.canUndo());
function<SIG_do> doItFun = doIt;
function<SIG_do> undoFun = memHolder.tieUndoFunc();
function<SIG_do> captFun = memHolder.tieCaptureFunc();
CmdFunctor bound_doItFun = args.bindArguments (CmdFunctor(doItFun));
CmdFunctor bound_undoFun = args.bindArguments (CmdFunctor(undoFun));
CmdFunctor bound_captFun = args.bindArguments (CmdFunctor(captFun));
typedef function<void()> OpFun;
// now close all the functions with the stored parameter values...
OpFun bound_doItFun = args.bindArguments (CmdFunctor(doItFun)).getFun<void()>();
OpFun bound_undoFun = args.bindArguments (CmdFunctor(undoFun)).getFun<void()>();
OpFun bound_captFun = args.bindArguments (CmdFunctor(captFun)).getFun<void()>();
protocol.seekp(0);
protocol << "START...";
@ -336,8 +334,9 @@ namespace test {
bound_captFun();
cout << "captured state: " << args.memento() << endl;
ASSERT (memHolder);
ASSERT (!isnil (args.memento()));
ASSERT (!isnil (*args.memento()));
ASSERT (args.canUndo());
cout << args << endl;
bound_doItFun();
cout << protocol.str() << endl;
@ -350,14 +349,14 @@ namespace test {
protocol.seekp(0);
protocol << "RESET...";
args.bind (123456, "unbelievable", rand() %100);
cout << "original: " << args << endl;
cout << "copied : " << argsCopy << endl;
args.bind (TTime(Time(123456)), Tstr("unbelievable"), rand() %100);
cout << "modified: " << args << endl;
cout << "copied : " << argsCopy << endl; // holds still the old params & memento
bound_undoFun();
cout << protocol.str() << endl;
}
#endif ////////////////////////////////////////////////////////////////////////////TODO.....
};

View file

@ -44,6 +44,7 @@ test_lib_SOURCES = \
$(testlib_srcdir)/factory-special-test.cpp \
$(testlib_srcdir)/factorytest.cpp \
$(testlib_srcdir)/format-helper-test.cpp \
$(testlib_srcdir)/functor-util-test.cpp \
$(testlib_srcdir)/hash-indexed-test.cpp \
$(testlib_srcdir)/helloworldtest.cpp \
$(testlib_srcdir)/lifecycletest.cpp \

View file

@ -26,11 +26,9 @@
//#include "lib/util.hpp"
#include "lib/functor-util.hpp"
//#include <boost/lexical_cast.hpp>
#include <tr1/functional>
#include <iostream>
//using boost::lexical_cast;
//using util::isnil;
//using std::string;
using std::cout;
@ -91,7 +89,7 @@ namespace test {
f1 = f2;
ASSERT ( rawComparison(f1, f2));
ASSERT (!rawComparison(f0, Fvi())); // note: can't detect they are equivalent
ASSERT (!rawComparison(f0, Fiv()));