Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
command-use1-test.cpp
Go to the documentation of this file.
1/*
2 CommandUse1(Test) - usage aspects I
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"
23#include "lib/format-cout.hpp"
24#include "lib/util.hpp"
25
27
28
29namespace steam {
30namespace control {
31namespace test {
32
34 using util::contains;
35 using LERR_(INVALID_COMMAND);
36 using LERR_(DUPLICATE_COMMAND);
37 using LERR_(UNBOUND_ARGUMENTS);
38 using LERR_(INVALID_ARGUMENTS);
39
40
41
42
43 /***********************************************************************/
50 class CommandUse1_test : public Test
51 {
52
54 int random() { return randVal = 10 + rani(40); }
55
56
57
58 virtual void
59 run (Arg)
60 {
61 seedRand();
64 uint cnt_inst = Command::instance_count();
65
73 undef();
74
76 CHECK (cnt_defs == Command::definition_count());
77 CHECK (cnt_inst == Command::instance_count());
78 }
79
80
81 void
83 {
84
85 CommandDef ("test.command1.1")
87 .captureUndo (command1::capture)
88 .undoOperation (command1::undoIt)
89 .bind (random())
90 .execSync()
91 ;
92
94
95 Command::get("test.command1.1").undo();
96 CHECK ( 0 == command1::check_);
97 }
98
99
100 void
102 {
103 {
104 CommandDef ("test.command1.2")
106 .captureUndo (command1::capture)
107 .undoOperation (command1::undoIt)
108 ;
109 }
110 CHECK (CommandDef("test.command1.2"));
111
112 Command com ("test.command1.2");
113 CHECK (com);
114 CHECK (com == Command::get("test.command1.2"));
115 CHECK (contains (string(com), "test.command1.2"));
116 CHECK (contains (string(com), "{def}"));
117 CHECK (!com.canExec());
118 VERIFY_ERROR (UNBOUND_ARGUMENTS, com() );
119 CHECK ( 0 == command1::check_);
120
121 VERIFY_ERROR (INVALID_ARGUMENTS, com.bind ("foo") );
122 com.bind (random()); // note: run-time type check only
123 CHECK ( com.canExec());
124 CHECK (!com.canUndo());
125 com();
127 com.undo();
128 CHECK ( 0 == command1::check_);
129
130 // the following shortcut does the same:
131 invoke ("test.command1.2") (1234);
132 CHECK ( 1234 == command1::check_);
133
134 com.undo();
135 CHECK ( 0 == command1::check_);
136 }
137
138
139 void
141 {
142 Command::remove("test.command1.2");
143 VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.2") );
144
145 CommandDef def ("test.command1.2");
146 CHECK (!def);
147
148 def.operation (command1::operate)
149 .captureUndo (command1::capture);
150 CHECK (!def); // undo functor still missing
151 VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.2") );
152
153 def.operation (command1::operate)
154 .captureUndo (command1::capture)
155 .undoOperation (command1::undoIt);
156 CHECK (def);
157 CHECK (CommandDef("test.command1.2"));
158 CHECK (Command::get("test.command1.2"));
159
160 CHECK ( Command::defined("test.command1.2"));
161 CHECK (!Command::canExec("test.command1.2"));
162 CHECK (!Command::canUndo("test.command1.2"));
163
164 Command com = Command::get("test.command1.2");
165 CHECK (com);
166 CHECK (!com.canExec());
167 CHECK (!com.canUndo());
168
169 com.bind (11111);
170 CHECK ( Command::defined("test.command1.2"));
171 CHECK ( Command::canExec("test.command1.2"));
172 CHECK (!Command::canUndo("test.command1.2"));
173
174 com();
175 CHECK ( Command::defined("test.command1.2"));
176 CHECK ( Command::canExec("test.command1.2"));
177 CHECK ( Command::canUndo("test.command1.2"));
178
179 com.undo();
180 CHECK ( Command::defined("test.command1.2"));
181 CHECK ( Command::canExec("test.command1.2"));
182 CHECK ( Command::canUndo("test.command1.2"));
183
184 com.unbind(); // revert to pristine state
185 CHECK ( Command::defined("test.command1.2"));
186 CHECK (!Command::canExec("test.command1.2"));
187 CHECK (!Command::canUndo("test.command1.2"));
188 }
189
190
191 void
193 {
194 CommandDef ("test.command1.3")
196 .captureUndo (command1::capture)
197 .undoOperation (command1::undoIt)
198 .bind (random())
199 ;
200
201 CHECK (Command::get("test.command1.3").canExec());
202 }
203
204
205 void
207 {
208 Command c1 = Command::get("test.command1.3");
209 CHECK (c1);
210 CHECK (c1.canExec());
211 CHECK (!c1.canUndo());
212
214 CHECK (c2);
215 CHECK (c2.canExec());
216 CHECK (!c2.canUndo());
217 CHECK (c2.isAnonymous());
218
219 CHECK (c1 != c2);
220 CHECK (!isSameObject(c1, c2));
221
222 CHECK (0 == command1::check_);
223
224 c1();
225
227 CHECK ( c1.canUndo());
228 CHECK (!c2.canUndo());
229
230 c2();
232 CHECK (c2.canUndo());
233 CHECK (c1 != c2);
234
235 c1.undo();
236 CHECK (0 == command1::check_);
237 c2.undo();
239
240 c2.bind(23);
241 c2();
243
244 // you should not use a command more than once (but it works...)
245 c1();
247 c1.undo();
249 // note we've overwritten the previous undo state
250 // and get the sate captured on the second invocation
251
252 c2.undo();
254 c1.undo();
256
257 // use the current sate of c2 as Prototype for new command definition
258 c2.storeDef ("test.command1.4");
259 Command c4 = Command::get("test.command1.4");
260 CHECK (c4);
261 CHECK (c4.canExec());
262 CHECK (c4.canUndo());
263 CHECK (not c4.isAnonymous());
264 CHECK ( c2.isAnonymous());
265 CHECK (c4 != c2); // note: it was stored as independent clone copy
266 CHECK (c4 != c1);
267 c4();
268 CHECK (c4 != c2); // now lives independently from the original
269 CHECK (randVal + 2*23 == command1::check_);
270
271 c4.bind(int(-command1::check_)); // new command argument binding
272 c4();
273 CHECK (0 == command1::check_);
274 c2();
275 CHECK (23 == command1::check_);
276 c2.undo();
277 CHECK (0 == command1::check_);
278
279 // remove argument bindings per instance and return to pristine state
280 c4.unbind();
281 CHECK (c2.canExec());
282 CHECK (c2.canUndo());
283 CHECK (not c4.canExec());
284 CHECK (not c4.canUndo());
285 }
286
287
288 void
290 {
291 #define BUILD_NEW_COMMAND_DEF(_ID_) \
292 CommandDef (_ID_) \
293 .operation (command1::operate) \
294 .captureUndo (command1::capture) \
295 .undoOperation (command1::undoIt)
296
297 CHECK (CommandDef ("test.command1.1"));
298 VERIFY_ERROR (DUPLICATE_COMMAND, BUILD_NEW_COMMAND_DEF ("test.command1.1") );
299 CHECK (CommandDef ("test.command1.2"));
300 VERIFY_ERROR (DUPLICATE_COMMAND, BUILD_NEW_COMMAND_DEF ("test.command1.2") );
301 CHECK (CommandDef ("test.command1.3"));
302 VERIFY_ERROR (DUPLICATE_COMMAND, BUILD_NEW_COMMAND_DEF ("test.command1.3") );
303 CHECK (CommandDef ("test.command1.4"));
304 VERIFY_ERROR (DUPLICATE_COMMAND, BUILD_NEW_COMMAND_DEF ("test.command1.4") );
305 }
306
307
308 void
310 {
311 cout << Command::get("test.command1.1") << endl;
312 cout << Command::get("test.command1.2") << endl;
313 cout << Command::get("test.command1.3") << endl;
314 cout << Command::get("test.command1.4") << endl;
315 cout << Command() << endl;
316
317 Command com
318 = CommandDef ("test.command1.5")
320 .captureUndo (command1::capture)
321 .undoOperation (command1::undoIt);
322
323 cout << com << endl;
324 com.bind(123);
325 cout << com << endl;
326 com();
327 cout << com << endl;
328 com.undo();
329 cout << com << endl;
330 }
331
332
333 void
335 {
336 CHECK (CommandDef ("test.command1.1"));
337 CHECK (CommandDef ("test.command1.2"));
338 CHECK (CommandDef ("test.command1.3"));
339 CHECK (CommandDef ("test.command1.4"));
340
341 CHECK (Command::get("test.command1.1"));
342 CHECK (Command::get("test.command1.2"));
343 CHECK (Command::get("test.command1.3"));
344 CHECK (Command::get("test.command1.4"));
345
346 VERIFY_ERROR (INVALID_COMMAND, Command::get("miracle"));
347 VERIFY_ERROR (INVALID_COMMAND, invoke ("miracle") (1,2,3));
348
349 CommandDef unbelievable ("miracle");
351
353 // but because the miracle isn't yet defined, any use throws
354 VERIFY_ERROR (INVALID_COMMAND, miracle.bind("abracadabra"));
355 VERIFY_ERROR (INVALID_COMMAND, miracle.execSync());
356 VERIFY_ERROR (INVALID_COMMAND, miracle.undo());
357 VERIFY_ERROR (INVALID_COMMAND, miracle());
358 CHECK (!miracle.canExec());
359 CHECK (!miracle.canUndo());
360 CHECK (!miracle);
361
362 Command c5 (Command::get("test.command1.5"));
363
364 CHECK (Command::remove("test.command1.1"));
365 CHECK (Command::remove("test.command1.2"));
366 CHECK (Command::remove("test.command1.3"));
367 CHECK (Command::remove("test.command1.4"));
368 CHECK (Command::remove("test.command1.5"));
369
370 CHECK (!Command::remove("miracle")); // there is no such thing...
371
372 VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.1"));
373 VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.2"));
374 VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.3"));
375 VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.4"));
376 VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.5"));
377 VERIFY_ERROR (INVALID_COMMAND, Command::get("miracle"));
378
379
380 // note, removed the registered definitions,
381 // but existing instances remain valid...
382 // thus we're free to create new instances...
383 CHECK (c5.isValid());
384 CHECK (c5.canExec());
385 }
386 };
387
388
389
391 LAUNCHER (CommandUse1_test, "function controller");
392
393
394}}} // namespace steam::control::test
Helper class used solely for defining a Command-Object.
auto operation(FUN operation_to_define)
Handle object representing a single Command instance to be used by client code.
Definition command.hpp:120
static bool defined(Symbol cmdID)
Definition command.hpp:264
static size_t definition_count()
Definition command.cpp:289
Command & unbind()
discard any argument data previously bound.
Definition command.cpp:279
Command newInstance() const
create independent (anonymous) clone copy of this command
Definition command.cpp:200
static Command get(Symbol cmdID)
Access existing command for use.
Definition command.cpp:120
static bool remove(Symbol cmdID)
Definition command.cpp:241
static size_t instance_count()
Definition command.cpp:298
Actually defining a command and binding it to execution parameters.
Some additional helpers and convenience shortcuts to ease command invocation.
#define BUILD_NEW_COMMAND_DEF(_ID_)
#define LERR_(_NAME_)
Definition error.hpp:45
Automatically use custom string conversion in C++ stream output.
unsigned int uint
Definition integral.hpp:29
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
void undoIt(int, int64_t oldVal)
int64_t check_
< test command just adding a given value
com::RuntimeCheckedCommandInvoker invoke(Symbol cmdID)
Steam-Layer implementation namespace root.
Test runner and basic definitions for tests.
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee's memory identities.
Definition util.hpp:421
bool contains(MAP &map, typename MAP::key_type const &key)
shortcut for containment test on a map
Definition util.hpp:230
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
Some dummy command functions used for building unit test cases.
A collection of frequently used helper functions to support unit testing.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...