Lumiera  0.pre.03
»edit your freedom«
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)
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"
22 #include "lib/scoped-ptrvect.hpp"
23 #include "lib/format-string.hpp"
24 #include "lib/format-cout.hpp"
25 #include "lib/util-foreach.hpp"
26 #include "lib/util.hpp"
27 
28 #include <functional>
29 #include <sstream>
30 #include <cstdlib>
31 #include <string>
32 #include <tuple>
33 
34 using util::_Fmt;
35 using util::isnil;
36 using util::for_each;
37 using lib::time::Time;
38 using lib::time::TimeVar;
40 using std::string;
41 using std::ostringstream;
42 using std::make_tuple;
43 using std::rand;
44 
45 
46 namespace steam {
47 namespace control {
48 namespace test {
49 
50  using lib::test::showSizeof;
51  using lib::test::randTime;
52  using namespace lib::meta;
53  using LERR_(MISSING_MEMENTO);
54 
55 
56 
57  namespace { // test helpers
58 
59  ostringstream protocol;
60 
61 
66  template<typename TY>
67  struct Tracker
68  {
69  TY element_;
70  static int instanceCnt;
71 
72  Tracker (TY init = TY()) : element_(init) { ++instanceCnt; }
73  Tracker (Tracker const& otr) : element_(otr.element_) { ++instanceCnt; }
74  ~Tracker() { --instanceCnt; }
75 
76  TY&
77  operator* ()
78  {
79  return element_;
80  }
81 
82  operator string() const { return element_; }
83 
84 
85  friend bool
86  operator== (Tracker const& tra1, Tracker const& tra2)
87  {
88  return tra1.element_ == tra2.element_;
89  }
90  };
91 
92  template<typename TY>
94 
103  void
105  {
107  }
108 
112  struct Sint5
113  {
114  int i[5];
115 
116  friend bool
117  operator== (Sint5 const& i1, Sint5 const& i2)
118  {
119  return i1.i == i2.i;
120  }
121  };
122 
123 
124 
125  /* === functions to implement test-"operation" & UNDO === */
126 
127  void
128  doIt (Tracker<TimeVar> time, Tracker<string> str, int rand)
129  {
130  static _Fmt fmt ("doIt( Time=%s \"%s\" rand=%2d )");
131  cout << "invoke operation..." << endl;
132  protocol << fmt % *time % *str % rand;
133  }
134 
136  captureState (Tracker<TimeVar>, Tracker<string> xstr, int)
137  {
138  cout << "capture state..." << endl;
139  return protocol.str() + *xstr;
140  }
141 
142  void
143  undoIt (Tracker<TimeVar> time, Tracker<string>, int, Tracker<string> memento)
144  {
145  cout << "undo... memento=" << memento << endl;
146  protocol << "undoIt(time="<<time<<")----memento-:"<< *memento;
147  }
148 
149 
151  void dummyU (int,int,int) { }
152  int dummyC (int u,int o) { return u + rani(o-u+1); }
153 
154 
155 
156  void
157  showIt (CmdClosure& clo)
158  {
159  cout << clo << endl;
160  }
161 
162  void
163  checkSerialisation (CmdClosure& clo)
164  {
165  TODO ("implement serialisation/de-serialisation-Check");
166  cout << "would be serialised....." << clo << endl;
167 
168  // serialise, then de-serialise into a new instance and compare both
169  }
170 
171 
172  int
173  twoRandomDigits()
174  {
175  return 10 + rani(90);
176  }
177 
178 
179  } // test-helper implementation
180 
181 
182 
183 
184 
185 
187 
188  /***********************************************************************/
194  class CommandArgument_test : public Test
195  {
196 
197  virtual void
198  run (Arg)
199  {
200  seedRand();
201  ArgTuples testTuples;
203  Tracker<TimeVar>::instanceCnt = 0;
204  Tracker<string>::instanceCnt = 0;
205 
206  createTuples (testTuples);
207  serialiseArgTuples (testTuples);
208  testTuples.clear();
209 
210  simulateCmdLifecycle();
211 
212  // verify all dtors properly called...
213  CHECK (0 == Tracker<TimeVar>::instanceCnt);
214  CHECK (0 == Tracker<string>::instanceCnt);
215  }
216 
217 
218  typedef Tracker<TimeVar> TTime;
219  typedef Tracker<string> Tstr;
220 
221 
222 
223 
225  void
226  createTuples (ArgTuples& tup)
227  {
228  typedef StorageHolder<void(), bool> A1;
232 
234 
235 
236  A1* arg1 = new A1(); tup.manage (arg1);
237  A2* arg2 = new A2(); tup.manage (arg2);
238  A3* arg3 = new A3(); tup.manage (arg3);
239  A4* arg4 = new A4(); tup.manage (arg4);
240  A5* arg5 = new A5(); tup.manage (arg5);
241 
242  CHECK (isnil (*arg1));
243  CHECK (isnil (*arg2));
244  CHECK (isnil (*arg3));
245  CHECK (isnil (*arg4));
246  CHECK (isnil (*arg5));
247 
248  for_each (tup, showIt);
249 
250  arg1->storeTuple (std::tuple<>());
251  arg2->storeTuple (make_tuple (rani(10)));
252  arg3->storeTuple (make_tuple (rani(10), TimeVar(randTime())));
253  arg4->storeTuple (make_tuple (rani(10), TimeVar(randTime())));
254 
255  arg5->storeTuple (make_tuple (TTime (randTime()), Tstr("glorious"), twoRandomDigits() ));
256 
257  CHECK (!arg5->canUndo());
258 
259  arg5->tie(undoIt, captureState)
260  .tieCaptureFunc() // bind capturing function to memento storage,
261  (TTime(), Tstr("destruction"), 11); // then invoke the bound capturing mechanism
262 
263  CHECK (arg5->canUndo());
264  CHECK (*arg5->memento() == "destruction");
265 
266  VERIFY_ERROR(MISSING_MEMENTO, arg4->memento().i[3] = 513 );
267 
268  for_each (tup, showIt);
269  }
270 
271 
272 
276  void
277  serialiseArgTuples (ArgTuples& tup)
278  {
279  for_each (tup, checkSerialisation);
280  }
281 
282 
283 
287  void
289  {
290  typedef void SIG_do(Tracker<TimeVar>, Tracker<string>, int);
292  using MemHolder = MementoTie<SIG_do, Tracker<string>>;
293 
294  Args args;
295  CHECK (isnil (args));
296  cout << showSizeof(args) << endl;
297 
298  // store a set of parameter values, later to be used on invocation
299  args.storeTuple (
300  make_tuple (TTime(randTime()), Tstr("Lumiera rocks"), twoRandomDigits() ));
301  CHECK (!isnil (args));
302  cout << args << endl;
303 
304  CHECK (!args.canUndo());
305  VERIFY_ERROR(MISSING_MEMENTO, args.memento() );
306 
307  MemHolder& memHolder = args.tie(undoIt,captureState);
308  CHECK (!memHolder); // no stored memento....
309  CHECK (!args.canUndo());
310 
311  function<SIG_do> doItFun = doIt;
312  function<SIG_do> undoFun = memHolder.tieUndoFunc();
313  function<SIG_do> captFun = memHolder.tieCaptureFunc();
314 
315  typedef function<void()> OpFun;
316 
317  // now close all the functions with the stored parameter values...
318  OpFun bound_doItFun = std::bind (&CmdClosure::invoke, args, CmdFunctor(doItFun));
319  OpFun bound_undoFun = std::bind (&CmdClosure::invoke, args, CmdFunctor(undoFun));
320  OpFun bound_captFun = std::bind (&CmdClosure::invoke, args, CmdFunctor(captFun));
321 
322  protocol.seekp(0);
323  protocol << "START...";
324 
325  bound_captFun();
326  cout << "captured state: " << args.memento() << endl;
327  CHECK (memHolder);
328  CHECK (!isnil (*args.memento()));
329  CHECK (args.canUndo());
330  cout << args << endl;
331 
332  bound_doItFun();
333  cout << protocol.str() << endl;
334  bound_undoFun();
335  cout << protocol.str() << endl;
336 
337  // Commands can serve as prototype to be copied....
338  Args argsCopy (args);
339  bound_captFun();
340  protocol.seekp(0);
341  protocol << "RESET...";
342 
343  args.storeTuple (
344  make_tuple (TTime(TimeValue(123456)), Tstr("unbelievable"), twoRandomDigits() ));
345  cout << "modified: " << args << endl;
346  cout << "copied : " << argsCopy << endl; // holds still the old params & memento
347 
348  bound_undoFun();
349  cout << protocol.str() << endl;
350  }
351 
352  };
353 
354 
355 
357  LAUNCHER (CommandArgument_test, "unit controller");
358 
359 
360 }}} // namespace steam::control::test
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:232
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:40
FunErasure< StoreFunction > CmdFunctor
A neutral container internally holding the functor used to implement the Command. ...
void prepareEmptyMemento()
prepare a (singleton) empty value for the memento.
ostringstream protocol
used to verify the test function calls
Front-end for printf-style string template interpolation.
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
Singleton holder for NIL or default value objects.
Definition: null-value.hpp:62
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Steam-Layer implementation namespace root.
A front-end for using printf-style formatting.
Managing lifecycle for a collection of objects.
Simple vector based collection of pointers, managing lifecycle of the pointed-to objects.
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:299
virtual void invoke(CmdFunctor const &)=0
invoke functor using the stored parameter values
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
void for_each(CON const &elements, FUN function, P1 &&bind1, ARGS &&...args)
Accept binding for arbitrary function arguments.
A collection of frequently used helper functions to support unit testing.
lib::time::Time randTime()
create a random but not insane Time value between 1s ...
basic constant internal time value.
Definition: timevalue.hpp:133
Binding together state capturing and execution of the undo operation.
Definition: memento-tie.hpp:79
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
This is "the" top level CmdClosure implementation.
A passive container record holding the actual command arguments & UNDO state.