LUMIERA.clone/tests/core/steam/mobject/session/timeline-sequence-handling-test.cpp
Ichthyostega 806db414dd Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
 * there is no entity "Lumiera.org" which holds any copyrights
 * Lumiera source code is provided under the GPL Version 2+

== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''

The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!

The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00

311 lines
13 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
TimelineSequenceHandling(Test) - managing the top level session facade objects
Copyright (C)
2008, 2011, Hermann Vosseler <Ichthyostega@web.de>
  **Lumiera** is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the
  Free Software Foundation; either version 2 of the License, or (at your
  option) any later version. See the file COPYING for further details.
* *****************************************************************/
/** @file timeline-sequence-handling-test.cpp
** unit test \ref TimelineSequenceHandling_test
*/
#include "lib/test/run.hpp"
#include "steam/mobject/session.hpp"
#include "steam/mobject/mobject-ref.hpp"
#include "steam/mobject/session/binding.hpp"
//#include "steam/mobject/session/fixture.hpp" // TODO only temporarily needed
#include "steam/assetmanager.hpp"
#include "steam/asset/timeline.hpp"
#include "steam/asset/sequence.hpp"
#include "steam/asset/pipe.hpp"
#include "common/query.hpp"
#include "lib/util.hpp"
using util::isSameObject;
using util::contains;
namespace steam {
namespace mobject {
namespace session {
namespace test {
using proc_interface::AssetManager;
using proc_interface::PAsset;
using asset::Timeline;
using asset::PTimeline;
using asset::Sequence;
using asset::PSequence;
using asset::Pipe;
using lumiera::Query;
/****************************************************************************//**
* @test verify retrieval and instance management of the top level facade objects
* as integrated with the session and high-level model. Both sequences and
* timelines are at the same time structural assets and act as facades
* on the session API. Thus we can query specific instances from the
* struct factory or alternatively access them through the session.
* Moreover we can create new top level elements in the session
* just by querying the respective asset.
*
* @todo specify how deletion is handled
* @todo specify how to \em move objects by placement
*
* @see session-structure-test.cpp
* @see Timeline
* @see Sequence
* @see Session
*/
class TimelineSequenceHandling_test : public Test
{
virtual void
run (Arg)
{
Session::current.reset();
CHECK (Session::current.isUp());
verify_retrieval();
verify_creation();
verify_removalTimeline();
verify_removalBinding();
verify_removalSequence();
indirect_SequenceHandling();
}
void
verify_retrieval()
{
PSess sess = Session::current;
CHECK (sess->isValid());
CHECK (0 < sess->timelines.size());
PTimeline defaultTimeline = sess->defaults (Query<Timeline> ()); //////////////////////TICKET #549
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
Query<Timeline> query1 = "id("+defaultTimeline->getNameID()+").";
PTimeline queriedTimeline = asset::Struct::retrieve (query1);
CHECK (queriedTimeline);
CHECK (queriedTimeline == defaultTimeline); // retrieved the existing timeline asset again
CHECK (queriedTimeline == sess->timelines[0]);
Query<Sequence> query2 = "id("+defaultTimeline->getSequence()->getNameID()+").";
PSequence queriedSequence = asset::Struct::retrieve (query2);
CHECK (queriedSequence);
CHECK (queriedSequence == sess->sequences[0]);
CHECK (queriedSequence == sess->timelines[0]->getSequence());
CHECK (queriedSequence == defaultTimeline->getSequence());
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
}
void
verify_creation()
{
PSess sess = Session::current;
CHECK (sess->isValid());
uint num_timelines = sess->timelines.size();
CHECK (0 < num_timelines);
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
Query<Timeline> special = "id(aSillyName), sequence("
+ sess->sequences[0]->getNameID()
+ "), pipe(ambiance).";
PTimeline specialTimeline (asset::Struct::retrieve (special));
CHECK (specialTimeline);
CHECK (num_timelines + 1 == sess->timelines.size());
CHECK (specialTimeline == session->timelines[num_timelines]); // new one got appended at the end
// verify the properties
CHECK (specialTimeline->getSequence() == sess->sequences[0]); // the already existing sequence got bound into that timeline too
CHECK (contains (specialTimeline->pipes, Pipe::query("pipe(ambiance)")));
CHECK (specialTimeline.use_count() == 3); // we, the AssetManager and the session
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
}
void
verify_removalTimeline()
{
PSess sess (Session::current);
AssetManager& assetM (AssetManager::instance());
CHECK (sess->isValid());
uint num_timelines = sess->timelines.size();
CHECK (2 <= num_timelines);
PTimeline specialTimeline = sess->timelines[num_timelines-1];
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
CHECK ("aSillyName" == specialTimeline->getNameID());
RBinding binding = specialTimeline->getBinding();
CHECK (binding);
PSequence theSeq = binding->getSequence();
CHECK (theSeq == sess->sequences[0]);
CHECK (theSeq == specialTimeline->getSequence());
CHECK (assetM.known (theSeq->getID()));
// cause removal of the timeline
assetM.remove (specialTimeline->getID()); //////////////TICKET #550
CHECK (!assetM.known (specialTimeline->getID()));
CHECK (1 == specialTimeline.use_count()); // we hold the only remaining ref
CHECK ( assetM.known (theSeq->getID())); // bound sequence isn't affected
CHECK (theSeq == sess->sequences[0]);
CHECK (num_timelines - 1 == sess->timelines.size());
CHECK (!binding); // got purged from the model
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
}
void
verify_removalBinding()
{
PSess sess (Session::current);
AssetManager& assetM (AssetManager::instance());
CHECK (sess->isValid());
uint num_timelines = sess->timelines.size();
CHECK (0 < num_timelines);
// create a new Timeline to play with, using the default sequence...
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
PTimeline aTimeline (asset::Struct::retrieve (Query<Timeline> ("sequence("+
+ sess->sequences[0]->getNameID()
+ ").")));
CHECK (num_timelines + 1 == sess->timelines.size());
RBinding binding = aTimeline->getBinding();
CHECK (binding);
PSequence theSeq = binding->getSequence();
CHECK (theSeq == sess->sequences[0]);
CHECK (theSeq == aTimeline->getSequence());
CHECK (assetM.known (aTimeline->getID()));
CHECK (assetM.known (theSeq->getID()));
// indirectly cause removal of the timeline by dropping the binding
sess->remove(binding);
CHECK (!binding);
CHECK (!assetM.known (aTimeline->getID()));
CHECK (1 == aTimeline.use_count());
CHECK ( assetM.known (theSeq->getID()));
CHECK (num_timelines == sess->timelines.size());
CHECK (!contains (sess->timelines, aTimeline));
CHECK ( contains (sess->sequences, theSeq)); // unaffected
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
}
void
verify_removalSequence()
{
PSess sess (Session::current);
AssetManager& assetM (AssetManager::instance());
CHECK (sess->isValid());
uint num_timelines = sess->timelines.size();
uint num_sequences = sess->sequences.size();
// create a new timeline, bound to a new sequence...
PTimeline aTimeline (asset::Struct::retrieve (Query<Timeline> ()));
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
PSequence aSequence (aTimeline->getSequence());
CHECK (num_timelines + 1 == sess->timelines.size());
CHECK (num_sequences + 1 == sess->sequences.size());
RBinding binding = aTimeline->getBinding();
RTrack rootTrack = aSequence->getTracks();
CHECK (rootTrack);
CHECK (binding);
CHECK (aSequence == binding->getSequence());
CHECK (assetM.known (aTimeline->getID()));
CHECK (assetM.known (aSequence->getID()));
// purging the sequence cascades to all linked entities
assetM.remove (aSequence->getID()); //////////////TICKET #550
CHECK (!assetM.known (aTimeline->getID()));
CHECK (!assetM.known (aSequence->getID()));
CHECK (!rootTrack);
CHECK (!binding);
CHECK (num_timelines == sess->timelines.size());
CHECK (num_sequences == sess->sequences.size());
CHECK (!contains (sess->timelines, aTimeline));
CHECK (!contains (sess->sequences, aSequence));
CHECK (1 == aTimeline.use_count());
CHECK (1 == aSequence.use_count());
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
}
void
indirect_SequenceHandling()
{
PSess sess (Session::current);
AssetManager& assetM (AssetManager::instance());
CHECK (sess->isValid());
uint num_sequences = sess->sequences.size();
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
RFork someFork = sess->sequences[0]->getForks();
// indirectly cause a new sequence to come to life...
RFork newFork = sess->getRoot().attach (someFork); // attach new Placement<Fork> to root scope
CHECK (newFork != someFork); // it's a new placement
CHECK (num_sequences + 1 == sess->sequences.size()); // this root-attachment created a new sequence by sideeffect
PSequence aSequence = sess->sequences[num_sequences];
CHECK (newFork == aSequence->getForks());
CHECK (newFork);
CHECK (someFork);
CHECK (assetM.known (aSequence->getID()));
//TODO maybe even bind it into a new timeline. Then verify this new timeline gets removed alongside with the sequence below!
// just moving the new fork away from root position
// causes the sequence to disappear
newFork.getPlacement().chain (someFork, Time(20)); /////////////////TICKET #555 does moving by placement really work this way??
//TODO 3/2010 not finally decided *if* we want this behaviour
//TODO how to verify the changed placement??
CHECK (!assetM.known (aSequence->getID()));
CHECK (num_sequences == sess->sequences.size());
CHECK (!contains (sess->sequences, aSequence));
CHECK (someFork);
CHECK (newFork);
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #499
}
};
/** Register this test class... */
LAUNCHER (TimelineSequenceHandling_test, "unit session");
}}}} // namespace steam::mobject::session::test