Lumiera  0.pre.03
»edit your freedom«
command-registry-test.cpp
Go to the documentation of this file.
1 /*
2  CommandRegistry(Test) - verify command registration and allocation
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"
23 #include "lib/symbol.hpp"
24 #include "lib/util.hpp"
25 
27 
28 #include <functional>
29 
30 
31 namespace steam {
32 namespace control {
33 namespace test {
34 
35 
36  using std::function;
37  using util::isSameObject;
38  using lib::Symbol;
39 
40 
41  namespace { // test data and helpers...
42 
43  Symbol TEST_CMD = "test.command1.1";
44  Symbol TEST_CMD2 = "test.command1.2";
45  }
46 
47 
48 
49  /***************************************************************************/
61  class CommandRegistry_test : public Test
62  {
63 
64  uint cnt_defs;
65  uint cnt_inst;
66 
67 
68  virtual void
69  run (Arg)
70  {
72  CHECK (&registry);
73 
74  cnt_defs = registry.index_size();
75  cnt_inst = registry.instance_count();
76 
77  // prepare a command definition (prototype)
78  CommandDef (TEST_CMD)
79  .operation (command1::operate)
80  .captureUndo (command1::capture)
81  .undoOperation (command1::undoIt)
82  .bind(123);
83 
84  // this command definition is
85  // represented internally by a prototype instance
86  CHECK (++cnt_inst == registry.instance_count());
87  CHECK (++cnt_defs == registry.index_size());
88 
89  checkRegistration (registry);
90  checkAllocation(registry);
91 
92  CHECK (cnt_inst == registry.instance_count());
93  CHECK (cnt_defs == registry.index_size());
94 
95  Command::remove (TEST_CMD);
96  CHECK (--cnt_inst == registry.instance_count());
97  }
98 
99 
100 
104  void
106  {
107  CHECK (cnt_inst == registry.instance_count());
108 
109  Command cmd1 = registry.queryIndex (TEST_CMD);
110  CHECK (cmd1);
111  CHECK (TEST_CMD == registry.findDefinition(cmd1));
112 
113  Command nonexistant = registry.queryIndex("miraculous");
114  CHECK (!nonexistant);
115 
116  // now create a clone, registered under a different ID
117  Command cmd2 = cmd1.storeDef(TEST_CMD2);
118  CHECK (cmd2 != cmd1); // note: while they are equivalent, they are not identical
119  Command cm2x = cmd2.bind(54321);
120  CHECK (cm2x != cmd1);
121  CHECK (cm2x == cmd2);
122 
123  // this created exactly one additional instance allocation:
124  CHECK (1+cnt_inst == registry.instance_count());
125  CHECK (1+cnt_defs == registry.index_size());
126  // ...and another index entry
127 
128 
129  Command cmdX = registry.queryIndex(TEST_CMD2);
130  CHECK (cmdX == cmd2);
131  CHECK (cmdX != cmd1);
132 
133  CHECK (registry.remove(TEST_CMD2));
134  CHECK (!registry.queryIndex(TEST_CMD2));
135  CHECK (cnt_defs == registry.index_size()); // removed from index
136  CHECK (1+cnt_inst == registry.instance_count()); //...but still alive
137 
138  CHECK (cmdX.isAnonymous());
139  CHECK (cmd2.isAnonymous()); //......they got deached
140  CHECK (!cmd1.isAnonymous());
141 
142  // create a new registration..
143  registry.track(TEST_CMD2, cmd2);
144  CHECK (registry.queryIndex(TEST_CMD2));
145  CHECK (1+cnt_defs == registry.index_size()); // again holding two distinct entries
146  CHECK (cmdX == cmd2);
147  CHECK (cmdX != cmd1);
148 
149  CHECK (TEST_CMD == registry.findDefinition(cmd1));
150  CHECK (TEST_CMD2 == registry.findDefinition(cmd2));
151  CHECK (TEST_CMD2 == registry.findDefinition(cmdX));
152 
153  CHECK ( registry.remove(TEST_CMD2));
154  CHECK (!registry.remove("miraculous"));
155 
156  CHECK (!registry.queryIndex(TEST_CMD2));
157  CHECK ( registry.queryIndex(TEST_CMD));
158  CHECK (cnt_defs == registry.index_size()); // the index entry is gone,
159 
160  CHECK (1+cnt_inst == registry.instance_count()); // but the allocation still lives
161  cmdX.close();
162  CHECK (1+cnt_inst == registry.instance_count());
163  cmd2.close();
164  cm2x.close();
165  CHECK (0+cnt_inst == registry.instance_count()); // ...as long as it's still referred
166  }
167 
168 
169 
175  void
177  {
178  // simulate what normally happens within a CommandDef
179  typedef void Sig_oper(int);
180  typedef long Sig_capt(int);
181  typedef void Sig_undo(int,long);
182 
183  function<Sig_oper> o_Fun (command1::operate);
184  function<Sig_capt> c_Fun (command1::capture);
185  function<Sig_undo> u_Fun (command1::undoIt);
186 
187  CHECK (o_Fun && c_Fun && u_Fun);
188  CHECK (cnt_inst == registry.instance_count());
189 
190  // when the CommandDef is complete, it issues the
191  // allocation call to the registry behind the scenes....
192 
193  typedef shared_ptr<CommandImpl> PImpl;
194 
195  PImpl pImpl = registry.newCommandImpl(o_Fun,c_Fun,u_Fun);
196  CHECK (1+cnt_inst == registry.instance_count());
197 
198  CHECK (pImpl);
199  CHECK (pImpl->isValid());
200  CHECK (!pImpl->canExec());
201  CHECK (1 == pImpl.use_count()); // no magic involved, we hold the only instance
202 
203  PImpl clone = registry.createCloneImpl(*pImpl);
204  CHECK (clone->isValid());
205  CHECK (!clone->canExec());
206  CHECK (1 == clone.use_count());
207  CHECK (1 == pImpl.use_count());
208  CHECK (2+cnt_inst == registry.instance_count());
209 
210  CHECK (!isSameObject (*pImpl, *clone));
211 
212  CHECK (!pImpl->canExec());
213  typedef Types<int> ArgType;
215  pImpl->setArguments(arg);
216  CHECK (pImpl->canExec());
217 
218  CHECK (!clone->canExec()); // this proves the clone has indeed a separate identity
219 
220  // discard the first clone and overwrite with a new one
221  clone = registry.createCloneImpl(*pImpl);
222  CHECK (2+cnt_inst == registry.instance_count());
223  CHECK (clone->canExec());
224 
225  clone.reset();
226  pImpl.reset();
227  // corresponding allocation slots cleared automatically
228  CHECK (cnt_inst == registry.instance_count());
229  }
230 
231  };
232 
233 
235  LAUNCHER (CommandRegistry_test, "function controller");
236 
237 
238 }}} // namespace steam::control::test
Helper class used solely for defining a Command-Object.
typename BuildTupleType< TYPES >::Type Tuple
Build a std::tuple from types given as type sequence.
bool remove(Symbol cmdID)
remove the given command registration.
Definition: run.hpp:40
shared_ptr< CommandImpl > newCommandImpl(function< SIG_OPER > &operFunctor, function< SIG_CAPT > &captFunctor, function< SIG_UNDO > &undoFunctor)
set up a new command implementation frame
void checkAllocation(CommandRegistry &registry)
Managing command definitions and the storage of individual command objects.
Command storeDef(Symbol newCmdID) const
create a clone definition
Definition: command.cpp:183
Registry managing command implementation objects (Singleton).
Steam-Layer implementation namespace root.
Symbol findDefinition(Command const &cmdInstance) const
search the command index for a definition
Token or Atom with distinct identity.
Definition: symbol.hpp:117
Command queryIndex(Symbol cmdID)
query the command index by ID
Marker types to indicate a literal string and a Symbol.
Simplistic test class runner.
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.
void close()
deactivate this handle, so it isn&#39;t tied any longer to the associated implementation or service objec...
Definition: handle.hpp:140
void checkRegistration(CommandRegistry &registry)
Some dummy command functions used for building unit test cases.
Handle object representing a single Command instance to be used by client code.
Definition: command.hpp:115
shared_ptr< CommandImpl > createCloneImpl(CommandImpl const &refObject)
create an allocation for holding a clone of the given CommandImpl data.
Definition: command.cpp:219
RET bind()
Accept dummy binding (0 Arg)
void track(Symbol cmdID, Command const &commandHandle)
register a command (Frontend) under the given ID.
bool isAnonymous() const
Definition: command.cpp:379
Actually defining a command and binding it to execution parameters.
static lib::Depend< CommandRegistry > instance
storage for the singleton factory used to access CommandRegistry
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee&#39;s memory identities. ...
Definition: util.hpp:421