Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
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"
23#include "lib/symbol.hpp"
24#include "lib/util.hpp"
25
27
28#include <functional>
29
30
31namespace steam {
32namespace control {
33namespace test {
34
35
36 using std::function;
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
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)
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");
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
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 using PImpl = shared_ptr<CommandImpl>;
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 using ArgTuple = std::tuple<int>;
214 TypedArguments<ArgTuple> arg{ArgTuple{98765}};
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
Token or Atom with distinct identity.
Definition symbol.hpp:120
Helper class used solely for defining a Command-Object.
auto operation(FUN operation_to_define)
Registry managing command implementation objects (Singleton).
void track(Symbol cmdID, Command const &commandHandle)
register a command (Frontend) under the given ID.
Symbol findDefinition(Command const &cmdInstance) const
search the command index for a definition
shared_ptr< CommandImpl > newCommandImpl(function< SIG_OPER > &operFunctor, function< SIG_CAPT > &captFunctor, function< SIG_UNDO > &undoFunctor)
set up a new command implementation frame
static lib::Depend< CommandRegistry > instance
storage for the singleton factory used to access CommandRegistry
Command queryIndex(Symbol cmdID)
query the command index by ID
shared_ptr< CommandImpl > createCloneImpl(CommandImpl const &refObject)
create an allocation for holding a clone of the given CommandImpl data.
Definition command.cpp:219
bool remove(Symbol cmdID)
remove the given command registration.
Handle object representing a single Command instance to be used by client code.
Definition command.hpp:120
static bool remove(Symbol cmdID)
Definition command.cpp:241
Command storeDef(Symbol newCmdID) const
create a clone definition
Definition command.cpp:183
void checkRegistration(CommandRegistry &registry)
Actually defining a command and binding it to execution parameters.
Managing command definitions and the storage of individual command objects.
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)
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
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
Marker types to indicate a literal string and a Symbol.
Some dummy command functions used for building unit test cases.
A collection of frequently used helper functions to support unit testing.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...