Lumiera  0.pre.03
»edit your freedom«
session-modify-parts-test.cpp
Go to the documentation of this file.
1 /*
2  SessionModifyParts(Test) - adding and removing elements, changing structure
3 
4  Copyright (C)
5  2010, 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"
21 #include "steam/fixture/fixture.hpp" // TODO only temporarily needed
22 //#include "steam/assetmanager.hpp" //////??
23 //#include "steam/asset/timeline.hpp"
24 #include "steam/asset/sequence.hpp"
25 #include "lib/format-cout.hpp"
26 #include "lib/util-foreach.hpp"
30 #include "common/query.hpp"
31 
32 #include <functional>
33 #include <set>
34 
35 using std::ref;
36 using std::placeholders::_1;
37 using util::isSameObject;
38 using util::and_all;
39 using std::set;
40 
41 
42 namespace steam {
43 namespace mobject {
44 namespace session {
45 namespace test {
46 
47 // using proc_interface::AssetManager;
48  using proc_interface::PAsset;
49 
50 // using asset::PTimeline;
51  using asset::PSequence;
52  using asset::Sequence;
53 
54  using lumiera::Query;
55 
56  typedef MORef<session::Clip> RClip;
57  typedef PlacementMO::ID PID;
58 
59 
60 
61  /***************************************************************************/
72  class SessionModifyParts_test : public Test
73  {
74  virtual void
75  run (Arg)
76  {
78  CHECK (Session::current.isUp());
79 
80  addForks();
81  addObjects();
82  removeParts();
83 
84  verify_dispatchedCommands();
85  }
86 
87 
88  void
89  addForks()
90  {
91  PSess sess = Session::current;
92  CHECK (sess->isValid());
93 
94  PSequence seq = sess->defaults (Query<Sequence> ());
95  CHECK (seq);
96 
97 #if false
98  RFork fork1 = seq->attachFork();
99  RFork fork2 = seq->attachFork("fork-2");
100  RFork fork21 = seq->attachFork("fork-2.1", fork2);
101  RFork fork22 = seq->attachFork("fork-2.2", "fork-2");
102 
103  QueryFocus& focus = sess->focus();
104  CHECK (fork22 == focus.getObject());
105 
106  RFork fork3 = seq->attachFork("fork-3", "root");
107  CHECK (fork3 == focus.getObject());
108 
109  RFork fork31 = sess->attach(
110  asset::Struct::retrieve (Query<asset::???? > ("id(fork31)")));
111 
112 
113  CHECK (fork31 == focus.getObject());
114  RFork rootFork = seq->rootFork();
115  CHECK (3 == rootFork->subForks.size());
116  CHECK (fork1 == rootFork->subForks[0]);
117  CHECK (fork2 == rootFork->subForks[1]);
118  CHECK (fork3 == rootFork->subForks[2]);
119  CHECK (0 == fork1->subForks.size());
120  CHECK (2 == fork2->subForks.size());
121  CHECK (fork21 == fork2->subForks[0]);
122  CHECK (fork22 == fork2->subForks[1]);
123  CHECK (1 == fork3->subForks.size());
124  CHECK (fork21 == fork3->subForks[0]);
125 
126  set<RFork> allForks;
127  allForks.insert(fork1);
128  allForks.insert(fork2);
129  allForks.insert(fork21);
130  allForks.insert(fork22);
131  allForks.insert(fork3);
132  allForks.insert(fork31);
133 
134  // verify we indeed covered all forks known to the session....
135  CHECK (and_all (sess->all<Fork>(), contains, ref(allForks), _1 ));
136 #endif
137  }
138 
139 
140  void
141  addObjects()
142  {
143  PSess sess = Session::current;
144  CHECK (sess->isValid());
145 
146 #if false
147  QueryFocus& focus = sess->focus();
148  CHECK (focus.getObject().isCompatible<session::Fork>());
149  RClip clip1 = sess->attach (TestClip::create());
150 
151  RTrack fork31 = clip.getParent();
152  CHECK (fork31);
153  CHECK ("fork31" == fork31->getNameID());
154 
155  CHECK (1 == fork31->clips.size());
156  CHECK (clip1 == fork31->clips[0]);
157 
158  RClip clip2 = fork31.attach (TestClip::create());
159  RClip clip3 = fork31.attach (clip1); // creates a clone instance
160 
161  CHECK (clip1); CHECK (clip2); CHECK (clip3);
162  CHECK (clip1 != clip2);
163  CHECK (clip1 != clip3);
164  CHECK (clip2 != clip3);
165  CHECK (!isSharedPointee (clip1, clip2));
166  CHECK (!isSharedPointee (clip2, clip3));
167  CHECK ( isSharedPointee (clip1, clip3));
168  CHECK (isEquivalentPlacement (clip1, clip2));
169  CHECK (isEquivalentPlacement (clip2, clip3));
170  CHECK (isEquivalentPlacement (clip1, clip3));
171 
172  RTrack fork2 = sess->sequences[0]
173  ->rootTrack()
174  ->subTracks[1];
175  RClip clip4 = fork2.attach (TestClip::create());
176 
177  // now verify structure built up thus far
178  CHECK (focus.getObject() == fork2); // focus follows point-of-mutation
179  CHECK (focus.contains (clip4));
180  CHECK (!focus.contains (clip1));
181  CHECK (!focus.contains (clip2));
182  CHECK (!focus.contains (clip3));
183 
184  focus.attach (fork31);
185  CHECK (focus.getObject() == fork31);
186  CHECK (focus.contains (clip1));
187  CHECK (focus.contains (clip2));
188  CHECK (focus.contains (clip3));
189  CHECK (!focus.contains (clip4));
190 
191  focus.reset();
192  CHECK (focus.getObject() == sess->getRoot());
193  CHECK (focus.contains (clip1)); // containment test includes sub-scopes
194  CHECK (focus.contains (clip2));
195  CHECK (focus.contains (clip3));
196  CHECK (focus.contains (clip4));
197  CHECK (!focus.hasChild (clip1)); // but they are indeed nested more deeply
198  CHECK (!focus.hasChild (clip2));
199  CHECK (!focus.hasChild (clip3));
200  CHECK (!focus.hasChild (clip4));
201 
202  focus.attach (sess->sequences[0]->rootTrack()->subTracks[2]->subTracks[0]); // train wreck. Don't try it at home!
203  CHECK (focus.getObject() == fork31); // (this test is an exception, as we know the structure precisely
204  // production code should always discover one level a time)
205  CHECK ( focus.hasChild (clip1));
206  CHECK ( focus.hasChild (clip2));
207  CHECK ( focus.hasChild (clip3));
208  CHECK (!focus.hasChild (clip4)); // ...because this one is on fork2, not fork31
209 #endif
210  }
211 
212 
213  void
214  removeParts()
215  {
216 #if false
217  PSess sess = Session::current;
218  CHECK (sess->isValid());
219 
220  RTrack fork31 = sess->sequences[0]->rootTrack()->subTracks[2]->subTracks[0];
221  CHECK (fork31);
222  CHECK (3 == fork31->clips.size());
223  RClip clip2 = fork31->clips[1];
224 
225  QueryFocus& focus = sess->focus();
226  focus.reset(); // navigate to root
227 
228  CHECK (focus.contains (clip2));
229  CHECK (clip2);
230  clip2.purge();
231  CHECK (!clip2);
232  CHECK (!focus.contains (clip2));
233 
234  CHECK (2 == fork31->clips.size());
235  CHECK (clip2 != fork31->clips[1]);
236 
237  CHECK (focus.getObject() == fork31); // focus follows point-of-mutation
238 
239  // Using the query-focus to explore the contents of this current object (fork31)
240  ScopeQuery<Clip>::iterator discoverClips = focus.explore<Clip>();
241  CHECK (discoverClips);
242  RClip clip1 = *discoverClips;
243  ++discoverClips;
244  RClip clip3 = *discoverClips;
245  ++discoverClips;
246  CHECK (!discoverClips);
247 
248  CHECK (fork31->clips[0] == clip1);
249  CHECK (fork31->clips[1] == clip3);
250  /* please note: the clips aren't discovered in any defined order (hashtable!)
251  * especially, the order doesn't match the order of addition!
252  * thus, what's called clip1 here may or may not be
253  * what we called clip1 in addObjects()
254  */
255 
256  RTrack fork3 = fork31.getParent();
257 
258  focus.reset(); // back to root
259  CHECK (focus.contains (clip1));
260  CHECK (focus.contains (clip3));
261  CHECK (focus.contains (fork3));
262  CHECK (focus.contains (fork31));
263  CHECK (clip1);
264  CHECK (clip3);
265  CHECK (fork3);
266  CHECK (fork31);
267 
268  sess->purge (fork31);
269 
270  CHECK (focus.getObject() == fork3);
271  focus.reset();
272  CHECK ( focus.contains (fork3));
273 
274  CHECK (!focus.contains (clip1));
275  CHECK (!focus.contains (clip3));
276  CHECK (!focus.contains (fork31));
277  CHECK (!clip1);
278  CHECK (!clip3);
279  CHECK (!fork31);
280  CHECK (fork3);
281 
282  fork3.purge();
283  CHECK (!fork3);
284  PSequence aSequence = sess->sequences[0];
285  CHECK (focus.getObject() == aSequence->rootTrack());
286  CHECK (2 == aSequece->rootTrack()->subTracks.size());
287 
288  CHECK ( contains (sess->sequences, aSequence));
289  aSequence->rootFork().purge(); // automatically kills the sequence as well (sequence == facade to the fork root)
290  CHECK (!contains (sess->sequences, aSequence));
291  CHECK (0 == sess->sequences.size());
292  CHECK (0 == sess->timelines.size()); // killing the sequence also cascaded to the timeline and binding
293  CHECK (!sess->isValid()); // thus effectively the session is now invalid (no timeline)
294 
295  CHECK (focus.getObject() == sess->getRoot());
296 
297  PID currRoot = sess->getRoot.getPlacement().getID();
298  sess->getRoot().purge(); // purging the root scope effectively resets the session to defaults
299  CHECK (currRoot == sess->getRoot.getPlacement.getID);
300  // but the root element itself is retained
301  CHECK (sess->isValid());
302  CHECK (1 == sess->timelines.size());
303  CHECK (1 == sess->sequences.size());
304  CHECK (aSequence != sess->sequences[0]);
305  CHECK (aSequence.use_count() == 1); // we're holding the last remaining reference
306 #endif
307  }
308 
309 
310  void
311  verify_dispatchedCommands()
312  {
313  TODO ("verify the commands issued by this test");
314  }
315 
316  };
317 
318 
320  LAUNCHER (SessionModifyParts_test, "unit session");
321 
322 
323 
324 }}}} // namespace steam::mobject::session::test
Automatically use custom string conversion in C++ stream output.
An active (smart-ptr like) external reference to a specifically placed MObject "instance" within the ...
Definition: mobject-ref.hpp:85
TODO type comment.
Definition: sequence.hpp:83
virtual void reset()=0
reset all session config and start with a pristine default session.
Basic and generic representation of an internal query.
void purge()
detach this object instance from model, including all child elements.
Definition: run.hpp:40
Core abstraction: placement of a media object into session context.
Backbone data structure of the low-level render node model The fixture defines the boundary between t...
bool isSharedPointee(MORef< MOX > const &ref1, MORef< MOY > const &ref2)
check if the two references actually share ownership on the same underlying MObject (as opposed to re...
bool and_all(CON const &elements, FUN function, P1 &&bind1, ARGS &&...args)
Accept binding for arbitrary function arguments.
static session::SessManager & current
access point to the current Session
Definition: session.hpp:120
A user visible/editable Clip is a reference to a contiguous sequence of media data loaded as Asset in...
Steam-Layer implementation namespace root.
DefaultsAccess defaults
manages default configured objects
Definition: session.hpp:122
Namespace of Session and user visible high-level objects.
Definition: sequence.hpp:65
static StructFactory retrieve
storage for the static StructFactory instance
Definition: struct.hpp:107
Structural building block of the session: a sequence of clips.
External MObject/Placement reference.
Simplistic test class runner.
ScopeQuery< MO >::iterator explore() const
discover any matching object contained as immediate Child within current focus.
creation, access and Session lifecycle Interface.
Definition: session.hpp:152
A stub implementation of the Clip interface for unit testing.
SequenceAccess sequences
collection of sequences
Definition: session.hpp:125
A Fork serves as grouping device within the Session.
Definition: fork.hpp:94
QueryFocus & reset()
discard any state and navigate current focus path to model root
Definition: query-focus.cpp:68
Customised refcounting smart pointer template, built upon std::shared_ptr, but forwarding type relati...
Definition: trait.hpp:71
Primary Interface to the current Session.
Current focus location to use as point-of reference for contents and location discovery queries...
Perform operations "for each element" of a collection.
Adapter for building an implementation of the »Lumiera Forward Iterator« concept. ...
Generic interface to express a query for specifically typed result elements exposing some capabilitie...
Definition: query.hpp:270
bool isEquivalentPlacement(MORef< MOX > const &ref1, MORef< MOY > const &ref2)
check if the two references actually denote an equivalent placement
TimelineAccess timelines
collection of timelines (top level)
Definition: session.hpp:124
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