From cbdc53e2d8e723e8d501a2350e0ad1d3fe36d5cd Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 30 Jul 2016 23:22:46 +0200 Subject: [PATCH] define a TreeMutator binding for our test::Opaque type OMG, this is intricate stuff.... Questionable if anyone (other than myself) will be able to get those bindings right??? Probably we'll need yet another abstraction layer to handle the most common binding situations automatically, so that people can use the diff framework without intricate knowledge of TreeMutator construction. --- src/lib/diff/tree-diff-traits.hpp | 30 ++++- .../diff-virtualised-application-test.cpp | 119 +++++++++++++++++- 2 files changed, 143 insertions(+), 6 deletions(-) diff --git a/src/lib/diff/tree-diff-traits.hpp b/src/lib/diff/tree-diff-traits.hpp index 553549fe4..bd72fe073 100644 --- a/src/lib/diff/tree-diff-traits.hpp +++ b/src/lib/diff/tree-diff-traits.hpp @@ -43,6 +43,7 @@ #include "lib/diff/tree-mutator.hpp" #include "lib/diff/diff-mutable.hpp" +#include "lib/null-value.hpp" #include "lib/util.hpp" #include @@ -82,13 +83,40 @@ namespace diff{ * @see tree-diff-application.hpp * @see DiffVirtualisedApplication_test */ - template + template struct TreeMutatorSizeTraits { enum { siz = 200 }; }; + constexpr size_t + treeMutatorSize (...) + { + return 0; + } + + + template + constexpr T* + getSelector() + { + return static_cast (nullptr); + } + + template + struct defines_custom_BufferSize + { + enum { value = 0 < treeMutatorSize (getSelector()) }; + }; + + + template + struct TreeMutatorSizeTraits> > + { + enum { siz = treeMutatorSize (getSelector()) }; + }; + diff --git a/tests/library/diff/diff-virtualised-application-test.cpp b/tests/library/diff/diff-virtualised-application-test.cpp index 491d2e318..70960ef70 100644 --- a/tests/library/diff/diff-virtualised-application-test.cpp +++ b/tests/library/diff/diff-virtualised-application-test.cpp @@ -24,6 +24,7 @@ #include "lib/test/run.hpp" #include "lib/format-util.hpp" #include "lib/diff/tree-diff-application.hpp" +#include "lib/diff/test-mutation-target.hpp" #include "lib/iter-adapter-stl.hpp" #include "lib/time/timevalue.hpp" #include "lib/format-cout.hpp" //////////TODO necessary? @@ -41,6 +42,7 @@ using util::join; using util::_Fmt; using util::join; using std::unique_ptr; +using std::make_unique; using std::string; using std::vector; using lib::time::Time; @@ -76,6 +78,9 @@ namespace test{ */ class Opaque { + idi::EntryID key_; + string type_ = Rec::TYPE_NIL; + int alpha_ = -1; string beta_ = "NIL"; double gamma_ = -1; @@ -88,10 +93,46 @@ namespace test{ public: Opaque() { } + explicit + Opaque (string keyID) + : key_(keyID) + { } + + explicit + Opaque (idi::BareEntryID id) + : key_(id) + { } + + Opaque (Opaque const& o) + : key_(o.key_) + , type_(o.type_) + , alpha_(o.alpha_) + , beta_(o.beta_) + , gamma_(o.gamma_) + , delta_() + , nestedObj_(o.nestedObj_) + , nestedData_(o.nestedData_) + { + if (o.delta_) + delta_.reset(new Opaque(*o.delta_)); + } + + Opaque& + operator= (Opaque const& o) + { + if (&o != this) + { + Opaque tmp(o); + swap (*this, tmp); + } + return *this; + } + + operator string() const { return _Fmt{"%s (α:%d β:%s γ:%7.5f δ:%s\n......|nested:%s\n......|data:%s\n )"} - % idi::instanceTypeID (this) + % identity() % alpha_ % beta_ % gamma_ @@ -101,15 +142,85 @@ namespace test{ ; } + string + identity() const + { + string symbol = key_.getSym() + (isTyped()? "≺"+type_+"≻" : ""); + return lib::idi::format::instance_hex_format(symbol, key_.getHash()); + } + + bool + isTyped() const + { + return Rec::TYPE_NIL != type_; + } + + void buildMutator (TreeMutator::Handle buff) { - UNIMPLEMENTED("construct the concrete Binding, using the TreeMutator::Builder DSL"); buff.create ( TreeMutator::build() .attach (collection(nestedData_) - )); + .isApplicableIf ([&](GenNode const& spec) -> bool + { + return not spec.isNamed(); // »Selector« : accept anything unnamed value-like + }) + .assignElement ([&](string& target, GenNode const& spec) -> bool + { + target = render(spec.data); + return true; + })) + .attach (collection(nestedObj_) + .isApplicableIf ([&](GenNode const& spec) -> bool + { + return type_ == spec.data.recordType(); // »Selector« : require object-like sub scope with matching typeID + }) + .constructFrom ([&](GenNode const& spec) -> Opaque + { + return Opaque{spec.idi}; + }) + .matchElement ([&](GenNode const& spec, Opaque const& elm) -> bool + { + return spec.idi == elm.key_; + }) + .buildChildMutator ([&](Opaque& target, GenNode::ID const& subID, TreeMutator::Handle buff) -> bool + { + if (target.key_ != subID) return false; // require match on already existing child object + target.buildMutator (buff); // delegate to child to build nested TreeMutator + return true; + })) + .change("type", [&](string typeID) + { + type_ = typeID; + }) + .change("α", [&](int val) + { + alpha_ = val; + }) + .change("β", [&](string val) + { + beta_ = val; + }) + .change("γ", [&](double val) + { + gamma_ = val; + }) + .mutateAttrib("δ", [&](TreeMutator::Handle buff) + { + if (not delta_) + delta_.reset (new Opaque("δ")); + REQUIRE (delta_); + + delta_->buildMutator(buff); + })); } + + friend constexpr size_t + treeMutatorSize (const Opaque*) + { + return 350; + } }; }//(End)Test fixture @@ -120,8 +231,6 @@ namespace test{ - - /***********************************************************************//** * @test Demonstration: apply a structural change to unspecified private * data structures, with the help of an [dynamic adapter](\ref TreeMutator)