Lumiera  0.pre.03
»edityourfreedom«
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
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...
LAUNCHER(ArgumentTupleAccept_test,"unit controller")
Register this test class...
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
Offset operator*(boost::rational< int64_t > factor, Offset const &o)
stretch offset by a possibly fractional factor
Definition: time.cpp:217
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.