diff --git a/src/proc/mobject/session/query-focus.cpp b/src/proc/mobject/session/query-focus.cpp index 424c137c6..5bbbf9a73 100644 --- a/src/proc/mobject/session/query-focus.cpp +++ b/src/proc/mobject/session/query-focus.cpp @@ -37,6 +37,16 @@ namespace session { { } + /** discard any state and clear + the current focus path */ + QueryFocus& + QueryFocus::reset () + { + scopes_.clear(); + return *this; + } + + /** attach this QueryFocus to a container-like scope, causing it to \em navigate, changing the current ScopePath as a side-effect diff --git a/src/proc/mobject/session/query-focus.hpp b/src/proc/mobject/session/query-focus.hpp index 2649cf53b..fa8d6343e 100644 --- a/src/proc/mobject/session/query-focus.hpp +++ b/src/proc/mobject/session/query-focus.hpp @@ -45,10 +45,12 @@ namespace session { class QueryFocus { ScopePath scopes_; + /////////////////////////////////////////////////////////////////////////////////////TODO how to integrate the ref-counting handle? public: QueryFocus(); + QueryFocus& reset (); QueryFocus& attach (Scope const&); static QueryFocus push (Scope const&); QueryFocus pop(); @@ -57,16 +59,16 @@ namespace session { ScopePath currentPath() const { return scopes_; } template - void query(); ////////////////////////////////////////////////////////////////TODO obviously needs to return an Iterator + void query() const; ////////////////////////////////////////////////////////////////TODO obviously needs to return an Iterator }; ///////////////////////////TODO currently just fleshing the API template void - QueryFocus::query() + QueryFocus::query() const { - UNIMPLEMENTED ("how the hell do we issue typed queries?????"); + UNIMPLEMENTED ("how the hell do we issue typed queries?????"); ///////////////////////TICKET #352 } diff --git a/tests/components/proc/mobject/query-focus-test.cpp b/tests/components/proc/mobject/query-focus-test.cpp index f3253af4b..d1e621c2d 100644 --- a/tests/components/proc/mobject/query-focus-test.cpp +++ b/tests/components/proc/mobject/query-focus-test.cpp @@ -26,22 +26,24 @@ //#include "proc/mobject/placement-ref.hpp" #include "proc/mobject/session/test-scopes.hpp" #include "proc/mobject/placement-index.hpp" +#include "proc/mobject/session/query-focus.hpp" +#include "proc/mobject/session/scope.hpp" //#include "lib/util.hpp" -//#include -//#include +#include +#include -//using util::isSameObject; -//using lumiera::Time; -//using std::string; -//using std::cout; -//using std::endl; namespace mobject { namespace session { namespace test { + //using util::isSameObject; + //using lumiera::Time; + using std::string; + using std::cout; + using std::endl; /********************************************************************************** @@ -62,11 +64,94 @@ namespace test { // Prepare an (test)Index backing the PlacementRefs PPIdx index = build_testScopes(); -// PMO& root = index->getRoot(); + PMO& root = index->getRoot(); UNIMPLEMENTED ("unit test to cover query focus management"); -//?? ASSERT (0 == index->size()); + QueryFocus theFocus; + theFocus.reset(); + ASSERT (Scope(root) == Scope(theFocus)); + + checkNavigation (theFocus); + + Scope scopePosition = Scope(theFocus); + manipulate_subFocus(); + + QueryFocus currentFocus; + ASSERT (scopePosition == Scope(currentFocus)); + ASSERT (currentFocus == theFocus); + } + + + /** @test move the current focus to various locations + * and discover contents there. */ + void + checkNavigation (QueryFocus& focus) + { + focus.reset(); + ASSERT (Scope(focus).isRoot()); + + PMO& someObj = focus.query(); + // by construction of the test fixture, + // we know this object is root -> ps2 -> ps3 + + ASSERT (Scope(focus).isRoot()); + focus.attach (someObj); + ASSERT (!Scope(focus).isRoot()); + ScopePath path = focus.currentPath(); + ASSERT (someObj == path.getLeaf()); + ASSERT (path.getParent().getParent().isRoot()); + + focus.attach (path.getParent()); + ASSERT (Scope(focus) == path.getParent()); + ASSERT (someObj != Scope(focus)); + ASSERT (path.contains (focus.currentPath())); + ASSERT (focus.currentPath().getParent().isRoot()); + } + + + /** @test side-effect free manipulation of a sub-focus */ + void + manipulate_subFocus() + { + QueryFocus original; + uint num_refs = original.ref_count(); + ASSERT (num_refs > 1); + + QueryFocus subF = QueryFocus::push(); + cout << string(subF) << endl; + ASSERT (subF == original); + + ASSERT ( 1 == subF.ref_count()); + ASSERT (num_refs == original.ref_count()); + + { + QueryFocus subF2 = QueryFocus::push(Scope(subF).getParent()); + ASSERT (subF2 != subF); + ASSERT (subF == original); + cout << string(subF2) << endl; + + Iterator ii = subF2.query(); + while (ii) + { + subF2.attach(*ii); + cout << string(subF2) << endl; + ii = subF2.query(); + } + cout << string(subF2) << "<<<--discovery exhausted" << endl; + + subF2.pop(); + cout << string(subF2) << "<<<--after pop()" << endl; + ASSERT (subF2 == subF); + ASSERT (2 == subF2.ref_count()); + ASSERT (2 == subF.ref_count()); + } + // subF2 went out of scope, but no auto-pop happens + cout << string(subF) << endl; + + ASSERT ( 1 == subF.ref_count()); + ASSERT (num_refs == original.ref_count()); + // when subF goes out of scope now, auto-pop will happen... } }; diff --git a/tests/components/proc/mobject/scope-path-test.cpp b/tests/components/proc/mobject/scope-path-test.cpp index 344e0f215..343104089 100644 --- a/tests/components/proc/mobject/scope-path-test.cpp +++ b/tests/components/proc/mobject/scope-path-test.cpp @@ -72,6 +72,7 @@ namespace test { invalildPath (testPath,startPlacement); check_Identity_and_Copy (startPlacement); navigate (testPath, index); + clear (testPath, index); } @@ -268,6 +269,19 @@ namespace test { ScopePath rootPrefix = commonPrefix (path,refPath); ASSERT (rootPrefix.endsAt (root)); } + + + void + clear (ScopePath& testPath, PPIdx index) + { + ASSERT (path); + PMO rootNode = index->getRoot(); + ASSERT (path.getLeaf() != rootNode); + + path.clear(); + ASSERT (path); + ASSERT (path.getLeaf() == rootNode); + } };