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) 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"
32 #include "lib/symbol.hpp"
33 #include "lib/util.hpp"
34 
36 
37 #include <functional>
38 
39 
40 namespace steam {
41 namespace control {
42 namespace test {
43 
44 
45  using std::function;
46  using util::isSameObject;
47  using lib::Symbol;
48 
49 
50  namespace { // test data and helpers...
51 
52  Symbol TEST_CMD = "test.command1.1";
53  Symbol TEST_CMD2 = "test.command1.2";
54  }
55 
56 
57 
58  /***************************************************************************/
70  class CommandRegistry_test : public Test
71  {
72 
73  uint cnt_defs;
74  uint cnt_inst;
75 
76 
77  virtual void
78  run (Arg)
79  {
81  CHECK (&registry);
82 
83  cnt_defs = registry.index_size();
84  cnt_inst = registry.instance_count();
85 
86  // prepare a command definition (prototype)
87  CommandDef (TEST_CMD)
88  .operation (command1::operate)
89  .captureUndo (command1::capture)
90  .undoOperation (command1::undoIt)
91  .bind(123);
92 
93  // this command definition is
94  // represented internally by a prototype instance
95  CHECK (++cnt_inst == registry.instance_count());
96  CHECK (++cnt_defs == registry.index_size());
97 
98  checkRegistration (registry);
99  checkAllocation(registry);
100 
101  CHECK (cnt_inst == registry.instance_count());
102  CHECK (cnt_defs == registry.index_size());
103 
104  Command::remove (TEST_CMD);
105  CHECK (--cnt_inst == registry.instance_count());
106  }
107 
108 
109 
113  void
115  {
116  CHECK (cnt_inst == registry.instance_count());
117 
118  Command cmd1 = registry.queryIndex (TEST_CMD);
119  CHECK (cmd1);
120  CHECK (TEST_CMD == registry.findDefinition(cmd1));
121 
122  Command nonexistant = registry.queryIndex("miraculous");
123  CHECK (!nonexistant);
124 
125  // now create a clone, registered under a different ID
126  Command cmd2 = cmd1.storeDef(TEST_CMD2);
127  CHECK (cmd2 != cmd1); // note: while they are equivalent, they are not identical
128  Command cm2x = cmd2.bind(54321);
129  CHECK (cm2x != cmd1);
130  CHECK (cm2x == cmd2);
131 
132  // this created exactly one additional instance allocation:
133  CHECK (1+cnt_inst == registry.instance_count());
134  CHECK (1+cnt_defs == registry.index_size());
135  // ...and another index entry
136 
137 
138  Command cmdX = registry.queryIndex(TEST_CMD2);
139  CHECK (cmdX == cmd2);
140  CHECK (cmdX != cmd1);
141 
142  CHECK (registry.remove(TEST_CMD2));
143  CHECK (!registry.queryIndex(TEST_CMD2));
144  CHECK (cnt_defs == registry.index_size()); // removed from index
145  CHECK (1+cnt_inst == registry.instance_count()); //...but still alive
146 
147  CHECK (cmdX.isAnonymous());
148  CHECK (cmd2.isAnonymous()); //......they got deached
149  CHECK (!cmd1.isAnonymous());
150 
151  // create a new registration..
152  registry.track(TEST_CMD2, cmd2);
153  CHECK (registry.queryIndex(TEST_CMD2));
154  CHECK (1+cnt_defs == registry.index_size()); // again holding two distinct entries
155  CHECK (cmdX == cmd2);
156  CHECK (cmdX != cmd1);
157 
158  CHECK (TEST_CMD == registry.findDefinition(cmd1));
159  CHECK (TEST_CMD2 == registry.findDefinition(cmd2));
160  CHECK (TEST_CMD2 == registry.findDefinition(cmdX));
161 
162  CHECK ( registry.remove(TEST_CMD2));
163  CHECK (!registry.remove("miraculous"));
164 
165  CHECK (!registry.queryIndex(TEST_CMD2));
166  CHECK ( registry.queryIndex(TEST_CMD));
167  CHECK (cnt_defs == registry.index_size()); // the index entry is gone,
168 
169  CHECK (1+cnt_inst == registry.instance_count()); // but the allocation still lives
170  cmdX.close();
171  CHECK (1+cnt_inst == registry.instance_count());
172  cmd2.close();
173  cm2x.close();
174  CHECK (0+cnt_inst == registry.instance_count()); // ...as long as it's still referred
175  }
176 
177 
178 
184  void
186  {
187  // simulate what normally happens within a CommandDef
188  typedef void Sig_oper(int);
189  typedef long Sig_capt(int);
190  typedef void Sig_undo(int,long);
191 
192  function<Sig_oper> o_Fun (command1::operate);
193  function<Sig_capt> c_Fun (command1::capture);
194  function<Sig_undo> u_Fun (command1::undoIt);
195 
196  CHECK (o_Fun && c_Fun && u_Fun);
197  CHECK (cnt_inst == registry.instance_count());
198 
199  // when the CommandDef is complete, it issues the
200  // allocation call to the registry behind the scenes....
201 
202  typedef shared_ptr<CommandImpl> PImpl;
203 
204  PImpl pImpl = registry.newCommandImpl(o_Fun,c_Fun,u_Fun);
205  CHECK (1+cnt_inst == registry.instance_count());
206 
207  CHECK (pImpl);
208  CHECK (pImpl->isValid());
209  CHECK (!pImpl->canExec());
210  CHECK (1 == pImpl.use_count()); // no magic involved, we hold the only instance
211 
212  PImpl clone = registry.createCloneImpl(*pImpl);
213  CHECK (clone->isValid());
214  CHECK (!clone->canExec());
215  CHECK (1 == clone.use_count());
216  CHECK (1 == pImpl.use_count());
217  CHECK (2+cnt_inst == registry.instance_count());
218 
219  CHECK (!isSameObject (*pImpl, *clone));
220 
221  CHECK (!pImpl->canExec());
222  typedef Types<int> ArgType;
224  pImpl->setArguments(arg);
225  CHECK (pImpl->canExec());
226 
227  CHECK (!clone->canExec()); // this proves the clone has indeed a separate identity
228 
229  // discard the first clone and overwrite with a new one
230  clone = registry.createCloneImpl(*pImpl);
231  CHECK (2+cnt_inst == registry.instance_count());
232  CHECK (clone->canExec());
233 
234  clone.reset();
235  pImpl.reset();
236  // corresponding allocation slots cleared automatically
237  CHECK (cnt_inst == registry.instance_count());
238  }
239 
240  };
241 
242 
244  LAUNCHER (CommandRegistry_test, "function controller");
245 
246 
247 }}} // 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:49
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:192
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:126
Command queryIndex(Symbol cmdID)
query the command index by ID
Marker types to indicate a literal string and a Symbol.
Simple 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:149
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:124
shared_ptr< CommandImpl > createCloneImpl(CommandImpl const &refObject)
create an allocation for holding a clone of the given CommandImpl data.
Definition: command.cpp:228
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:388
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, bypassing any custom comparison operators.
Definition: util.hpp:372