Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
scope-path-test.cpp
Go to the documentation of this file.
1/*
2 ScopePath(Test) - verify handling of logical access path down from Session root
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"
25#include "lib/format-cout.hpp"
26#include "lib/util.hpp"
27
28#include <string>
29
30
31namespace steam {
32namespace mobject {
33namespace session {
34namespace test {
35
36 using std::string;
37 using util::isnil;
39
40 using LERR_(LOGIC);
41 using LERR_(INVALID_SCOPE);
42 using LERR_(NOT_IN_SESSION);
43 using LERR_(EMPTY_SCOPE_PATH);
44
45
46
47 /***********************************************************************/
58 class ScopePath_test : public Test
59 {
60
61 virtual void
62 run (Arg)
63 {
64 // Prepare an (test)Index backing the PlacementRefs
65 PPIdx index = build_testScopes();
66 PMO& startPlacement = retrieve_startElm();
67 CHECK (startPlacement.isValid());
68
70 ScopePath testPath = buildPath (startPlacement);
71 checkRelations (testPath,startPlacement);
72 invalidPath (testPath,startPlacement);
73 rootPath (testPath);
74 check_Identity_and_Copy (startPlacement);
75 check_RefcountProtection (startPlacement);
76 navigate (testPath, index);
77 clear (testPath, index);
78 }
79
80
82 buildPath (PMO& startPla)
83 {
84 Scope startScope (startPla);
85 ScopePath path (startScope);
86 ScopePath path2 (startScope);
87 ScopePath path3 (path2);
88
89 CHECK (path);
90 CHECK (path.contains (startScope));
91 CHECK ( path.getLeaf() == path2.getLeaf());
92 CHECK (path2.getLeaf() == path3.getLeaf());
93
94 return path;
95 }
96
97
98 void
100 {
101 // verify detection of illegal scopes and paths...
102 TestPlacement<> notRelated2anything (*new DummyMO);
103 VERIFY_ERROR (NOT_IN_SESSION, Scope invalid (notRelated2anything) );
104
105 Scope const& scopeOfEvil = fabricate_invalidScope();
106 CHECK (!scopeOfEvil.isValid());
107
108 VERIFY_ERROR (INVALID_SCOPE, ScopePath outsideCurrentModel (scopeOfEvil) );
109
110 // but there is one exception to this rule...
111 ScopePath theInvalidToken (Scope::INVALID);
112 CHECK (!theInvalidToken.isValid());
113 CHECK (theInvalidToken.empty());
114 }
115
116
117
118 void
119 checkIteration (ScopePath path, PMO& refPlacement)
120 {
121 Scope refScope(refPlacement);
122 ScopePath::iterator ii = path.begin();
123 CHECK (ii);
124 while (++ii)
125 {
126 CHECK (*ii == refScope.getParent());
127 refScope = *ii;
128 }
129 }
130
131
132 void
133 checkRelations (ScopePath path1, PMO& refPlacement)
134 {
135 CHECK (path1.contains (refPlacement));
136
137 Scope refScope (refPlacement);
138 CHECK (path1.contains (refScope));
139 CHECK (path1.endsAt (refScope));
140
141 ScopePath path2 (refScope);
142 CHECK (path2.contains (refScope));
143 CHECK (path2.endsAt (refScope));
144
145 CHECK (path1 == path2);
146 CHECK (!isSameObject (path1,path2));
147
148 Scope parent = path2.moveUp();
149 CHECK (path2.endsAt (parent));
150 CHECK (path1.endsAt (refScope));
151 CHECK (parent == refScope.getParent());
152 CHECK (path1 != path2);
153 CHECK (path2 != path1);
154 CHECK (path1.contains (path2));
155 CHECK (!disjoint(path1,path2));
156 CHECK (path2 == commonPrefix(path1,path2));
157 CHECK (path2 == commonPrefix(path2,path1));
158 CHECK (path1 != commonPrefix(path1,path2));
159 CHECK (path1 != commonPrefix(path2,path1));
160 }
161
162
163 void
165 {
166 CHECK ( refPath);
167 refPath.goRoot();
168 CHECK (!refPath);
169 CHECK (!refPath.empty());
170 CHECK (!refPath.isValid());
171 CHECK (1 == refPath.length());
172
173 ScopePath defaultPath;
174 CHECK (!defaultPath);
175 CHECK (refPath == defaultPath);
176 }
177
178
179 void
180 invalidPath (ScopePath refPath, PMO& refPlacement)
181 {
182 CHECK (refPath);
183 CHECK (!ScopePath::INVALID);
184 CHECK (isnil (ScopePath::INVALID));
185 CHECK ("!" == string(ScopePath::INVALID));
186
187 ScopePath invalidP (ScopePath::INVALID);
188 CHECK (isnil (invalidP));
189 CHECK (invalidP == ScopePath::INVALID);
190 CHECK (!isSameObject (invalidP, ScopePath::INVALID));
191
192 CHECK (refPath.contains (refPlacement));
193 CHECK (!invalidP.contains (refPlacement));
194
195 Scope refScope (refPlacement);
196 CHECK (!invalidP.contains (refScope));
197 VERIFY_ERROR (EMPTY_SCOPE_PATH, invalidP.endsAt (refScope) ); // Logic: can't inspect the end of nothing
198
199 CHECK (refPath.contains (invalidP)); // If the moon is made of green cheese, I'll eat my hat!
200 CHECK (!invalidP.contains (refPath));
201 CHECK (invalidP == commonPrefix(refPath,invalidP));
202 CHECK (invalidP == commonPrefix(invalidP,refPath));
203
204 VERIFY_ERROR (EMPTY_SCOPE_PATH, invalidP.moveUp() );
205 Scope root = refPath.goRoot();
206 CHECK (1 == refPath.length());
207
208 Scope const& nil = refPath.moveUp();
209 CHECK (refPath.empty());
210 CHECK (!nil.isValid());
211 CHECK (refPath == invalidP);
212 CHECK (invalidP.contains (nil));
213 CHECK (invalidP.contains (refPath));
214 CHECK (!invalidP.contains (refScope));
215
216 VERIFY_ERROR (EMPTY_SCOPE_PATH, refPath.navigate(root) );
217
218 //ScopePath::INVALID.navigate(root); // doesn't compile: INVALID is immutable
219 }
220
221
222 void
224 {
225 Scope startScope (refPlacement);
226 ScopePath path1 (startScope);
227 ScopePath path2 (startScope);
228 ScopePath path3 (path2);
229
230 CHECK (path1.contains (startScope));
231 CHECK (path2.contains (startScope));
232 CHECK (path3.contains (startScope));
233
234 CHECK (path1 == path2);
235 CHECK (path2 == path3);
236 CHECK (path1 == path3);
237 CHECK (!isSameObject (path1,path2));
238 CHECK (!isSameObject (path2,path3));
239 CHECK (!isSameObject (path1,path3));
240
241 Scope parent = path3.moveUp(); // mutation
242 CHECK (parent == path2.getLeaf().getParent());
243
244 CHECK (path1 == path2); // the others are not affected
245 CHECK (path2 != path3);
246 CHECK (path1 != path3);
247
248 path2 = path3;
249 CHECK (path1 != path2);
250 CHECK (path2 == path3);
251 CHECK (path1 != path3);
252
253 path2 = ScopePath::INVALID;
254 CHECK (path1 != path2);
255 CHECK (path2 != path3);
256 CHECK (path1 != path3);
257 }
258
259
263 void
265 {
266 Scope startScope (refPlacement);
267 ScopePath path1 (startScope);
268 ScopePath path2 (path1);
269
270 path1 = path2;
271 CHECK (!isSameObject (path1,path2));
272 CHECK (0 == path1.ref_count());
273 CHECK (0 == path2.ref_count());
274
275 intrusive_ptr_add_ref (&path2);
276 CHECK (0 == path1.ref_count());
277 CHECK (0 < path2.ref_count());
278
279 ScopePath path3 (path2);
280 CHECK (0 == path3.ref_count()); // refcount not copied
281
282 path3.moveUp();
283
284 VERIFY_ERROR (LOGIC, path2 = path3 ); // overwriting of path with refcount is prohibited
285 CHECK (path1 != path3);
286 path1 = path2; // but path without refcount may be overwritten
287 path1 = path3;
288 CHECK (path1 == path3);
289
290 intrusive_ptr_release (&path2); // refcount drops to zero...
291 CHECK (0 == path1.ref_count());
292 CHECK (0 == path2.ref_count());
293 }
294
295
296
306 void
307 navigate (const ScopePath refPath, PPIdx index)
308 {
309 #define __SHOWPATH(N) cout << "Step("<<N<<"): "<< path << endl;
310
311 ScopePath path (refPath); __SHOWPATH(1)
312 CHECK (path == refPath);
313
314 Scope leaf = path.getLeaf();
315 Scope parent = path.moveUp(); __SHOWPATH(2)
316 CHECK (path != refPath);
317 CHECK (refPath.contains (path));
318 CHECK (refPath.endsAt (leaf));
319 CHECK (path.endsAt (parent));
320 CHECK (parent == leaf.getParent());
321 CHECK (parent == path.getLeaf());
322
323 Scope root = path.goRoot(); __SHOWPATH(3)
324 CHECK (path != refPath);
325 CHECK (path.endsAt (root));
326 CHECK (refPath.contains (path));
327 CHECK (!path.endsAt (parent));
328 CHECK (!path.endsAt (leaf));
329
330 path.navigate (parent); __SHOWPATH(4)
331 CHECK (path.endsAt (parent));
332 CHECK (!path.endsAt (root));
333 CHECK (!path.endsAt (leaf));
334
335 TestPlacement<> newNode (*new DummyMO);
336 PMO& parentRefPoint = parent.getTop();
337 Scope newLocation =
338 index->find( // place newNode as sibling of "leaf"
339 index->insert (newNode, parentRefPoint));
340 path.navigate (newLocation); __SHOWPATH(5)
341 Scope sibling = path.getLeaf();
342 CHECK (sibling == newLocation);
343 CHECK (parent == sibling.getParent());
344 CHECK (path.endsAt (sibling));
345 CHECK (path.contains (parent));
346 CHECK (path.contains (root));
347 CHECK (!refPath.contains (path));
348 CHECK (!path.contains (refPath));
349 CHECK (!disjoint (path,refPath));
350 CHECK (!disjoint (refPath,path));
351
352 ScopePath prefix = commonPrefix (path,refPath);
353 CHECK (prefix == commonPrefix (refPath,path));
354 CHECK (prefix.endsAt (parent));
355 CHECK (!prefix.contains (leaf));
356 CHECK (!prefix.contains (sibling));
357 path.navigate (prefix.getLeaf()); __SHOWPATH(6)
358 CHECK (path == prefix);
359
360 // try to navigate to an unconnected location...
361 ScopePath beforeInvalidNavigation = path;
362 Scope const& unrelatedScope (fabricate_invalidScope());
363 VERIFY_ERROR (INVALID_SCOPE, path.navigate (unrelatedScope) );
364 CHECK (path == beforeInvalidNavigation); // not messed up by the incident
365
366 // now explore a completely separate branch....
367 PMO& separatePlacement = *explore_testScope (
370 path.navigate (separatePlacement);
371 CHECK (path);
372 CHECK (disjoint (path,refPath));
373 CHECK (path.contains(separatePlacement));
374 Scope other = path.getLeaf();
375 CHECK (isSameObject (other.getTop(), separatePlacement));
376 ScopePath rootPrefix = commonPrefix (path,refPath);
377 CHECK (rootPrefix.endsAt (root));
378 }
379
380
381
382 void
383 clear (ScopePath& path, PPIdx index)
384 {
385 CHECK (path);
386 PMO& rootNode = index->getRoot();
387 CHECK (path.getLeaf() != rootNode);
388
389 path.clear();
390 CHECK (!path);
391 CHECK (!isnil (path));
392 CHECK (path.getLeaf() == rootNode);
393 }
394 };
395
396
397
399 LAUNCHER (ScopePath_test, "unit session");
400
401
402}}}} // namespace steam::mobject::session::test
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
Sequence of nested scopes within the high-level model.
bool endsAt(Scope const &) const
verify the scope in question is equivalent to our leaf scope.
static const ScopePath INVALID
constant invalid path token.
bool isValid() const
a valid path consists of more than just the root element.
bool empty() const
an empty path doesn't even contain a root element.
bool contains(Scope const &) const
A Placement scope within the high-level-model.
Definition scope.hpp:70
PlacementMO & getTop() const
Definition scope.cpp:198
Scope getParent() const
retrieve the parent scope which encloses this scope.
Definition scope.cpp:209
bool isValid() const
check if this scope can be located.
Definition scope.cpp:231
static const Scope INVALID
constant invalid scope token.
Definition scope.hpp:83
void checkRelations(ScopePath path1, PMO &refPlacement)
void clear(ScopePath &path, PPIdx index)
void navigate(const ScopePath refPath, PPIdx index)
void invalidPath(ScopePath refPath, PMO &refPlacement)
void checkIteration(ScopePath path, PMO &refPlacement)
Test MObject subclass, which, contrary to any real MObject, can be created directly without involving...
#define LERR_(_NAME_)
Definition error.hpp:45
Automatically use custom string conversion in C++ stream output.
PlacementMO & retrieve_firstTestSubMO21()
PPIdx build_testScopes()
helper for tests: create a pseudo-session (actually just a PlacementIndex), which contains some neste...
std::shared_ptr< PlacementIndex > PPIdx
PlacementMO & retrieve_startElm()
complement to the helper: retrieve one of the dummy placements which is a Placement<> and way down in...
ScopeQuery< MObject >::iterator explore_testScope(PlacementMO const &scopeTop)
shortcut to explore the contents of a scope within the current index.
Namespace of Session and user visible high-level objects.
Definition sequence.hpp:65
bool disjoint(ScopePath const &path1, ScopePath const &path2)
void intrusive_ptr_add_ref(ScopePath *pathFrame)
management function for boost::intrusive_ptr to be picked up by ADL
void intrusive_ptr_release(ScopePath *pathFrame)
ScopePath commonPrefix(ScopePath const &path1, ScopePath const &path2)
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 isnil(lib::time::Duration const &dur)
Core of the session implementation datastructure.
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
#define __SHOWPATH(N)
An Object representing a sequence of nested scopes within the Session.
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.
Unit test helper to generate deliberately wrong placement scopes.
Unit test helper to generate a system of nested test scopes.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...