Lumiera  0.pre.03
»edit your freedom«
placement-index-test.cpp
Go to the documentation of this file.
1 /*
2  PlacementIndex(Test) - facility keeping track of Placements within the Session
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"
24 #include "steam/asset/media.hpp"
25 #include "lib/format-string.hpp"
26 #include "lib/format-cout.hpp"
27 #include "lib/util.hpp"
28 
31 
32 
33 using util::_Fmt;
34 using util::isSameObject;
35 using std::string;
36 
37 
38 namespace steam {
39 namespace mobject {
40 namespace session {
41 namespace test {
42 
43  using session::test::TestClip;
44  using LERR_(BOTTOM_PLACEMENTREF);
45  using LERR_(NONEMPTY_SCOPE);
46  using LERR_(INVALID_SCOPE);
47 
48  typedef PlacementIndex& Idx;
49 
50 
51  /***********************************************************************/
59  class PlacementIndex_test : public Test
60  {
61 
62  virtual void
63  run (Arg)
64  {
65  PlacementIndex index (make_dummyRoot());
66  CHECK (index.isValid());
67 
68  checkSimpleInsertRemove (index);
69  has_size (0, index);
70 
71  PMO::ID elmID = checkSimpleAccess (index);
72  CHECK (index.isValid());
73  has_size (2, index);
74 
75  checkTypedAccess (index, elmID);
76  has_size (3, index);
77 
78  checkScopeHandling (index);
79  has_size (9, index);
80 
82 
83  has_size (9, index);
84  CHECK (index.isValid());
85 
86  index.clear();
87  has_size (0, index);
88  CHECK (index.isValid());
89  }
90 
91  void
92  has_size(uint siz, Idx index)
93  {
94  CHECK (siz == index.size());
95  }
96 
97 
98  void
99  checkSimpleInsertRemove (Idx index)
100  {
101  PMO clip = TestClip::create();
102  PMO& root = index.getRoot();
103 
104  CHECK (0 == index.size());
105 
106  PMO::ID elmID = index.insert (clip, root);
107  CHECK (1 == index.size());
108  CHECK ( index.contains (elmID));
109  CHECK (!index.contains (clip)); // index stores copies
110 
111  index.remove(clip); // has no effect
112  CHECK (1 == index.size());
113  index.remove(elmID);
114  CHECK (0 == index.size());
115  CHECK (!index.contains (elmID));
116  CHECK ( index.contains (root));
117  }
118 
119 
120  PMO::ID
121  checkSimpleAccess (Idx index)
122  {
123  PMO testObj = TestClip::create();
124  PMO& root = index.getRoot();
125  PMO::ID elmID = index.insert (testObj, root);
126 
127  PMO& elm = index.find(elmID);
128  CHECK (elmID == elm.getID());
129  CHECK (!isSameObject (elm,testObj)); // note: placements are registered as copy
130  CHECK (isSameDef(elm,testObj)); // they are semantically equivalent ////////TICKET #511
131  CHECK (elmID != testObj.getID()); // but have a distinct identity
132 
133  PMO::ID elmID2 = index.insert(testObj, root);
134  CHECK (elmID2 != elmID); // ...and each insert creates a new instance
135  CHECK (testObj != index.find (elmID));
136  CHECK (testObj != index.find (elmID2));
137  CHECK (isSameDef(testObj, index.find(elmID)));
138  CHECK (isSameDef(testObj, index.find(elmID2)));
139  CHECK (!isSameObject (testObj, index.find(elmID2)));
140  CHECK (!isSameObject (elm, index.find(elmID2)));
141 
142  // can repeatedly retrieve a reference to the same object
143  CHECK ( isSameObject (elm, index.find(elmID )));
144  CHECK ( isSameObject (elm, index.find(elmID )));
145 
146  // can also re-access objects by previous ref
147  CHECK ( isSameObject (elm, index.find(elm)));
148  return elmID;
149  }
150 
151 
152 
153  void
154  checkTypedAccess (Idx index, PMO::ID elmID)
155  {
156  PMO& elm = index.find(elmID);
157  CHECK (elmID == elm.getID());
158 
159  typedef Placement<Clip> PClip;
160  PClip anotherTestClip = TestClip::create();
161 
162  typedef PlacementMO::Id<Clip> IDClip;
163  IDClip clipID = index.insert(anotherTestClip, elmID);
164  // retaining the more specific type info
165 
166  // access as MObject...
167  PMO::ID mID = clipID;
168  PMO& asMO = index.find(mID);
169 
170  // access as Clip
171  PClip& asClip = index.find(clipID);
172  CHECK (LENGTH_TestClip == asClip->getMedia()->getLength()); // using the Clip API
173 
174  CHECK ( isSameObject(asMO,asClip));
175  CHECK (!isSameObject(asClip, anotherTestClip)); // always inserting a copy into the PlacementIndex
176  }
177 
178 
179  void
180  checkInvalidRef (Idx index)
181  {
182  RefPlacement invalid;
183  PlacementMO::ID invalidID (invalid);
184  CHECK (!bool(invalidID));
185  CHECK (!bool(invalid));
186 
187  VERIFY_ERROR(BOTTOM_PLACEMENTREF, index.find(invalid) );
188  VERIFY_ERROR(BOTTOM_PLACEMENTREF, index.find(invalidID) );
189  VERIFY_ERROR(BOTTOM_PLACEMENTREF, index.getScope(invalidID) );
190 
191  CHECK (!index.contains(invalidID));
192 
193  PMO testObj = TestClip::create();
194  VERIFY_ERROR(INVALID_SCOPE, index.insert(testObj, invalidID) );
195 
196  CHECK (false == index.remove(invalidID));
197  }
198 
199 
200  void
201  checkScopeHandling (Idx index)
202  {
203  PMO testObj = TestClip::create();
204  PMO& root = index.getRoot();
205 
206  typedef PMO::ID ID;
207  ID e1 = index.insert (testObj, root);
208  ID e11 = index.insert (testObj, e1);
209  ID e12 = index.insert (testObj, e1);
210  ID e13 = index.insert (testObj, e1);
211  ID e131 = index.insert (testObj, e13);
212  ID e132 = index.insert (testObj, e13);
213  ID e133 = index.insert (testObj, e13);
214  ID e1331 = index.insert (testObj, e133);
215 
216  CHECK (index.isValid());
217  CHECK (root == index.getScope(e1));
218  CHECK (e1 == index.getScope(e11).getID());
219  CHECK (e1 == index.getScope(e12).getID());
220  CHECK (e1 == index.getScope(e13).getID());
221  CHECK (e13 == index.getScope(e131).getID());
222  CHECK (e13 == index.getScope(e132).getID());
223  CHECK (e13 == index.getScope(e133).getID());
224  CHECK (e133 == index.getScope(e1331).getID());
225  CHECK (e1 != e13);
226  CHECK (e13 != e133);
227 
228  CHECK (index.getScope(e11) == index.getScope(index.find(e11)));
229  CHECK (index.getScope(e131) == index.getScope(index.find(e131)));
230 
231  VERIFY_ERROR(NONEMPTY_SCOPE, index.remove(e13) ); // can't remove a scope-constituting element
232  VERIFY_ERROR(NONEMPTY_SCOPE, index.remove(e133) );
233 
234  CHECK (index.contains(e1331));
235  CHECK (index.remove(e1331));
236  CHECK (!index.contains(e1331));
237  CHECK (!index.remove(e1331));
238 
239  CHECK (index.remove(e133)); // but can remove an scope, after emptying it
240  CHECK (!index.contains(e133));
241  CHECK (index.isValid());
242 
243  // build a complete new subtree
244  uint siz = index.size();
245  ID e1321 = index.insert (testObj, e132);
246  ID e13211 = index.insert (testObj, e1321);
247  ID e13212 = index.insert (testObj, e1321);
248  ID e13213 = index.insert (testObj, e1321);
249  ID e13214 = index.insert (testObj, e1321);
250  ID e132131 = index.insert (testObj, e13213);
251  ID e132132 = index.insert (testObj, e13213);
252  ID e132133 = index.insert (testObj, e13213);
253  ID e132134 = index.insert (testObj, e13213);
254  ID e132141 = index.insert (testObj, e13214);
255  ID e132142 = index.insert (testObj, e13214);
256  ID e132143 = index.insert (testObj, e13214);
257  ID e132144 = index.insert (testObj, e13214);
258 
259  // ...and kill it recursively in one sway
260  index.clear (e1321);
261  CHECK (!index.contains (e1321));
262  CHECK (!index.contains (e13211));
263  CHECK (!index.contains (e13212));
264  CHECK (!index.contains (e13213));
265  CHECK (!index.contains (e132131));
266  CHECK (!index.contains (e132132));
267  CHECK (!index.contains (e132133));
268  CHECK (!index.contains (e132134));
269  CHECK (!index.contains (e132141));
270  CHECK (!index.contains (e132142));
271  CHECK (!index.contains (e132143));
272  CHECK (!index.contains (e132144));
273  CHECK (siz == index.size());
274  CHECK (index.isValid());
275  }
276 
277 
278 
280 
292  void
294  {
295  PMO& root = index.getRoot();
296 
297  Iter rootContents = index.getReferrers (root.getID());
298  CHECK (rootContents);
299 
300  discover (index, rootContents, 0);
301  }
302 
303 
304  void
305  discover (Idx index, Iter iter, uint level)
306  {
307  uint count (0);
308  for ( ; iter; ++iter )
309  {
310  cout << indent(level) << "::" << *iter << endl;
311 
312  ++count;
313  Iter scopeContents = index.getReferrers (iter->getID());
314  if (scopeContents)
315  discover (index, scopeContents, level+1);
316  }
317 
318  static _Fmt summary{"...%i elements at Level %i"};
319  cout << indent(level) << summary % count % level << endl;
320 
321  CHECK (!iter);
322  CHECK (0 < count);
323  }
324 
325  static string
326  indent (uint level)
327  {
328  return string (level, ' ');
329  }
330  };
331 
332 
334  LAUNCHER (PlacementIndex_test, "unit session");
335 
336 
337 }}}} // namespace steam::mobject::session::test
Automatically use custom string conversion in C++ stream output.
Media data represented a specific kind of Asset.
Definition: run.hpp:40
Core abstraction: placement of a media object into session context.
Front-end for printf-style string template interpolation.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
PlacementMO & getRoot() const
retrieve the logical root scope
Steam-Layer implementation namespace root.
A front-end for using printf-style formatting.
Namespace of Session and user visible high-level objects.
Definition: sequence.hpp:65
Core of the session implementation datastructure.
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Iterator tool treating pulled data by a custom transformation (function)
Definition: itertools.hpp:754
bool isSameDef(PlacementMO const &pl1, PlacementMO const &pl2)
compare the properties of placement
Definition: placement.cpp:68
A stub implementation of the Clip interface for unit testing.
bool isValid() const
validity self-check, used for sanity checks and the session self-check.
A collection of frequently used helper functions to support unit testing.
ID insert(PlacementMO const &newObj, ID targetScope)
Add a new Placement (Object "instance") into the index.
void clear(ID targetScope)
recursively kill a complete scope, including the given element and all children.
Structured compound of Placement instances with lookup capabilities.
iterator getReferrers(ID) const
Retrieve all the elements attached to the given entry (scope) Each element (Placement) can act as a s...
Setup of a faked session root for unit testing.
thin wrapper around a size_t hash ID used as primary key for all Asset objects.
Definition: asset.hpp:99
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