LUMIERA.clone/tests/core/steam/mobject/session/placement-scope-test.cpp
Ichthyostega a90b9e5f16 Library: uniform definition scheme for error-IDs
In the Lumiera code base, we use C-String constants as unique error-IDs.
Basically this allows to create new unique error IDs anywhere in the code.

However, definition of such IDs in arbitrary namespaces tends to create
slight confusion and ambiguities, while maintaining the proper use statements
requires some manual work.

Thus I introduce a new **standard scheme**
 * Error-IDs for widespread use shall be defined _exclusively_ into `namespace lumiera::error`
 * The shorthand-Macro `LERR_()` can now be used to simplify inclusion and referral
 * (for local or single-usage errors, a local or even hidden definition is OK)
2024-03-21 19:57:34 +01:00

203 lines
6.6 KiB
C++

/*
PlacementScope(Test) - accessing and navigating placement scope
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
This program 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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file placement-scope-test.cpp
** unit test \ref PlacementScope_test
*/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "steam/mobject/mobject.hpp"
#include "steam/mobject/session/scope.hpp"
#include "steam/mobject/session/test-scopes.hpp"
#include "steam/mobject/session/scope-locator.hpp"
#include "lib/format-cout.hpp"
#include "lib/util.hpp"
namespace steam {
namespace mobject {
namespace session {
namespace test {
namespace { // Helper to enumerate Contents
// of the test-dummy session
typedef _ScopeIterMO _Iter;
_Iter
contents_of_testSession (PPIdx testSession)
{
return ScopeLocator::instance().query<MObject> (testSession->getRoot());
}
_Iter
pathToRoot (PlacementMO& elm)
{
Scope startScope(elm);
return ScopeLocator::instance().getRawPath (startScope);
}
}
using LERR_(NO_PARENT_SCOPE);
using util::isSameObject;
/***********************************************************************//**
* @test basic behaviour of the nested placement search scopes.
* Using a pseudo-session (actually just a PlacementIndex),
* this test creates some nested scopes and then...
* - discovers the scope of a placement
* - finds the parent scope
* - enumerates a scope path up to root
*
* @see mobject::Placement
* @see mobject::session::ScopePath
* @see mobject::session::QueryFocus
*/
class PlacementScope_test : public Test
{
virtual void
run (Arg)
{
// Prepare an (test)Session
// with some dummy contents
PPIdx index = build_testScopes();
verifyEquality();
verifyLookup (index);
verifyNavigation (index);
}
/** @test for each Placement in our test "session",
* find the scope and verify it's in line with the index
*/
void
verifyLookup (PPIdx sess)
{
for (_Iter ii = contents_of_testSession(sess); ii; ++ii)
{
PlacementMO& elm = *ii;
CHECK (elm.isValid());
Scope const& scope1 = Scope::containing(elm);
cout << "Scope: " << scope1 << endl;
cout << elm << endl;
RefPlacement ref (elm);
Scope const& scope2 = Scope::containing(ref);
// verify this with the scope registered within the index...
PlacementMO& scopeTop = sess->getScope(elm);
CHECK (scope1 == scopeTop);
CHECK (scope2 == scopeTop);
CHECK (scope1 == scope2);
CHECK (!isSameObject (scope1,scope2));
}
}
/** @test equality of scopes is based on the ID of the scope top (Placement) */
void
verifyEquality ()
{
PlacementMO& aPlac = retrieve_startElm();
Scope scope1(aPlac);
Scope scope2(aPlac);
Scope nil;
CHECK (scope1 == scope2); CHECK (scope2 == scope1);
CHECK (scope1 != nil); CHECK (nil != scope1);
CHECK (scope2 != nil); CHECK (nil != scope2);
CHECK (aPlac == scope1); CHECK (scope1 == aPlac);
CHECK (aPlac == scope2); CHECK (scope2 == aPlac);
CHECK (aPlac != nil); CHECK (nil != aPlac);
Scope par (scope1.getParent());
CHECK (scope1 != par); CHECK (par != scope1);
CHECK (scope2 != par); CHECK (par != scope2);
PlacementMO& placm2 (scope2.getTop());
CHECK (aPlac.getID() == placm2.getID());
PlacementMO& parPlac (par.getTop());
CHECK (aPlac.getID() != parPlac.getID());
}
/** @test for each element in our test session,
* establish the scope and retrieve the path to root,
* verifying the parent relationships as we go up.
* @note this is the "raw" path, i.e as stored in the
* PlacementIndex, as opposed to the effective
* path, which might digress for meta-clips
*/
void
verifyNavigation (PPIdx sess)
{
for (_Iter elm = contents_of_testSession(sess); elm; ++elm)
{
_Iter pathIter = pathToRoot(*elm);
Scope const& enclosing = Scope::containing(*elm);
CHECK (enclosing == Scope(*elm).getParent());
CHECK (*pathIter == Scope(*elm));
for ( ; pathIter; ++pathIter)
{
Scope sco(*pathIter);
if (sco.isRoot())
{
VERIFY_ERROR (NO_PARENT_SCOPE, sco.getParent() );
PlacementMO& top = sco.getTop();
PlacementMO& root = sess->getRoot();
CHECK (isSameObject (top,root));
}
else
{
Scope parent = sco.getParent();
PlacementMO& top = sco.getTop();
Scope parentsScope = Scope::containing(top);
PlacementMO& topsTop = sess->getScope(top); ///////////////////TODO impact of Binding a Sequence? see Ticket #311
CHECK (topsTop == parentsScope);
CHECK (isSameObject (topsTop, parentsScope.getTop()));
}}}
}
};
/** Register this test class... */
LAUNCHER (PlacementScope_test, "function session");
}}}}// namespace steam::mobject::session::test