Lumiera  0.pre.03
»edityourfreedom«
command-argument-test.cpp
Go to the documentation of this file.
1 /*
2  CommandArgument(Test) - checking storage of specifically typed command arguments
3 
4  Copyright (C) Lumiera.org
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
28 #include "lib/test/run.hpp"
29 #include "lib/test/test-helper.hpp"
31 #include "lib/scoped-ptrvect.hpp"
32 #include "lib/format-string.hpp"
33 #include "lib/format-cout.hpp"
34 #include "lib/util-foreach.hpp"
35 #include "lib/util.hpp"
36 
37 #include <functional>
38 #include <sstream>
39 #include <cstdlib>
40 #include <string>
41 #include <tuple>
42 
43 using util::_Fmt;
44 using util::isnil;
45 using util::for_each;
46 using lib::time::Time;
47 using lib::time::TimeVar;
49 using std::string;
50 using std::ostringstream;
51 using std::make_tuple;
52 using std::rand;
53 
54 
55 namespace proc {
56 namespace control {
57 namespace test {
58 
60  using lib::test::randTime;
61  using namespace lib::meta;
62 
63 
64 
65 
66 
67  namespace { // test helpers
68 
69  ostringstream protocol;
70 
71 
76  template<typename TY>
77  struct Tracker
78  {
79  TY element_;
80  static int instanceCnt;
81 
82  Tracker (TY init = TY()) : element_(init) { ++instanceCnt; }
83  Tracker (Tracker const& otr) : element_(otr.element_) { ++instanceCnt; }
84  ~Tracker() { --instanceCnt; }
85 
86  TY&
87  operator* ()
88  {
89  return element_;
90  }
91 
92  operator string() const { return element_; }
93 
94 
95  friend bool
96  operator== (Tracker const& tra1, Tracker const& tra2)
97  {
98  return tra1.element_ == tra2.element_;
99  }
100  };
101 
102  template<typename TY>
103  int Tracker<TY>::instanceCnt (0);
104 
113  void
114  prepareEmptyMemento()
115  {
117  }
118 
122  struct Sint5
123  {
124  int i[5];
125 
126  friend bool
127  operator== (Sint5 const& i1, Sint5 const& i2)
128  {
129  return i1.i == i2.i;
130  }
131  };
132 
133 
134 
135  /* === functions to implement test-"operation" & UNDO === */
136 
137  void
138  doIt (Tracker<TimeVar> time, Tracker<string> str, int rand)
139  {
140  static _Fmt fmt ("doIt( Time=%s \"%s\" rand=%2d )");
141  cout << "invoke operation..." << endl;
142  protocol << fmt % *time % *str % rand;
143  }
144 
145  Tracker<string>
146  captureState (Tracker<TimeVar>, Tracker<string> xstr, int)
147  {
148  cout << "capture state..." << endl;
149  return protocol.str() + *xstr;
150  }
151 
152  void
153  undoIt (Tracker<TimeVar> time, Tracker<string>, int, Tracker<string> memento)
154  {
155  cout << "undo... memento=" << memento << endl;
156  protocol << "undoIt(time="<<time<<")----memento-:"<< *memento;
157  }
158 
159 
161  void dummyU (int,int,int) { }
162  int dummyC (int u,int o) { return u + rand() % (o-u+1); }
163 
164 
165 
166  void
167  showIt (CmdClosure& clo)
168  {
169  cout << clo << endl;
170  }
171 
172  void
173  checkSerialisation (CmdClosure& clo)
174  {
175  TODO ("implement serialisation/de-serialisation-Check");
176  cout << "would be serialised....." << clo << endl;
177 
178  // serialise, then de-serialise into a new instance and compare both
179  }
180 
181 
182  int
183  twoRandomDigits()
184  {
185  return 10 + rand() % 90;
186  }
187 
188 
189  } // test-helper implementation
190 
191 
192 
193 
194 
195 
197 
198  /***********************************************************************/
204  class CommandArgument_test : public Test
205  {
206 
207  virtual void
209  {
210  ArgTuples testTuples;
211  prepareEmptyMemento();
212  Tracker<TimeVar>::instanceCnt = 0;
213  Tracker<string>::instanceCnt = 0;
214 
215  createTuples (testTuples);
216  checkArgumentComparison ();
217  serialiseArgTuples (testTuples);
218  testTuples.clear();
219 
220  simulateCmdLifecycle();
221 
222  // verify all dtors properly called...
223  CHECK (0 == Tracker<TimeVar>::instanceCnt);
224  CHECK (0 == Tracker<string>::instanceCnt);
225  }
226 
227 
228  typedef Tracker<TimeVar> TTime;
229  typedef Tracker<string> Tstr;
230 
231 
232 
233 
235  void
236  createTuples (ArgTuples& tup)
237  {
238  typedef StorageHolder<void(), bool> A1;
242 
244 
245 
246  A1* arg1 = new A1(); tup.manage (arg1);
247  A2* arg2 = new A2(); tup.manage (arg2);
248  A3* arg3 = new A3(); tup.manage (arg3);
249  A4* arg4 = new A4(); tup.manage (arg4);
250  A5* arg5 = new A5(); tup.manage (arg5);
251 
252  CHECK (isnil (*arg1));
253  CHECK (isnil (*arg2));
254  CHECK (isnil (*arg3));
255  CHECK (isnil (*arg4));
256  CHECK (isnil (*arg5));
257 
258  for_each (tup, showIt);
259 
260  arg1->storeTuple (std::tuple<>());
261  arg2->storeTuple (make_tuple (rand() % 10));
262  arg3->storeTuple (make_tuple (rand() % 10, TimeVar(randTime())));
263  arg4->storeTuple (make_tuple (rand() % 10, TimeVar(randTime())));
264 
265  arg5->storeTuple (make_tuple (TTime (randTime()), Tstr("glorious"), twoRandomDigits() ));
266 
267  CHECK (!arg5->canUndo());
268 
269  arg5->tie(undoIt, captureState)
270  .tieCaptureFunc() // bind capturing function to memento storage,
271  (TTime(), Tstr("destruction"), 11); // then invoke the bound capturing mechanism
272 
273  CHECK (arg5->canUndo());
274  CHECK (*arg5->memento() == "destruction");
275 
276  VERIFY_ERROR(MISSING_MEMENTO, arg4->memento().i[3] = 513 );
277 
278  for_each (tup, showIt);
279  }
280 
281 
282 
286  void
287  serialiseArgTuples (ArgTuples& tup)
288  {
289  for_each (tup, checkSerialisation);
290  }
291 
292 
293 
295  void
297  {
299  CHECK (one == two); // empty, identically typed argument holders -->equal
300 
301  one.tie(dummyU,dummyC)
302  .tieCaptureFunc()(1,9);
303  CHECK (one != two); // now one contains captured UNDO state
304 
305  two.tie(dummyU,dummyC)
306  .tieCaptureFunc()(1,9);
307  two.memento() = one.memento(); // put the same UNDO state in both
308  CHECK (one == two); // ...makes them equal again
309 
310  one.storeTuple (make_tuple (1,2));
311  CHECK (one != two); // verify argument tuple comparison
312  CHECK (two != one);
313  CHECK (!isnil (one));
314  CHECK ( isnil (two));
315 
316  two.storeTuple (make_tuple (3,4));
317  CHECK (!isnil (two));
318  CHECK (one != two);
319  CHECK (two != one);
320 
321  one.storeTuple (make_tuple (1,4));
322  CHECK (!isnil (one));
323  CHECK (one != two);
324  CHECK (two != one);
325 
326  one.storeTuple (make_tuple (3,4));
327  CHECK (!isnil (one));
328  CHECK (one == two);
329  CHECK (two == one);
330  two.memento() = 12345;
331  CHECK (!isnil (two));
332  CHECK (one != two);
333  CHECK (two != one);
334  }
335 
336 
337 
341  void
343  {
344  typedef void SIG_do(Tracker<TimeVar>, Tracker<string>, int);
346  using MemHolder = MementoTie<SIG_do, Tracker<string>>;
347 
348  Args args;
349  CHECK (isnil (args));
350  cout << showSizeof(args) << endl;
351 
352  // store a set of parameter values, later to be used on invocation
353  args.storeTuple (
354  make_tuple (TTime(randTime()), Tstr("Lumiera rocks"), twoRandomDigits() ));
355  CHECK (!isnil (args));
356  cout << args << endl;
357 
358  CHECK (!args.canUndo());
359  VERIFY_ERROR(MISSING_MEMENTO, args.memento() );
360 
361  MemHolder& memHolder = args.tie(undoIt,captureState);
362  CHECK (!memHolder); // no stored memento....
363  CHECK (!args.canUndo());
364 
365  function<SIG_do> doItFun = doIt;
366  function<SIG_do> undoFun = memHolder.tieUndoFunc();
367  function<SIG_do> captFun = memHolder.tieCaptureFunc();
368 
369  typedef function<void()> OpFun;
370 
371  // now close all the functions with the stored parameter values...
372  OpFun bound_doItFun = std::bind (&CmdClosure::invoke, args, CmdFunctor(doItFun));
373  OpFun bound_undoFun = std::bind (&CmdClosure::invoke, args, CmdFunctor(undoFun));
374  OpFun bound_captFun = std::bind (&CmdClosure::invoke, args, CmdFunctor(captFun));
375 
376  protocol.seekp(0);
377  protocol << "START...";
378 
379  bound_captFun();
380  cout << "captured state: " << args.memento() << endl;
381  CHECK (memHolder);
382  CHECK (!isnil (*args.memento()));
383  CHECK (args.canUndo());
384  cout << args << endl;
385 
386  bound_doItFun();
387  cout << protocol.str() << endl;
388  bound_undoFun();
389  cout << protocol.str() << endl;
390 
391  // Commands can serve as prototype to be copied....
392  Args argsCopy (args);
393  bound_captFun();
394  protocol.seekp(0);
395  protocol << "RESET...";
396 
397  args.storeTuple (
398  make_tuple (TTime(TimeValue(123456)), Tstr("unbelievable"), twoRandomDigits() ));
399  cout << "modified: " << args << endl;
400  cout << "copied : " << argsCopy << endl; // holds still the old params & memento
401 
402  bound_undoFun();
403  cout << protocol.str() << endl;
404  }
405 
406  };
407 
408 
409 
411  LAUNCHER (CommandArgument_test, "unit controller");
412 
413 
414 }}} // namespace proc::control::test
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:142
void storeTuple(ArgTuple const &argTup)
store a new argument tuple within this StorageHolder, discarding any previously stored arguments ...
Automatically use custom string conversion in C++ stream output.
string showSizeof(size_t siz, string name)
for printing sizeof().
Definition: test-helper.cpp:48
void undoIt(int, int64_t oldVal)
Definition: run.hpp:49
Front-end for printf-style string template interpolation.
Singleton holder for NIL or default value objects.
Definition: null-value.hpp:72
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify a statement indeed raises an exception.
A front-end for using printf-style formatting.
Managing lifecycle for a collection of objects.
MEM & memento()
direct "backdoor" access to stored memento value.
FunErasure< StoreFunction > CmdFunctor
A neutral container internally holding the functor used to implement the Command. ...
Simple vector based collection of pointers, managing lifecycle of the pointed-to objects.
bool operator==(Command const &c1, Command const &c2)
Definition: command.hpp:312
std::vector< string > & Arg
Definition: run.hpp:54
LAUNCHER(ArgumentTupleAccept_test, "unit controller")
Register this test class...
Simple test class runner.
This is "the" top level CmdClosure implementation.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Offset operator*(Offset const &distance, INT factor)
Definition: timevalue.hpp:341
A collection of frequently used helper functions to support unit testing.
bool isnil(lib::time::Duration const &dur)
Definition: timevalue.hpp:642
Binding together state capturing and execution of the undo operation.
Definition: memento-tie.hpp:90
MementoTie< SIG, MEM > & tie(function< SIG_undo > const &undoFunc, function< SIG_cap > const &captureFunc)
create a new memento storage wiring, discarding existing memento state.
Proc-Layer implementation namespace root.
Definition: id-scheme.hpp:63
lib::time::Time randTime()
create a random but not insane Time value
disable_if< can_IterForEach< Container >, FUN > for_each(Container const &coll, FUN doIt)
operate on all elements of a STL container.
basic constant internal time value.
Definition: timevalue.hpp:80
lib::ScopedPtrVect< CmdClosure > ArgTuples
Perform operations "for each element" of a collection.
T & manage(T *obj)
take ownership of the given object, adding it at the end of the collection
virtual void invoke(CmdFunctor const &)=0
invoke functor using the stored parameter values
A passive container record holding the actual command arguments & UNDO state.