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) 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"
33 #include "steam/asset/media.hpp"
34 #include "lib/format-string.hpp"
35 #include "lib/format-cout.hpp"
36 #include "lib/util.hpp"
37 
40 
41 
42 using util::_Fmt;
43 using util::isSameObject;
44 using std::string;
45 
46 
47 namespace steam {
48 namespace mobject {
49 namespace session {
50 namespace test {
51 
52  using session::test::TestClip;
53  using LERR_(BOTTOM_PLACEMENTREF);
54  using LERR_(NONEMPTY_SCOPE);
55  using LERR_(INVALID_SCOPE);
56 
57  typedef PlacementIndex& Idx;
58 
59 
60  /***********************************************************************/
68  class PlacementIndex_test : public Test
69  {
70 
71  virtual void
72  run (Arg)
73  {
74  PlacementIndex index (make_dummyRoot());
75  CHECK (index.isValid());
76 
77  checkSimpleInsertRemove (index);
78  has_size (0, index);
79 
80  PMO::ID elmID = checkSimpleAccess (index);
81  CHECK (index.isValid());
82  has_size (2, index);
83 
84  checkTypedAccess (index, elmID);
85  has_size (3, index);
86 
87  checkScopeHandling (index);
88  has_size (9, index);
89 
91 
92  has_size (9, index);
93  CHECK (index.isValid());
94 
95  index.clear();
96  has_size (0, index);
97  CHECK (index.isValid());
98  }
99 
100  void
101  has_size(uint siz, Idx index)
102  {
103  CHECK (siz == index.size());
104  }
105 
106 
107  void
108  checkSimpleInsertRemove (Idx index)
109  {
110  PMO clip = TestClip::create();
111  PMO& root = index.getRoot();
112 
113  CHECK (0 == index.size());
114 
115  PMO::ID elmID = index.insert (clip, root);
116  CHECK (1 == index.size());
117  CHECK ( index.contains (elmID));
118  CHECK (!index.contains (clip)); // index stores copies
119 
120  index.remove(clip); // has no effect
121  CHECK (1 == index.size());
122  index.remove(elmID);
123  CHECK (0 == index.size());
124  CHECK (!index.contains (elmID));
125  CHECK ( index.contains (root));
126  }
127 
128 
129  PMO::ID
130  checkSimpleAccess (Idx index)
131  {
132  PMO testObj = TestClip::create();
133  PMO& root = index.getRoot();
134  PMO::ID elmID = index.insert (testObj, root);
135 
136  PMO& elm = index.find(elmID);
137  CHECK (elmID == elm.getID());
138  CHECK (!isSameObject (elm,testObj)); // note: placements are registered as copy
139  CHECK (isSameDef(elm,testObj)); // they are semantically equivalent ////////TICKET #511
140  CHECK (elmID != testObj.getID()); // but have a distinct identity
141 
142  PMO::ID elmID2 = index.insert(testObj, root);
143  CHECK (elmID2 != elmID); // ...and each insert creates a new instance
144  CHECK (testObj != index.find (elmID));
145  CHECK (testObj != index.find (elmID2));
146  CHECK (isSameDef(testObj, index.find(elmID)));
147  CHECK (isSameDef(testObj, index.find(elmID2)));
148  CHECK (!isSameObject (testObj, index.find(elmID2)));
149  CHECK (!isSameObject (elm, index.find(elmID2)));
150 
151  // can repeatedly retrieve a reference to the same object
152  CHECK ( isSameObject (elm, index.find(elmID )));
153  CHECK ( isSameObject (elm, index.find(elmID )));
154 
155  // can also re-access objects by previous ref
156  CHECK ( isSameObject (elm, index.find(elm)));
157  return elmID;
158  }
159 
160 
161 
162  void
163  checkTypedAccess (Idx index, PMO::ID elmID)
164  {
165  PMO& elm = index.find(elmID);
166  CHECK (elmID == elm.getID());
167 
168  typedef Placement<Clip> PClip;
169  PClip anotherTestClip = TestClip::create();
170 
171  typedef PlacementMO::Id<Clip> IDClip;
172  IDClip clipID = index.insert(anotherTestClip, elmID);
173  // retaining the more specific type info
174 
175  // access as MObject...
176  PMO::ID mID = clipID;
177  PMO& asMO = index.find(mID);
178 
179  // access as Clip
180  PClip& asClip = index.find(clipID);
181  CHECK (LENGTH_TestClip == asClip->getMedia()->getLength()); // using the Clip API
182 
183  CHECK ( isSameObject(asMO,asClip));
184  CHECK (!isSameObject(asClip, anotherTestClip)); // always inserting a copy into the PlacementIndex
185  }
186 
187 
188  void
189  checkInvalidRef (Idx index)
190  {
191  RefPlacement invalid;
192  PlacementMO::ID invalidID (invalid);
193  CHECK (!bool(invalidID));
194  CHECK (!bool(invalid));
195 
196  VERIFY_ERROR(BOTTOM_PLACEMENTREF, index.find(invalid) );
197  VERIFY_ERROR(BOTTOM_PLACEMENTREF, index.find(invalidID) );
198  VERIFY_ERROR(BOTTOM_PLACEMENTREF, index.getScope(invalidID) );
199 
200  CHECK (!index.contains(invalidID));
201 
202  PMO testObj = TestClip::create();
203  VERIFY_ERROR(INVALID_SCOPE, index.insert(testObj, invalidID) );
204 
205  CHECK (false == index.remove(invalidID));
206  }
207 
208 
209  void
210  checkScopeHandling (Idx index)
211  {
212  PMO testObj = TestClip::create();
213  PMO& root = index.getRoot();
214 
215  typedef PMO::ID ID;
216  ID e1 = index.insert (testObj, root);
217  ID e11 = index.insert (testObj, e1);
218  ID e12 = index.insert (testObj, e1);
219  ID e13 = index.insert (testObj, e1);
220  ID e131 = index.insert (testObj, e13);
221  ID e132 = index.insert (testObj, e13);
222  ID e133 = index.insert (testObj, e13);
223  ID e1331 = index.insert (testObj, e133);
224 
225  CHECK (index.isValid());
226  CHECK (root == index.getScope(e1));
227  CHECK (e1 == index.getScope(e11).getID());
228  CHECK (e1 == index.getScope(e12).getID());
229  CHECK (e1 == index.getScope(e13).getID());
230  CHECK (e13 == index.getScope(e131).getID());
231  CHECK (e13 == index.getScope(e132).getID());
232  CHECK (e13 == index.getScope(e133).getID());
233  CHECK (e133 == index.getScope(e1331).getID());
234  CHECK (e1 != e13);
235  CHECK (e13 != e133);
236 
237  CHECK (index.getScope(e11) == index.getScope(index.find(e11)));
238  CHECK (index.getScope(e131) == index.getScope(index.find(e131)));
239 
240  VERIFY_ERROR(NONEMPTY_SCOPE, index.remove(e13) ); // can't remove a scope-constituting element
241  VERIFY_ERROR(NONEMPTY_SCOPE, index.remove(e133) );
242 
243  CHECK (index.contains(e1331));
244  CHECK (index.remove(e1331));
245  CHECK (!index.contains(e1331));
246  CHECK (!index.remove(e1331));
247 
248  CHECK (index.remove(e133)); // but can remove an scope, after emptying it
249  CHECK (!index.contains(e133));
250  CHECK (index.isValid());
251 
252  // build a complete new subtree
253  uint siz = index.size();
254  ID e1321 = index.insert (testObj, e132);
255  ID e13211 = index.insert (testObj, e1321);
256  ID e13212 = index.insert (testObj, e1321);
257  ID e13213 = index.insert (testObj, e1321);
258  ID e13214 = index.insert (testObj, e1321);
259  ID e132131 = index.insert (testObj, e13213);
260  ID e132132 = index.insert (testObj, e13213);
261  ID e132133 = index.insert (testObj, e13213);
262  ID e132134 = index.insert (testObj, e13213);
263  ID e132141 = index.insert (testObj, e13214);
264  ID e132142 = index.insert (testObj, e13214);
265  ID e132143 = index.insert (testObj, e13214);
266  ID e132144 = index.insert (testObj, e13214);
267 
268  // ...and kill it recursively in one sway
269  index.clear (e1321);
270  CHECK (!index.contains (e1321));
271  CHECK (!index.contains (e13211));
272  CHECK (!index.contains (e13212));
273  CHECK (!index.contains (e13213));
274  CHECK (!index.contains (e132131));
275  CHECK (!index.contains (e132132));
276  CHECK (!index.contains (e132133));
277  CHECK (!index.contains (e132134));
278  CHECK (!index.contains (e132141));
279  CHECK (!index.contains (e132142));
280  CHECK (!index.contains (e132143));
281  CHECK (!index.contains (e132144));
282  CHECK (siz == index.size());
283  CHECK (index.isValid());
284  }
285 
286 
287 
289 
301  void
303  {
304  PMO& root = index.getRoot();
305 
306  Iter rootContents = index.getReferrers (root.getID());
307  CHECK (rootContents);
308 
309  discover (index, rootContents, 0);
310  }
311 
312 
313  void
314  discover (Idx index, Iter iter, uint level)
315  {
316  uint count (0);
317  for ( ; iter; ++iter )
318  {
319  cout << indent(level) << "::" << *iter << endl;
320 
321  ++count;
322  Iter scopeContents = index.getReferrers (iter->getID());
323  if (scopeContents)
324  discover (index, scopeContents, level+1);
325  }
326 
327  static _Fmt summary{"...%i elements at Level %i"};
328  cout << indent(level) << summary % count % level << endl;
329 
330  CHECK (!iter);
331  CHECK (0 < count);
332  }
333 
334  static string
335  indent (uint level)
336  {
337  return string (level, ' ');
338  }
339  };
340 
341 
343  LAUNCHER (PlacementIndex_test, "unit session");
344 
345 
346 }}}} // 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:49
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:74
Core of the session implementation datastructure.
Simple 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:763
bool isSameDef(PlacementMO const &pl1, PlacementMO const &pl2)
compare the properties of placement
Definition: placement.cpp:77
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:108
bool isSameObject(A const &a, B const &b)
compare plain object identity, bypassing any custom comparison operators.
Definition: util.hpp:372