Lumiera  0.pre.03
»edit your freedom«
command-mutation-test.cpp
Go to the documentation of this file.
1 /*
2  CommandMutation(Test) - checking the functor and undo-functor used within Steam-commands
3 
4  Copyright (C)
5  2009, 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"
20 #include "lib/test/test-helper.hpp"
25 #include "lib/meta/typelist.hpp"
26 #include "lib/format-cout.hpp"
27 
28 #include <functional>
29 #include <cstdlib>
30 #include <string>
31 
32 using std::function;
33 using std::string;
34 using std::rand;
35 
36 
37 namespace steam {
38 namespace control {
39 namespace test {
40 
41  using namespace lib::meta;
42  using control::CmdClosure;
43  using LERR_(MISSING_MEMENTO);
44  using LERR_(UNBOUND_ARGUMENTS);
45 
46 
47  namespace { /* ======= test functions to bind ========= */
48 
49  int testVal=0;
50 
51  void
52  testFunc (int val)
53  {
54  testVal += val;
55  }
56 
57  int
58  capture ()
59  {
60  return testVal;
61  }
62 
63  }
64 
65 
66 
67  /***********************************************************************/
78  class CommandMutation_test : public Test
79  {
80 
81  virtual void
82  run (Arg)
83  {
84  seedRand();
85 
86  checkMutation();
87  checkUndoMutation();
88  checkStateCapturingMechanism();
89  }
90 
91 
96  void
98  {
99  typedef void SIG_fun(int);
100  function<SIG_fun> funky = testFunc;
101 
102  Mutation functor (funky);
103 
104  SimpleClosure<SIG_fun> nullClosure;
105  CHECK (not nullClosure.isValid());
106  cout << "empty placeholder closure: " << nullClosure << endl;
107  VERIFY_ERROR (UNBOUND_ARGUMENTS, functor(nullClosure) );
108 
109  // now create a real closure....
110  Tuple<Types<int>> param = std::make_tuple (23);
111  SimpleClosure<void(int)> closed_over{param};
112 
113  CmdClosure& closure (closed_over);
114  CHECK (closure);
115 
116  cout << "param values: " << closure << endl;
117 
118  testVal = 0;
119  functor(closure);
120  CHECK (testVal == 23);
121  functor(closure);
122  CHECK (testVal == 2*23);
123  }
124 
125 
141  void
143  {
144  function<void(int)> undo_func = testFunc;
145  function<int(void)> cap_func = capture;
146 
147  typedef MementoTie<void(),int> MemHolder;
148 
149  MemHolder mementoHolder (undo_func,cap_func);
150  UndoMutation undoFunctor (mementoHolder);
151  CHECK (!mementoHolder);
152 
153  SimpleClosure<void(void)> nullClosure;
154  VERIFY_ERROR (UNBOUND_ARGUMENTS, undoFunctor(nullClosure) );
155  VERIFY_ERROR (UNBOUND_ARGUMENTS, undoFunctor.captureState(nullClosure) );
156 
157  Tuple<Types<> > param;
158  SimpleClosure<void()> clo{param};
159 
160  CHECK (!mementoHolder);
161  VERIFY_ERROR (MISSING_MEMENTO, undoFunctor (clo) );
162  VERIFY_ERROR (MISSING_MEMENTO, mementoHolder.getState() );
163 
164  testVal = 11;
165  undoFunctor.captureState(clo);
166  CHECK (mementoHolder);
167  CHECK (testVal == 11);
168 
169  int mem = mementoHolder.getState();
170  cout << "saved state: " << mem << endl;
171 
172  undoFunctor(clo);
173  CHECK (testVal == 11 + 11);
174  undoFunctor(clo);
175  CHECK (testVal == 11 + 11 + 11);
176  undoFunctor.captureState(clo);
177  CHECK (33 == mementoHolder.getState());
178  undoFunctor(clo);
179  CHECK (testVal == 33 + 33);
180  testVal = 9;
181  undoFunctor(clo);
182  CHECK (testVal == 42);
183  }
184 
185 
188  void
190  {
191  typedef MementoTie<void(),int> MemHolder;
192 
193  MemHolder mementoHolder (testFunc, capture);
194 
195  function<void()> bound_undo_func = mementoHolder.tieUndoFunc();
196  function<void()> bound_cap_func = mementoHolder.tieCaptureFunc();
197 
198 
199  int rr{rani (100)};
200  testVal = rr;
201  bound_cap_func(); // invoke state capturing
202  CHECK (rr == mementoHolder.getState());
203 
204  testVal = 10; // meanwhile "somehow" mutate the state
205  bound_undo_func(); // invoking the undo() feeds back the memento
206  CHECK (testVal == 10+rr);
207  }
208  };
209 
210 
212  LAUNCHER (CommandMutation_test, "unit controller");
213 
214 
215 }}} // namespace steam::control::test
Automatically use custom string conversion in C++ stream output.
A template metaprogramming technique for manipulating collections of types.
typename BuildTupleType< TYPES >::Type Tuple
Build a std::tuple from types given as type sequence.
Definition: run.hpp:40
Core of a Steam-Layer command: functor containing the operation to be executed.
Proof-of-concept implementation of CmdClosure.
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Steam-Layer implementation namespace root.
Metaprogramming with tuples-of-types and the std::tuple record.
Specialised version of the command Mutation functor, used to implement the UNDO functionality.
A special binding used by Steam-Layer commands for capturing UNDO state information.
Simplistic test class runner.
Dummy / proof-of-concept implementation of CmdClosure.
A collection of frequently used helper functions to support unit testing.
Unspecific command functor for implementing Steam-Layer Command.
virtual bool isValid() const override
does this closure hold a valid argument tuple?
Binding together state capturing and execution of the undo operation.
Definition: memento-tie.hpp:79
Verify the behaviour of the type erased closure, which is used by Steam-Layer commands to implement t...