/* PlacementRef(Test) - generic reference to a Placement within the Session Copyright (C) Lumiera.org 2009, Hermann Vosseler 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. * *****************************************************/ #include "lib/test/run.hpp" #include "lib/test/test-helper.hpp" #include "proc/mobject/placement.hpp" #include "proc/mobject/placement-ref.hpp" #include "proc/mobject/session/placement-index.hpp" #include "proc/mobject/session/session-service-mock-index.hpp" #include "proc/mobject/explicitplacement.hpp" #include "proc/mobject/test-dummy-mobject.hpp" #include "lib/time/timevalue.hpp" #include "lib/util.hpp" #include using util::isSameObject; using std::string; using std::cout; using std::endl; namespace proc { namespace mobject { namespace session { namespace test { using namespace mobject::test; typedef TestPlacement PSub; typedef PlacementMO::ID P_ID; /***********************************************************************//** * @test properties and behaviour of the reference-mechanism for Placements. * We create an mock placement index and install it to be used * by all PlacementRef instances while conducting this test. * Then we add two dummy placements and create some * references to conduct placement operations * through these references. * @see mobject::Placement * @see mobject::MObject#create * @see mobject::Placement#addPlacement * @see mobject::Placement#resolve */ class PlacementRef_test : public Test { virtual void run (Arg) { PSub testPlacement1(*new TestSubMO21); PSub testPlacement2(*new TestSubMO21); lib::time::Time twoSec(0,2); testPlacement2.chain (twoSec); // define start time of Placement-2 to be at t=2sec // Prepare an (test)Index backing the PlacementRefs PPIdx index = SessionServiceMockIndex::install(); PMO& root = index->getRoot(); P_ID id1 = index->insert (testPlacement1, root); P_ID tmpID = index->insert (testPlacement2, root); CHECK (2 == index->size()); // References to the "live" placements within our test index PMO& p1 = index->find(id1); PMO& p2 = index->find(tmpID); PlacementMO::Id id2 = p2.recastID(); CHECK (id2); CHECK (id2 != p1.getID()); // create placement refs PlacementRef ref1 (p1); PlacementRef ref2 (id2); PlacementRef refX (ref2); CHECK (ref1); CHECK (ref2); CHECK (refX); CHECK (ref1 != ref2); CHECK (ref2 == refX); // indeed a "reference": resolves to the same memory location CHECK (isSameObject (p1, *ref1)); CHECK (isSameObject (p2, *ref2)); CHECK (isSameObject (p2, *refX)); cout << string(*ref1) << endl; cout << string(*ref2) << endl; cout << string(*refX) << endl; // PlacementRef mimics placement behaviour ref1->specialAPI(); CHECK (2 == ref1.use_count()); CHECK (2 == ref2.use_count()); ExplicitPlacement exPla = refX.resolve(); CHECK (exPla.time == twoSec); // indeed get back the time we set on p2 above CHECK (3 == ref2.use_count()); // exPla shares ownership with p2 CHECK (index->contains(ref1)); // ref can stand-in for a placement-ID CHECK (sizeof(id2) == sizeof(ref2)); // (and is actually implemented based on an ID) // assignment on placement refs refX = ref1; CHECK (ref1 != ref2); CHECK (ref1 == refX); CHECK (ref2 != refX); // re-assignment with a new placement refX = p2; CHECK (refX == ref2); CHECK (isSameObject (*refX, p2)); refX = p1.getID(); CHECK (refX == ref1); CHECK (refX != ref2); CHECK (isSameObject (*refX, p1)); LumieraUid luid2 (p2.getID().get()); refX = luid2; // assignment works even based on a plain LUID ref2 = ref1; ref1 = refX; // dynamic type check when downcasting CHECK (isSameObject (p1, *ref2)); CHECK (isSameObject (p2, *ref1)); refX = ref2; ref2 = ref1; ref1 = refX; CHECK (isSameObject (p1, *ref1)); CHECK (isSameObject (p1, *refX)); CHECK (isSameObject (p2, *ref2)); CHECK (ref1 != ref2); CHECK (ref1 == refX); CHECK (ref2 != refX); // resolution is indeed "live", we see changes to the referred placement CHECK (refX.resolve().time == lib::time::Time::MIN); p1.chain = p2.chain; // do a change on the placement within index.... CHECK (refX.resolve().time == twoSec); // now we get the time tie we originally set on p2 CHECK (p1.getID() != p2.getID()); // but the instance identities are still unaltered CHECK (2 == ref1.use_count()); CHECK (3 == ref2.use_count()); // one more because of shared ownership with exPla // actively removing p2 invalidates the other refs to index->remove (ref1); CHECK (!ref1); // checks invalidity without throwing CHECK (!refX); VERIFY_ERROR(NOT_IN_SESSION, *ref1 ); // deliberately create an invalid PlacementRef PlacementRef bottom; CHECK (!bottom); VERIFY_ERROR(BOTTOM_PLACEMENTREF, *bottom ); VERIFY_ERROR(BOTTOM_PLACEMENTREF, bottom->specialAPI() ); VERIFY_ERROR(BOTTOM_PLACEMENTREF, bottom.resolve() ); //consistency check; then reset PlacementRef index to default CHECK (1 == index->size()); CHECK (index->isValid()); index.reset(); } }; /** Register this test class... */ LAUNCHER (PlacementRef_test, "unit session"); }}}} // namespace proc::mobject::session::test