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) Lumiera.org
5  2010, 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"
30 #include "steam/fixture/fixture.hpp" // TODO only temporarily needed
31 //#include "steam/assetmanager.hpp" //////??
32 //#include "steam/asset/timeline.hpp"
33 #include "steam/asset/sequence.hpp"
34 #include "lib/format-cout.hpp"
35 #include "lib/util-foreach.hpp"
39 #include "common/query.hpp"
40 
41 #include <functional>
42 #include <set>
43 
44 using std::ref;
45 using std::placeholders::_1;
46 using util::isSameObject;
47 using util::and_all;
48 using std::set;
49 
50 
51 namespace steam {
52 namespace mobject {
53 namespace session {
54 namespace test {
55 
56 // using proc_interface::AssetManager;
57  using proc_interface::PAsset;
58 
59 // using asset::PTimeline;
60  using asset::PSequence;
61  using asset::Sequence;
62 
63  using lumiera::Query;
64 
65  typedef MORef<session::Clip> RClip;
66  typedef PlacementMO::ID PID;
67 
68 
69 
70  /***************************************************************************/
81  class SessionModifyParts_test : public Test
82  {
83  virtual void
84  run (Arg)
85  {
87  CHECK (Session::current.isUp());
88 
89  addForks();
90  addObjects();
91  removeParts();
92 
93  verify_dispatchedCommands();
94  }
95 
96 
97  void
98  addForks()
99  {
100  PSess sess = Session::current;
101  CHECK (sess->isValid());
102 
103  PSequence seq = sess->defaults (Query<Sequence> ());
104  CHECK (seq);
105 
106 #if false
107  RFork fork1 = seq->attachFork();
108  RFork fork2 = seq->attachFork("fork-2");
109  RFork fork21 = seq->attachFork("fork-2.1", fork2);
110  RFork fork22 = seq->attachFork("fork-2.2", "fork-2");
111 
112  QueryFocus& focus = sess->focus();
113  CHECK (fork22 == focus.getObject());
114 
115  RFork fork3 = seq->attachFork("fork-3", "root");
116  CHECK (fork3 == focus.getObject());
117 
118  RFork fork31 = sess->attach(
119  asset::Struct::retrieve (Query<asset::???? > ("id(fork31)")));
120 
121 
122  CHECK (fork31 == focus.getObject());
123  RFork rootFork = seq->rootFork();
124  CHECK (3 == rootFork->subForks.size());
125  CHECK (fork1 == rootFork->subForks[0]);
126  CHECK (fork2 == rootFork->subForks[1]);
127  CHECK (fork3 == rootFork->subForks[2]);
128  CHECK (0 == fork1->subForks.size());
129  CHECK (2 == fork2->subForks.size());
130  CHECK (fork21 == fork2->subForks[0]);
131  CHECK (fork22 == fork2->subForks[1]);
132  CHECK (1 == fork3->subForks.size());
133  CHECK (fork21 == fork3->subForks[0]);
134 
135  set<RFork> allForks;
136  allForks.insert(fork1);
137  allForks.insert(fork2);
138  allForks.insert(fork21);
139  allForks.insert(fork22);
140  allForks.insert(fork3);
141  allForks.insert(fork31);
142 
143  // verify we indeed covered all forks known to the session....
144  CHECK (and_all (sess->all<Fork>(), contains, ref(allForks), _1 ));
145 #endif
146  }
147 
148 
149  void
150  addObjects()
151  {
152  PSess sess = Session::current;
153  CHECK (sess->isValid());
154 
155 #if false
156  QueryFocus& focus = sess->focus();
157  CHECK (focus.getObject().isCompatible<session::Fork>());
158  RClip clip1 = sess->attach (TestClip::create());
159 
160  RTrack fork31 = clip.getParent();
161  CHECK (fork31);
162  CHECK ("fork31" == fork31->getNameID());
163 
164  CHECK (1 == fork31->clips.size());
165  CHECK (clip1 == fork31->clips[0]);
166 
167  RClip clip2 = fork31.attach (TestClip::create());
168  RClip clip3 = fork31.attach (clip1); // creates a clone instance
169 
170  CHECK (clip1); CHECK (clip2); CHECK (clip3);
171  CHECK (clip1 != clip2);
172  CHECK (clip1 != clip3);
173  CHECK (clip2 != clip3);
174  CHECK (!isSharedPointee (clip1, clip2));
175  CHECK (!isSharedPointee (clip2, clip3));
176  CHECK ( isSharedPointee (clip1, clip3));
177  CHECK (isEquivalentPlacement (clip1, clip2));
178  CHECK (isEquivalentPlacement (clip2, clip3));
179  CHECK (isEquivalentPlacement (clip1, clip3));
180 
181  RTrack fork2 = sess->sequences[0]
182  ->rootTrack()
183  ->subTracks[1];
184  RClip clip4 = fork2.attach (TestClip::create());
185 
186  // now verify structure built up thus far
187  CHECK (focus.getObject() == fork2); // focus follows point-of-mutation
188  CHECK (focus.contains (clip4));
189  CHECK (!focus.contains (clip1));
190  CHECK (!focus.contains (clip2));
191  CHECK (!focus.contains (clip3));
192 
193  focus.attach (fork31);
194  CHECK (focus.getObject() == fork31);
195  CHECK (focus.contains (clip1));
196  CHECK (focus.contains (clip2));
197  CHECK (focus.contains (clip3));
198  CHECK (!focus.contains (clip4));
199 
200  focus.reset();
201  CHECK (focus.getObject() == sess->getRoot());
202  CHECK (focus.contains (clip1)); // containment test includes sub-scopes
203  CHECK (focus.contains (clip2));
204  CHECK (focus.contains (clip3));
205  CHECK (focus.contains (clip4));
206  CHECK (!focus.hasChild (clip1)); // but they are indeed nested more deeply
207  CHECK (!focus.hasChild (clip2));
208  CHECK (!focus.hasChild (clip3));
209  CHECK (!focus.hasChild (clip4));
210 
211  focus.attach (sess->sequences[0]->rootTrack()->subTracks[2]->subTracks[0]); // train wreck. Don't try it at home!
212  CHECK (focus.getObject() == fork31); // (this test is an exception, as we know the structure precisely
213  // production code should always discover one level a time)
214  CHECK ( focus.hasChild (clip1));
215  CHECK ( focus.hasChild (clip2));
216  CHECK ( focus.hasChild (clip3));
217  CHECK (!focus.hasChild (clip4)); // ...because this one is on fork2, not fork31
218 #endif
219  }
220 
221 
222  void
223  removeParts()
224  {
225 #if false
226  PSess sess = Session::current;
227  CHECK (sess->isValid());
228 
229  RTrack fork31 = sess->sequences[0]->rootTrack()->subTracks[2]->subTracks[0];
230  CHECK (fork31);
231  CHECK (3 == fork31->clips.size());
232  RClip clip2 = fork31->clips[1];
233 
234  QueryFocus& focus = sess->focus();
235  focus.reset(); // navigate to root
236 
237  CHECK (focus.contains (clip2));
238  CHECK (clip2);
239  clip2.purge();
240  CHECK (!clip2);
241  CHECK (!focus.contains (clip2));
242 
243  CHECK (2 == fork31->clips.size());
244  CHECK (clip2 != fork31->clips[1]);
245 
246  CHECK (focus.getObject() == fork31); // focus follows point-of-mutation
247 
248  // Using the query-focus to explore the contents of this current object (fork31)
249  ScopeQuery<Clip>::iterator discoverClips = focus.explore<Clip>();
250  CHECK (discoverClips);
251  RClip clip1 = *discoverClips;
252  ++discoverClips;
253  RClip clip3 = *discoverClips;
254  ++discoverClips;
255  CHECK (!discoverClips);
256 
257  CHECK (fork31->clips[0] == clip1);
258  CHECK (fork31->clips[1] == clip3);
259  /* please note: the clips aren't discovered in any defined order (hashtable!)
260  * especially, the order doesn't match the order of addition!
261  * thus, what's called clip1 here may or may not be
262  * what we called clip1 in addObjects()
263  */
264 
265  RTrack fork3 = fork31.getParent();
266 
267  focus.reset(); // back to root
268  CHECK (focus.contains (clip1));
269  CHECK (focus.contains (clip3));
270  CHECK (focus.contains (fork3));
271  CHECK (focus.contains (fork31));
272  CHECK (clip1);
273  CHECK (clip3);
274  CHECK (fork3);
275  CHECK (fork31);
276 
277  sess->purge (fork31);
278 
279  CHECK (focus.getObject() == fork3);
280  focus.reset();
281  CHECK ( focus.contains (fork3));
282 
283  CHECK (!focus.contains (clip1));
284  CHECK (!focus.contains (clip3));
285  CHECK (!focus.contains (fork31));
286  CHECK (!clip1);
287  CHECK (!clip3);
288  CHECK (!fork31);
289  CHECK (fork3);
290 
291  fork3.purge();
292  CHECK (!fork3);
293  PSequence aSequence = sess->sequences[0];
294  CHECK (focus.getObject() == aSequence->rootTrack());
295  CHECK (2 == aSequece->rootTrack()->subTracks.size());
296 
297  CHECK ( contains (sess->sequences, aSequence));
298  aSequence->rootFork().purge(); // automatically kills the sequence as well (sequence == facade to the fork root)
299  CHECK (!contains (sess->sequences, aSequence));
300  CHECK (0 == sess->sequences.size());
301  CHECK (0 == sess->timelines.size()); // killing the sequence also cascaded to the timeline and binding
302  CHECK (!sess->isValid()); // thus effectively the session is now invalid (no timeline)
303 
304  CHECK (focus.getObject() == sess->getRoot());
305 
306  PID currRoot = sess->getRoot.getPlacement().getID();
307  sess->getRoot().purge(); // purging the root scope effectively resets the session to defaults
308  CHECK (currRoot == sess->getRoot.getPlacement.getID);
309  // but the root element itself is retained
310  CHECK (sess->isValid());
311  CHECK (1 == sess->timelines.size());
312  CHECK (1 == sess->sequences.size());
313  CHECK (aSequence != sess->sequences[0]);
314  CHECK (aSequence.use_count() == 1); // we're holding the last remaining reference
315 #endif
316  }
317 
318 
319  void
320  verify_dispatchedCommands()
321  {
322  TODO ("verify the commands issued by this test");
323  }
324 
325  };
326 
327 
329  LAUNCHER (SessionModifyParts_test, "unit session");
330 
331 
332 
333 }}}} // 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:94
TODO type comment.
Definition: sequence.hpp:92
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:49
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:129
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:131
Namespace of Session and user visible high-level objects.
Definition: sequence.hpp:74
static StructFactory retrieve
storage for the static StructFactory instance
Definition: struct.hpp:116
Structural building block of the session: a sequence of clips.
External MObject/Placement reference.
Simple 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:161
A stub implementation of the Clip interface for unit testing.
SequenceAccess sequences
collection of sequences
Definition: session.hpp:134
A Fork serves as grouping device within the Session.
Definition: fork.hpp:103
QueryFocus & reset()
discard any state and navigate current focus path to model root
Definition: query-focus.cpp:77
Customised refcounting smart pointer template, built upon std::shared_ptr, but forwarding type relati...
Definition: trait.hpp:80
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:279
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:133
bool isSameObject(A const &a, B const &b)
compare plain object identity, bypassing any custom comparison operators.
Definition: util.hpp:372