Lumiera  0.pre.03
»edityourfreedom«
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 proc {
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)
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);
128  cmd2.bind(54321);
129  CHECK (cmd2 != cmd1);
130 
131  // this created exactly one additional instance allocation:
132  CHECK (1+cnt_inst == registry.instance_count());
133  CHECK (1+cnt_defs == registry.index_size());
134  // ...and another index entry
135 
136 
137  Command cmdX = registry.queryIndex(TEST_CMD2);
138  CHECK (cmdX == cmd2);
139  CHECK (cmdX != cmd1);
140 
141  CHECK (registry.remove(TEST_CMD2));
142  CHECK (!registry.queryIndex(TEST_CMD2));
143  CHECK (cnt_defs == registry.index_size()); // removed from index
144  CHECK (1+cnt_inst == registry.instance_count()); //...but still alive
145 
146  // create a new registration..
147  registry.track(TEST_CMD2, cmd2);
148  CHECK (registry.queryIndex(TEST_CMD2));
149  CHECK (1+cnt_defs == registry.index_size()); // again holding two distinct entries
150  CHECK (cmdX == cmd2);
151  CHECK (cmdX != cmd1);
152 
153  CHECK (TEST_CMD == registry.findDefinition(cmd1));
154  CHECK (TEST_CMD2 == registry.findDefinition(cmd2));
155  CHECK (TEST_CMD2 == registry.findDefinition(cmdX));
156 
157  CHECK ( registry.remove(TEST_CMD2));
158  CHECK (!registry.remove("miraculous"));
159 
160  CHECK (!registry.queryIndex(TEST_CMD2));
161  CHECK ( registry.queryIndex(TEST_CMD));
162  CHECK (cnt_defs == registry.index_size()); // the index entry is gone,
163 
164  CHECK (1+cnt_inst == registry.instance_count()); // but the allocation still lives
165  cmdX.close();
166  CHECK (1+cnt_inst == registry.instance_count());
167  cmd2.close();
168  CHECK (0+cnt_inst == registry.instance_count()); // ...as long as it's still referred
169  }
170 
171 
172 
178  void
180  {
181  // simulate what normally happens within a CommandDef
182  typedef void Sig_oper(int);
183  typedef long Sig_capt(int);
184  typedef void Sig_undo(int,long);
185 
186  function<Sig_oper> o_Fun (command1::operate);
187  function<Sig_capt> c_Fun (command1::capture);
188  function<Sig_undo> u_Fun (command1::undoIt);
189 
190  CHECK (o_Fun && c_Fun && u_Fun);
191  CHECK (cnt_inst == registry.instance_count());
192 
193  // when the CommandDef is complete, it issues the
194  // allocation call to the registry behind the scenes....
195 
196  typedef shared_ptr<CommandImpl> PImpl;
197 
198  PImpl pImpl = registry.newCommandImpl(o_Fun,c_Fun,u_Fun);
199  CHECK (1+cnt_inst == registry.instance_count());
200 
201  CHECK (pImpl);
202  CHECK (pImpl->isValid());
203  CHECK (!pImpl->canExec());
204  CHECK (1 == pImpl.use_count()); // no magic involved, we hold the only instance
205 
206  PImpl clone = registry.createCloneImpl(*pImpl);
207  CHECK (clone->isValid());
208  CHECK (!clone->canExec());
209  CHECK (1 == clone.use_count());
210  CHECK (1 == pImpl.use_count());
211  CHECK (2+cnt_inst == registry.instance_count());
212 
213  CHECK (!isSameObject (*pImpl, *clone));
214  CHECK (*pImpl == *clone);
215 
216  CHECK (!pImpl->canExec());
217  typedef Types<int> ArgType;
219  pImpl->setArguments(arg);
220  CHECK (pImpl->canExec());
221 
222  CHECK (!clone->canExec()); // this proves the clone has indeed a separate identity
223  CHECK (*pImpl != *clone);
224 
225  // discard the first clone and overwrite with a new one
226  clone = registry.createCloneImpl(*pImpl);
227  CHECK (2+cnt_inst == registry.instance_count());
228  CHECK (*pImpl == *clone);
229  CHECK (clone->canExec());
230 
231  clone.reset();
232  pImpl.reset();
233  // corresponding allocation slots cleared automatically
234  CHECK (cnt_inst == registry.instance_count());
235  }
236 
237  };
238 
239 
241  LAUNCHER (CommandRegistry_test, "function controller");
242 
243 
244 }}} // namespace proc::control::test
auto operation(FUN operation_to_define)
void undoIt(int, int64_t oldVal)
Definition: run.hpp:49
Symbol findDefinition(Command const &cmdInstance) const
search the command index for a definition
Managing command definitions and the storage of individual command objects.
void checkRegistration(CommandRegistry &registry)
shared_ptr< CommandImpl > createCloneImpl(CommandImpl const &refObject)
create an allocation for holding a clone of the given CommandImpl data.
Definition: command.cpp:226
Helper class used solely for defining a Command-Object.
typename BuildTupleType< TYPES >::Type Tuple
Build a std::tuple from types given as type sequence.
void track(Symbol cmdID, Command const &commandHandle)
register a command (Frontend) under the given ID.
bool remove(Symbol cmdID)
remove the given command registration.
void checkAllocation(CommandRegistry &registry)
Registry managing command implementation objects (Singleton).
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
shared_ptr< CommandImpl > newCommandImpl(function< SIG_OPER > &operFunctor, function< SIG_CAPT > &captFunctor, function< SIG_UNDO > &undoFunctor)
set up a new command implementation frame
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.
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:143
static lib::Depend< CommandRegistry > instance
storage for the singleton factory used to access CommandRegistry
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:125
static bool remove(Symbol cmdID)
Definition: command.cpp:248
Proc-Layer implementation namespace root.
Definition: id-scheme.hpp:63
Actually defining a command and binding it to execution parameters.
Command storeDef(Symbol newCmdID) const
create a clone definition
Definition: command.cpp:190
Command queryIndex(Symbol cmdID)
query the command index by ID