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) 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 steam {
56 namespace control {
57 namespace test {
58 
59  using lib::test::showSizeof;
60  using lib::test::randTime;
61  using namespace lib::meta;
62  using LERR_(MISSING_MEMENTO);
63 
64 
65 
66  namespace { // test helpers
67 
68  ostringstream protocol;
69 
70 
75  template<typename TY>
76  struct Tracker
77  {
78  TY element_;
79  static int instanceCnt;
80 
81  Tracker (TY init = TY()) : element_(init) { ++instanceCnt; }
82  Tracker (Tracker const& otr) : element_(otr.element_) { ++instanceCnt; }
83  ~Tracker() { --instanceCnt; }
84 
85  TY&
86  operator* ()
87  {
88  return element_;
89  }
90 
91  operator string() const { return element_; }
92 
93 
94  friend bool
95  operator== (Tracker const& tra1, Tracker const& tra2)
96  {
97  return tra1.element_ == tra2.element_;
98  }
99  };
100 
101  template<typename TY>
102  int Tracker<TY>::instanceCnt (0);
103 
112  void
114  {
116  }
117 
121  struct Sint5
122  {
123  int i[5];
124 
125  friend bool
126  operator== (Sint5 const& i1, Sint5 const& i2)
127  {
128  return i1.i == i2.i;
129  }
130  };
131 
132 
133 
134  /* === functions to implement test-"operation" & UNDO === */
135 
136  void
137  doIt (Tracker<TimeVar> time, Tracker<string> str, int rand)
138  {
139  static _Fmt fmt ("doIt( Time=%s \"%s\" rand=%2d )");
140  cout << "invoke operation..." << endl;
141  protocol << fmt % *time % *str % rand;
142  }
143 
145  captureState (Tracker<TimeVar>, Tracker<string> xstr, int)
146  {
147  cout << "capture state..." << endl;
148  return protocol.str() + *xstr;
149  }
150 
151  void
152  undoIt (Tracker<TimeVar> time, Tracker<string>, int, Tracker<string> memento)
153  {
154  cout << "undo... memento=" << memento << endl;
155  protocol << "undoIt(time="<<time<<")----memento-:"<< *memento;
156  }
157 
158 
160  void dummyU (int,int,int) { }
161  int dummyC (int u,int o) { return u + rand() % (o-u+1); }
162 
163 
164 
165  void
166  showIt (CmdClosure& clo)
167  {
168  cout << clo << endl;
169  }
170 
171  void
172  checkSerialisation (CmdClosure& clo)
173  {
174  TODO ("implement serialisation/de-serialisation-Check");
175  cout << "would be serialised....." << clo << endl;
176 
177  // serialise, then de-serialise into a new instance and compare both
178  }
179 
180 
181  int
182  twoRandomDigits()
183  {
184  return 10 + rand() % 90;
185  }
186 
187 
188  } // test-helper implementation
189 
190 
191 
192 
193 
194 
196 
197  /***********************************************************************/
203  class CommandArgument_test : public Test
204  {
205 
206  virtual void
207  run (Arg)
208  {
209  ArgTuples testTuples;
211  Tracker<TimeVar>::instanceCnt = 0;
212  Tracker<string>::instanceCnt = 0;
213 
214  createTuples (testTuples);
215  serialiseArgTuples (testTuples);
216  testTuples.clear();
217 
218  simulateCmdLifecycle();
219 
220  // verify all dtors properly called...
221  CHECK (0 == Tracker<TimeVar>::instanceCnt);
222  CHECK (0 == Tracker<string>::instanceCnt);
223  }
224 
225 
226  typedef Tracker<TimeVar> TTime;
227  typedef Tracker<string> Tstr;
228 
229 
230 
231 
233  void
234  createTuples (ArgTuples& tup)
235  {
236  typedef StorageHolder<void(), bool> A1;
240 
242 
243 
244  A1* arg1 = new A1(); tup.manage (arg1);
245  A2* arg2 = new A2(); tup.manage (arg2);
246  A3* arg3 = new A3(); tup.manage (arg3);
247  A4* arg4 = new A4(); tup.manage (arg4);
248  A5* arg5 = new A5(); tup.manage (arg5);
249 
250  CHECK (isnil (*arg1));
251  CHECK (isnil (*arg2));
252  CHECK (isnil (*arg3));
253  CHECK (isnil (*arg4));
254  CHECK (isnil (*arg5));
255 
256  for_each (tup, showIt);
257 
258  arg1->storeTuple (std::tuple<>());
259  arg2->storeTuple (make_tuple (rand() % 10));
260  arg3->storeTuple (make_tuple (rand() % 10, TimeVar(randTime())));
261  arg4->storeTuple (make_tuple (rand() % 10, TimeVar(randTime())));
262 
263  arg5->storeTuple (make_tuple (TTime (randTime()), Tstr("glorious"), twoRandomDigits() ));
264 
265  CHECK (!arg5->canUndo());
266 
267  arg5->tie(undoIt, captureState)
268  .tieCaptureFunc() // bind capturing function to memento storage,
269  (TTime(), Tstr("destruction"), 11); // then invoke the bound capturing mechanism
270 
271  CHECK (arg5->canUndo());
272  CHECK (*arg5->memento() == "destruction");
273 
274  VERIFY_ERROR(MISSING_MEMENTO, arg4->memento().i[3] = 513 );
275 
276  for_each (tup, showIt);
277  }
278 
279 
280 
284  void
285  serialiseArgTuples (ArgTuples& tup)
286  {
287  for_each (tup, checkSerialisation);
288  }
289 
290 
291 
295  void
297  {
298  typedef void SIG_do(Tracker<TimeVar>, Tracker<string>, int);
300  using MemHolder = MementoTie<SIG_do, Tracker<string>>;
301 
302  Args args;
303  CHECK (isnil (args));
304  cout << showSizeof(args) << endl;
305 
306  // store a set of parameter values, later to be used on invocation
307  args.storeTuple (
308  make_tuple (TTime(randTime()), Tstr("Lumiera rocks"), twoRandomDigits() ));
309  CHECK (!isnil (args));
310  cout << args << endl;
311 
312  CHECK (!args.canUndo());
313  VERIFY_ERROR(MISSING_MEMENTO, args.memento() );
314 
315  MemHolder& memHolder = args.tie(undoIt,captureState);
316  CHECK (!memHolder); // no stored memento....
317  CHECK (!args.canUndo());
318 
319  function<SIG_do> doItFun = doIt;
320  function<SIG_do> undoFun = memHolder.tieUndoFunc();
321  function<SIG_do> captFun = memHolder.tieCaptureFunc();
322 
323  typedef function<void()> OpFun;
324 
325  // now close all the functions with the stored parameter values...
326  OpFun bound_doItFun = std::bind (&CmdClosure::invoke, args, CmdFunctor(doItFun));
327  OpFun bound_undoFun = std::bind (&CmdClosure::invoke, args, CmdFunctor(undoFun));
328  OpFun bound_captFun = std::bind (&CmdClosure::invoke, args, CmdFunctor(captFun));
329 
330  protocol.seekp(0);
331  protocol << "START...";
332 
333  bound_captFun();
334  cout << "captured state: " << args.memento() << endl;
335  CHECK (memHolder);
336  CHECK (!isnil (*args.memento()));
337  CHECK (args.canUndo());
338  cout << args << endl;
339 
340  bound_doItFun();
341  cout << protocol.str() << endl;
342  bound_undoFun();
343  cout << protocol.str() << endl;
344 
345  // Commands can serve as prototype to be copied....
346  Args argsCopy (args);
347  bound_captFun();
348  protocol.seekp(0);
349  protocol << "RESET...";
350 
351  args.storeTuple (
352  make_tuple (TTime(TimeValue(123456)), Tstr("unbelievable"), twoRandomDigits() ));
353  cout << "modified: " << args << endl;
354  cout << "copied : " << argsCopy << endl; // holds still the old params & memento
355 
356  bound_undoFun();
357  cout << protocol.str() << endl;
358  }
359 
360  };
361 
362 
363 
365  LAUNCHER (CommandArgument_test, "unit controller");
366 
367 
368 }}} // namespace steam::control::test
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:241
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:49
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.
Singleton holder for NIL or default value objects.
Definition: null-value.hpp:71
#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:308
virtual void invoke(CmdFunctor const &)=0
invoke functor using the stored parameter values
Simple 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:142
Binding together state capturing and execution of the undo operation.
Definition: memento-tie.hpp:88
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.