Lumiera  0.pre.03
»edityourfreedom«
command-equality-test.cpp
Go to the documentation of this file.
1 /*
2  CommandEquality(Test) - verify equality comparisons on command's subsystems
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"
37 #include "lib/format-cout.hpp"
38 #include "lib/symbol.hpp"
39 #include "lib/util.hpp"
40 
41 #include <functional>
42 #include <string>
43 #include <tuple>
44 
45 namespace proc {
46 namespace control {
47 namespace test {
48 
49 
50 
51  using namespace lib::meta;
52  using lib::Symbol;
53  using util::isnil;
54  using util::isSameObject;
55 
56  using std::function;
57  using std::bind;
58  using std::string;
59  using std::make_tuple;
60 
61 
62 
63  namespace {
64 
65  string check_;
66 
67  Symbol COMMAND1 ("test.equalityCommand1");
68  Symbol COMMAND2 ("test.equalityCommand2");
69 
70  const string MARK_1 ("|_1_");
71  const string MARK_2 ("|_2_");
72 
73  void oper_1 (char par) { check_ += MARK_1 + par; }
74  void oper_2 (char par) { check_ += MARK_2 + par; }
75 
76  string capt_1 (char par) { return check_ + MARK_1 + "|"+par+"|"; }
77  string capt_2 (char par) { return check_ + MARK_2 + "|"+par+"|"; }
78 
79  void undo_1 (char par, string mem) { check_ = mem + MARK_1 + par + "|";}
80  void undo_2 (char par, string mem) { check_ = mem + MARK_2 + par + "|";}
81 
82 
83  typedef void Sig_oper(char);
84  typedef string Sig_capt(char);
85  typedef void Sig_undo(char,string);
86 
87  typedef function<Sig_oper> Fun_o;
88  typedef function<Sig_capt> Fun_c;
89  typedef function<Sig_undo> Fun_u;
90 
91  using ArgTuple = Tuple<Types<char>>;
92  using ArgHolder = OpClosure<Sig_oper>;
93  using MemHolder = MementoTie<Sig_oper, string>;
94  using Closure = SimpleClosure<Sig_oper>;
95  }
96 
97 
98 
99  /*************************************************************************************/
126  class CommandEquality_test : public Test
127  {
128 
129  virtual void
130  run (Arg)
131  {
132  CHECK (&oper_1 != &oper_2);
133  CHECK (&capt_1 != &capt_2);
134  CHECK (&undo_1 != &undo_2);
135 
136  verifyMutationEquality();
137  verifyMementoEquality();
138  verifyClosureEquality();
139  verifyCommandEquality();
140  }
141 
142 
143 
144  void
146  {
147  Fun_o oFun_1 (oper_1);
148  Fun_o oFun_2 (oper_2);
149  Fun_o oFun_empty;
150 
151  Fun_u uFun_1 (undo_1);
152  Fun_u uFun_empty;
153 
154  Mutation mut1 (oFun_1);
155  Mutation muti (oFun_1);
156  Mutation mut2 (oFun_2);
157  CHECK (mut1 == mut1);
158  CHECK (mut1 == muti);
159  CHECK (muti == mut1);
160  CHECK (mut1 != mut2);
161  CHECK (mut2 != mut1);
162  CHECK (muti != mut2);
163  CHECK (mut2 != muti);
164 
165  Mutation umu (oFun_empty); // empty operation function
166  CHECK (mut1 != umu);
167 
168  Mutation mut_u0 (uFun_empty); // empty undo function
169  CHECK (mut_u0 != umu);
170  CHECK (mut_u0 != muti);
171 
172  Mutation mut_u1 (uFun_1);
173  CHECK (mut_u0 != mut_u1); // function signatures differing
174  }
175 
176 
177  void
179  {
180  ArgHolder a1 (make_tuple ('a'));
181  ArgHolder a2 (make_tuple ('a'));
182  ArgHolder a3 (make_tuple ('z'));
183  CHECK (a1 == a1);
184  CHECK (a1 == a2);
185  CHECK (a2 == a1);
186  CHECK (a1 != a3);
187  CHECK (a3 != a1);
188  CHECK (a2 != a3);
189  CHECK (a3 != a2);
190 
191  typedef StorageHolder<Sig_oper,string> Storage;
192  Storage abuff1;
193  Storage abuff2;
194  CHECK (abuff1 == abuff2);
195 
196  TypedArguments<ArgTuple> newArgs (make_tuple ('z'));
197  abuff1.bindArguments(newArgs);
198  CHECK (abuff1 != abuff2);
199  abuff2.bindArguments(newArgs);
200  CHECK (abuff1 == abuff2);
201  UndoMutation umu1 (abuff1.tie (undo_1, capt_1));
202  CHECK (abuff1 != abuff2); // abuff2 isn't tied yet, i.e. has no undo/capture function
203  UndoMutation umu2 (abuff2.tie (undo_1, capt_1));
204  CHECK (abuff1 == abuff2); // same capture function, no memento state!
205 
206  Closure args {make_tuple ('u')};
207  umu1.captureState(args);
208  CHECK (abuff1 != abuff2);
209  umu2.captureState(args);
210  CHECK (abuff1 == abuff2); // same functions, same memento state
211 
212  check_ += "fake"; // manipulate the "state" to be captured
213  umu2.captureState(args); // capture again...
214  CHECK (abuff1 != abuff2); // captured memento differs!
215 
216  UndoMutation umu3 (abuff2.tie (undo_1, capt_2));
217  umu3.captureState(args);
218  CHECK (abuff1 != abuff2); // differing functions detected
219  }
220 
221 
222  void
224  {
225  Fun_u uFun_1 (undo_1);
226  Fun_u uFun_2 (undo_2);
227  Fun_c cFun_1 (capt_1);
228  Fun_c cFun_2 (capt_2);
229  Fun_c cFun_empty;
230 
231  Fun_c empty_c;
232 
233  MemHolder m11 (uFun_1, cFun_1);
234  MemHolder m12 (uFun_1, cFun_2);
235  MemHolder m21 (uFun_2, cFun_empty); // note: unbound capture function
236  MemHolder m22 (uFun_2, cFun_2);
237 
238  CHECK (m11 == m11);
239  CHECK (m12 == m12);
240  CHECK (m21 == m21);
241  CHECK (m22 == m22);
242  CHECK (!(m11 != m11));
243 
244  CHECK (m11 != m12);
245  CHECK (m11 != m21);
246  CHECK (m11 != m22);
247  CHECK (m12 != m11);
248  CHECK (m12 != m21);
249  CHECK (m12 != m22);
250  CHECK (m21 != m11);
251  CHECK (m21 != m12);
252  CHECK (m21 != m22);
253  CHECK (m22 != m11);
254  CHECK (m22 != m12);
255  CHECK (m22 != m21);
256 
257  MemHolder m22x (m22); // clone copy
258  CHECK (!m22x);
259  CHECK (m22 == m22x); // same functions, no state --> equal
260 
261  m22x.tieCaptureFunc() ('x'); // produce a memento state
262  CHECK (!isnil (m22x.getState()));
263 
264  CHECK (m22 != m22x);
265  m22.tieCaptureFunc() ('x'); // get same value into the memento within m22
266  CHECK (m22 == m22x);
267 
268  // document shortcomings on UndoMutation comparisons
269  UndoMutation umu11 (m11);
270  UndoMutation umu12 (m11); // note: due to cloning the embedded functor,
271  CHECK (umu11 != umu12); // our hacked-in comparison operator fails
272  }
273 
274 
275  void
277  {
278  CommandDef (COMMAND1)
279  .operation (oper_1)
280  .captureUndo (capt_1)
281  .undoOperation (undo_1)
282  ;
283  CommandDef (COMMAND2)
284  .operation (oper_2)
285  .captureUndo (capt_2)
286  .undoOperation (undo_2)
287  ;
288 
289  Command c1 = Command::get(COMMAND1);
290  Command c2 = Command::get(COMMAND2);
291  CHECK (c1 == c1);
292  CHECK (c1 != c2);
293  CHECK (c2 != c1);
294 
295  Command cx = c1;
296  CHECK (c1 == cx);
297  CHECK (cx == c1);
298  CHECK (!isSameObject (c1, c2));
299 
300  // verify equality matches behaviour
301  string protocol1 = execCommand(c1);
302  string protocolX = execCommand(cx);
303  string protocol2 = execCommand(c2);
304 
305  CHECK (protocol1 == protocolX);
306  CHECK (protocol1 != protocol2);
307  }
308 
309 
313  string
315  {
316  check_ = "(start)";
317  com.bind('o');
318  com();
319  cout << com << ":" << check_ << endl;
320  com.undo();
321  cout << com << ":" << check_ << endl;
322  return check_;
323  }
324  };
325 
326 
328  LAUNCHER (CommandEquality_test, "function controller");
329 
330 
331 }}} // namespace proc::control::test
Unspecific command functor for implementing Proc-Layer Command.
int64_t check_
< test command just adding a given value
auto operation(FUN operation_to_define)
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:49
Core of a Proc-Layer command: functor containing the operation to be executed.
Implementation helper to bind Proc-Layer commands with arbitrary argument tuples. ...
Proof-of-concept implementation of CmdClosure.
Helper class used solely for defining a Command-Object.
typename BuildTupleType< TYPES >::Type Tuple
Build a std::tuple from types given as type sequence.
Metaprogramming with tuples-of-types and the std::tuple record.
A special binding used by Proc-Layer commands for capturing UNDO state information.
bool isSameObject(A const &a, B const &b)
compare plain object identity, bypassing any custom comparison operators.
Definition: util.hpp:337
Token or Atom with distinct identity.
Definition: symbol.hpp:116
RET bind()
Accept dummy binding (0 Arg)
std::vector< string > & Arg
Definition: run.hpp:54
LAUNCHER(ArgumentTupleAccept_test, "unit controller")
Register this test class...
Marker types to indicate a literal string and a Symbol.
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...
A collection of frequently used helper functions to support unit testing.
static Command get(Symbol cmdID)
Access existing command for use.
Definition: command.cpp:127
bool isnil(lib::time::Duration const &dur)
Definition: timevalue.hpp:642
Mutation & captureState(CmdClosure &clo)
Handle object representing a single Command instance to be used by client code.
Definition: command.hpp:125
Proc-Layer implementation namespace root.
Definition: id-scheme.hpp:63
Actually defining a command and binding it to execution parameters.
ExecResult undo()
Definition: command.hpp:246
string execCommand(Command com)
Helper: invoke and undo a command,.
Specialised version of the command Mutation functor, used to implement the UNDO functionality.
A passive container record holding the actual command arguments & UNDO state.