finish and tidy up control::Mutation, unit test pass

This commit is contained in:
Fischlurch 2009-07-10 19:04:01 +02:00
parent e892a0087a
commit 9aa5ba560c
9 changed files with 119 additions and 88 deletions

View file

@ -88,8 +88,8 @@ namespace lib {
* \c isValid() function, the conversion operator returns either a
* bound or unbound member pointer.
*
* @todo list some usage examples here
* @see bool-checkable-test.cpp
* @see bool-checkable-test.cpp
* @see control::Mutation usage example
*/
template< class T ///< the target type implementing \c isValid()
, class PAR = imp::Dummy ///< optional parent for inheritance chain

View file

@ -381,7 +381,7 @@ namespace lib {
template<class SUB>
InPlaceAnyHolder(SUB const& obj)
{
{
place_inBuff (obj);
}

View file

@ -45,7 +45,8 @@
#include <tr1/memory>
#include <tr1/functional>
#include <iostream>
#include <iostream>
#include <sstream>
#include <string>
@ -119,14 +120,12 @@ namespace control {
ParamAccessor(TUP const& tuple)
: BASE(tuple)
{
cout << showSizeof(element()) << endl; //////////TODO remove this test code
}
{ }
string
dump (string const& prefix = "(") const
ostream&
dump (ostream& output) const
{
return BASE::dump (prefix+element()+",");
return BASE::dump (output << element() << ',');
}
@ -144,14 +143,10 @@ namespace control {
////////////////////TODO the recursion-end of the access operations goes here
string
dump (string const& prefix ="(") const
ostream&
dump (ostream& output) const
{
if (1 < prefix.length())
// remove trailing comma...
return prefix.substr (0, prefix.length()-1) +")";
else
return prefix+")";
return output;
}
};
@ -212,7 +207,15 @@ namespace control {
operator string() const
{
UNIMPLEMENTED ("how to do a string conversion on the variable argument tuple??");
std::ostringstream buff;
params_.dump (buff << "Closure(" );
string dumped (buff.str());
if (1 < dumped.length())
// remove trailing comma...
return dumped.substr (0, dumped.length()-1) +")";
else
return dumped+")";
}
};

View file

@ -22,11 +22,32 @@
/** @file command-mutation.hpp
** The core of a Proc-Layer command: functor containing the actual operation to be executed.
** //TODO
**
** Core of a Proc-Layer command: functor containing the actual operation to be executed.
** Each command holds two of these functors: one representing the actual operation
** and one to undo the effect of this operation. The latter involves the capturing
** and storing of a "memento" value behind the scenes. But towards Command, the
** Mutation acts as interface to conceal these details, as well as the actual
** type and parameters of the functions to be invoked. Thus, Mutation's
** public interface just consists of a function call operator \c void() .
**
** \par Lifecycle
** Mutation objects are to be created based on a concrete function object, which then
** gets embedded into a type erasure container, thus disposing the specific type information.
** Moreover, building on this lib::OpaqueHolder yields a fixed size storage for Mutation objects,
** allowing them to be embedded immediately within the Command instance.
**
** Later on, any command needs to be made ready for execution by binding it to a specific
** execution environment, which especially includes the target objects to be mutated by the
** command. This procedure includes "closing" the Mutation (and UNDO) functor(s) with the
** actual function arguments. These arguments are stored embedded within an ArgumentHolder,
** which thereby acts as closure. Besides, the ArgumentHolder also has to accommodate for
** storage holding the captured UNDO state (memento). Thus, internally the ArgumentHolder
** has to keep track of the actual types, thus allowing to re-construct the concrete
** function signature when closing the Mutation.
**
** @see Command
** @see ProcDispatcher
** @see MementoTie binding memento state
**
*/
@ -41,9 +62,6 @@
#include "proc/control/command-closure.hpp"
#include "proc/control/memento-tie.hpp"
//#include <tr1/memory>
#include <boost/scoped_ptr.hpp>
#include <tr1/functional>
#include <iostream>
#include <string>
@ -51,10 +69,6 @@
namespace control {
// using lumiera::Symbol;
// using std::tr1::shared_ptr;
using boost::scoped_ptr;
using std::tr1::function;
using std::ostream;
using std::string;
@ -63,7 +77,13 @@ namespace control {
/**
* @todo Type-comment
* Unspecific command functor for implementing Proc-Layer Command.
* To be created from an tr1::function object, which later on
* can be \link #close closed \endlink with a set of actual
* function arguments. The concrete type of the function
* and the arguments is concealed (erased) on the interface,
* while the unclosed/closed - state of the functor can be
* checked by bool() conversion.
*/
class Mutation
: public lib::BoolCheckable<Mutation>
@ -105,7 +125,8 @@ namespace control {
/** diagnostics */
operator string() const
{
return isValid()? string (*clo_) : "Mutation(state missing)";
return isValid()? "Mutation("+string (*clo_)+")"
: "Mutation(untied)";
}
virtual bool
@ -114,7 +135,8 @@ namespace control {
return func_ && clo_;
}
protected:
private:
void
invoke (CmdFunctor & closedFunction)
{
@ -128,8 +150,21 @@ namespace control {
/**
* @todo Type-comment
* Specialised version of the command Mutation functor,
* used to implement the UNDO functionality. The operation
* executed when invoking this functor is the UNDO operation
* of the respective command; additionally we need another
* functor to capture the state to be restored on UNDO.
* Both functors are wired up internally to cooperate
* and store the state (memento), which is implemented
* by the specifically typed MementoTie object passed
* in on construction. All these specific details
* are concealed on the interface
*/
class UndoMutation
: public Mutation
@ -143,11 +178,6 @@ namespace control {
, captureMemento_(mementoHolder.tieCaptureFunc())
{ }
// UndoMutation (UndoMutation const& o)
// : Mutation(o)
// , captureMemento_(o.captureMemento_)
// { }
virtual Mutation&
close (CmdClosure& cmdClosure)
@ -172,16 +202,13 @@ namespace control {
private:
virtual bool
isValid () const
isValid () const
{
return Mutation::isValid() && captureMemento_;
}
};
////////////////TODO currently just fleshing out the API....
} // namespace control

View file

@ -50,7 +50,6 @@
namespace control {
using std::tr1::ref;
using lumiera::typelist::func::bindLast;
using lumiera::typelist::func::chained;

View file

@ -11,10 +11,14 @@ PLANNED "CommandArgument_test" CommandArgument_test <<END
END
PLANNED "CommandMutation_test" CommandMutation_test <<END
TEST "Command functor" CommandMutation_test <<END
out: Mutation\(untied\)
out: param values: Closure\(23\)
out: Mutation\(Closure\(23\)\)
out: saved state: 11
END
Test "MementoTie_test" MementoTie_test <<END
TEST "Memento binding" MementoTie_test <<END
return: 0
END

View file

@ -50,7 +50,7 @@ test_components_SOURCES = \
$(testcomponents_srcdir)/proc/control/command-basic-test.cpp \
$(testcomponents_srcdir)/proc/control/command-argument-test.cpp \
$(testcomponents_srcdir)/proc/control/command-mutation-test.cpp \
$(testcomponents_srcdir)/proc/control/memento-tie-test.cpp \
$(testcomponents_srcdir)/proc/control/memento-tie-test.cpp \
$(testcomponents_srcdir)/proc/engine/bufftabletest.cpp \
$(testcomponents_srcdir)/proc/engine/sourcenodetest.cpp \
$(testcomponents_srcdir)/proc/mobject/builder/buildertooltest.cpp \

View file

@ -69,7 +69,7 @@ namespace test {
using lumiera::P;
using lumiera::typelist::BuildTupleAccessor;
//using lumiera::typelist::BuildTupleAccessor;

View file

@ -22,36 +22,17 @@
#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-mutation.hpp"
#include "proc/control/memento-tie.hpp"
#include "lib/meta/typelist.hpp"
#include "lib/meta/tuple.hpp"
//#include "lib/lumitime.hpp"
//#include "lib/util.hpp"
#include <tr1/functional>
//#include <boost/format.hpp>
#include <iostream>
#include <cstdlib>
#include <string>
using std::tr1::bind;
//using std::tr1::placeholders::_1;
//using std::tr1::placeholders::_2;
using std::tr1::function;
//using boost::format;
//using lumiera::Time;
//using util::contains;
using std::string;
using std::rand;
using std::cout;
@ -60,25 +41,15 @@ using std::endl;
namespace control {
namespace test {
using lib::test::showSizeof;
// using session::test::TestClip;
// using lumiera::P;
using namespace lumiera::typelist;
using lumiera::typelist::Tuple;
using namespace lumiera::typelist;
using control::CmdClosure;
namespace {
namespace { /* ======= test functions to bind ========= */
int testVal=0; ///< used to verify the effect of testFunc
void
testFunc (int val)
{
@ -114,6 +85,7 @@ namespace test {
{
checkMutation();
checkUndoMutation();
checkStateCapturingMechanism();
}
@ -125,11 +97,12 @@ namespace test {
void
checkMutation ()
{
function<void(int)> funky = bind (testFunc, _1);
function<void(int)> funky = testFunc;
Mutation functor (funky);
ASSERT (!functor);
VERIFY_ERROR (UNBOUND_ARGUMENTS, functor() );
cout << functor << endl;
Tuple<Types<int> > param = tuple::make(23);
Closure<void(int)> close_over (param);
@ -139,6 +112,7 @@ namespace test {
ASSERT (functor);
cout << "param values: " << clo << endl;
cout << functor << endl;
testVal = 0;
functor();
@ -154,8 +128,8 @@ namespace test {
* captured state value. Consequently this time the \em operation
* which is to be undone would have the signature \c void(void) .
* Obviously this is a rather silly "undo" function, but it is
* easy to check in a unit test. To carry out this test, we first
* have to trigger the state capturing mechanism; after that,
* easy to check for unit testing. To carry out this test, we
* first have to trigger the state capturing mechanism; after that,
* invoking the UndoMutation will call the testFunc with the
* previously captured state.
* @note Mutation and UndoMutation are value objects, but they refer
@ -166,27 +140,29 @@ namespace test {
void
checkUndoMutation ()
{
function<void(int)> undo_func = bind (&testFunc,_1);
function<int(void)> cap_func = bind (&capture );
function<void(int)> undo_func = testFunc;
function<int(void)> cap_func = capture;
typedef MementoTie<void(),int> MemHolder;
MemHolder mementoHolder (undo_func,cap_func);
UndoMutation undoFunctor (mementoHolder);
ASSERT (!undoFunctor);
ASSERT (!mementoHolder);
VERIFY_ERROR (UNBOUND_ARGUMENTS, undoFunctor() );
Tuple<Types<> > param;
Closure<void()> clo (param);
undoFunctor.close(clo);
ASSERT (!undoFunctor);
ASSERT ( undoFunctor);
ASSERT (!mementoHolder);
VERIFY_ERROR (MISSING_MEMENTO, undoFunctor() );
VERIFY_ERROR (MISSING_MEMENTO, mementoHolder.getState() );
testVal = 11;
undoFunctor.captureState();
ASSERT (undoFunctor);
ASSERT (mementoHolder);
ASSERT (testVal == 11);
int mem = mementoHolder.getState();
@ -217,11 +193,33 @@ namespace test {
}
/** @test check the undo memento capturing mechanism in isolation
* @see memento-tie-test.cpp more in-depth coverage */
void
checkStateCapturingMechanism ()
{
typedef MementoTie<void(),int> MemHolder;
MemHolder mementoHolder (testFunc, capture);
function<void()> bound_undo_func = mementoHolder.tieUndoFunc();
function<void()> bound_cap_func = mementoHolder.tieCaptureFunc();
int rr (rand() % 100);
testVal = rr;
bound_cap_func(); // invoke state capturing
ASSERT (rr == mementoHolder.getState());
testVal = 10; // meanwhile "somehow" mutate the state
bound_undo_func(); // invoking the undo() feeds back the memento
ASSERT (testVal == 10+rr);
}
};
/** Register this test class... */
LAUNCHER (CommandMutation_test, "unit controller");
}} // namespace control::test