35 #ifndef LIB_DIFF_TEST_MUTATION_TARGET_H 36 #define LIB_DIFF_TEST_MUTATION_TARGET_H 63 using iter_stl::eachElm;
78 identify (
const T*
const entity)
88 renderAttribute (
GenNode const& elm)
90 return elm.idi.getSym()
96 renderChild (
GenNode const& elm)
104 return n.isNamed()? renderAttribute(n)
110 renderRecord (
Rec const& record)
116 + (Rec::TYPE_NIL==record.getType()?
"" : record.getType())
117 + (isnil(record.attribs())?
"" :
"| "+join (
transformIterator (record.attribs(), renderAttribute))+
" ")
118 + (isnil(record.scope())?
"" :
"|{"+join (
transformIterator (record.scope(), renderChild))+
"}")
127 struct StringRenderer
128 :
public Variant<DataValues>::Visitor
130 string representation{
""};
132 #define STRINGIFY_CONTENT(_TY_) \ 133 virtual void handle (_TY_& val) override { representation = util::toString (val); } 135 STRINGIFY_CONTENT (
int)
136 STRINGIFY_CONTENT (int64_t)
137 STRINGIFY_CONTENT (
short)
138 STRINGIFY_CONTENT (
char)
139 STRINGIFY_CONTENT (
bool)
140 STRINGIFY_CONTENT (
double)
141 STRINGIFY_CONTENT (
string)
151 handle (
Rec & rec)
override 153 representation = renderRecord (rec);
157 handle (
RecRef & ref)
override 160 representation = renderRecord (ref);
162 representation = util::BOTTOM_INDICATOR;
166 StringRenderer visitor;
167 unConst(content).accept (visitor);
168 return visitor.representation;
189 using VecG = std::vector<GenNode>;
194 VecG prev_content_{};
198 using iterator =
typename iter_stl::_SeqT<VecG>::Range;
199 using const_iterator =
typename iter_stl::_SeqT<const VecG>::Range;
201 const_iterator begin()
const {
return eachElm(content_); }
202 const_iterator end()
const {
return const_iterator(); }
204 iterator srcIter() {
return eachElm(prev_content_); }
205 iterator lastElm() {
return iterator(VecG::iterator(&content_.back()), content_.end());}
208 friend const_iterator begin (
TestMutationTarget const& target) {
return target.begin(); }
216 initMutation (
string mutatorID)
218 prev_content_.clear();
219 swap (content_, prev_content_);
220 log_.event (
"attachMutator "+mutatorID);
225 inject (
GenNode&& elm,
string operationID)
227 content_.emplace_back (forward<GenNode>(elm));
228 log_.event (operationID, renderNode (content_.back()));
234 while (pos and not pos->matches(targetID))
242 if (!empty() and content_.back().matches(targetID))
245 return search (targetID, eachElm(content_));
249 logSkip (
GenNode const& content)
251 log_.event (
"skipSrc", isnil(content.idi.getSym())? util::BOTTOM_INDICATOR : renderNode(content));
255 logAssignment (
GenNode const& target,
string oldPayload)
257 log_.event (
"assignElm",
_Fmt{
"%s: %s ⤅ %s"}
258 % target.idi.getSym()
264 logMutation (
GenNode const& target)
266 log_.event (
"mutateChild",
_Fmt{
"%s: start mutation...%s"}
267 % target.idi.getSym()
272 logScopeCompletion (iterator processingPos)
274 log_.event (
"completeScope",
_Fmt{
"⤴ scope%s completed / %d waste elm(s)"}
275 % (processingPos?
" NOT":
"")
276 % prev_content_.size());
285 return content_.empty();
303 verify (
string match)
const 305 return getLog().verify(match);
309 verifyMatch (
string regExp)
const 311 return getLog().verifyMatch(regExp);
315 verifyEvent (
string match)
const 317 return getLog().verifyEvent(match);
321 verifyEvent (
string classifier,
string match)
const 323 return getLog().verifyEvent (classifier,match);
327 verifyCall (
string match)
const 329 return getLog().verifyCall(match);
333 ensureNot (
string match)
const 335 return getLog().ensureNot(match);
354 using Iter = TestMutationTarget::iterator;
361 : PAR{forward<PAR> (chain)}
373 pos_ = target_.initMutation (identify(
this));
387 target_.inject (
GenNode{n},
"injectNew");
388 return PAR::injectNew (n);
403 return PAR::matchSrc(n)
413 GenNode const& skippedElm = *pos_;
415 target_.logSkip (skippedElm);
424 bool isSrcMatch = pos_ and n.
matches(*pos_);
427 target_.inject (move(*pos_),
"acceptSrc");
430 return PAR::acceptSrc(n)
438 Iter found = TestMutationTarget::search (ref.idi, pos_);
441 target_.inject (move(*found),
"findSrc");
443 return PAR::findSrc(ref)
451 bool foundTarget =
true;
454 for ( ; pos_; ++pos_)
455 target_.inject (move(*pos_),
"accept_until END");
458 for ( ; pos_ and pos_->isNamed(); ++pos_)
459 target_.inject (move(*pos_),
"accept_until after ATTRIBS");
462 string logMsg{
"accept_until "+spec.idi.getSym()};
463 while (pos_ and not TestWireTap::matchSrc(spec))
465 target_.inject (move(*pos_), logMsg);
468 if (TestWireTap::matchSrc(spec))
470 target_.inject (move(*pos_), logMsg);
476 return PAR::accept_until(spec)
485 Iter targetElm = target_.locate (spec.idi);
488 string logOldPayload{
render(targetElm->data)};
490 target_.logAssignment (*targetElm, logOldPayload);
492 return PAR::assignElm(spec)
501 if (PAR::mutateChild (spec, targetBuff))
505 Iter targetElm = target_.locate (spec.idi);
509 target_.logMutation (*targetElm);
521 target_.logScopeCompletion (pos_);
522 return PAR::completeScope()
523 and isnil(this->pos_);
532 return chainedBuilder<TestWireTap<PAR>> (dummy);
virtual bool completeScope()
verify all our pending (old) source elements where mentioned.
string showContent() const
render payload content for diagnostics
virtual bool assignElm(GenNode const &spec)
locate element already accepted into the target sequence and assign the designated payload value to i...
string render(DataCap const &)
Builder-DSL to create and configure a concrete TreeMutator.
Support for verifying the occurrence of events from unit tests.
Test adapter to watch and verify how the TreeMutator binds to custom tree data structures.
Any copy and copy construction prohibited.
inline string literal This is a marker type to indicate that
Helper to log and verify the occurrence of events.
A front-end for using printf-style formatting.
virtual bool accept_until(GenNode const &spec)
repeatedly accept, until after the designated location
Implementation namespace for support and library code.
Generic functions to build identification schemes.
Lumiera's internal time value datatype.
virtual bool matchSrc(GenNode const &n) override
ensure the next recorded source element matches on a formal level with given spec ...
static Builder< TreeMutator > build()
DSL: start building a custom adapted tree mutator, where the operations are tied by closures or wrapp...
SUB & emplace(SUB &&implementation)
move-construct an instance of a subclass into the opaque buffer
string showSrcBuffer() const
render elements waiting in source buffer to be accepted
Mix-Ins to allow or prohibit various degrees of copying and cloning.
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBu...
Special collection to represent object-like data.
static const Ref END
symbolic ID ref "_END_"
Marker types to indicate a literal string and a Symbol.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
wrapped record reference.
virtual void skipSrc(GenNode const &n) override
skip next recorded src element without touching it
Lumiera error handling (C++ interface).
string instanceTypeID(const TY *const obj)
designation of an distinct object instance
Hash implementation based on a lumiera unique object id (LUID) When invoking the default ctor...
bool matches(GenNode const &o) const
static const Ref ATTRIBS
symbolic ID ref "_ATTRIBS_"
Offset measures a distance in time.
Customisable intermediary to abstract generic tree mutation operations.
virtual bool mutateChild(GenNode const &spec, TreeMutator::Handle targetBuff)
locate the designated target element and build a suitable sub-mutator for this element into the provi...
Duration is the internal Lumiera time metric.
virtual bool findSrc(GenNode const &ref) override
locate designated element and accept it at current position
A time interval anchored at a specific point in time.
auto transformIterator(IT const &src, FUN processingFunc)
Build a TransformIter: convenience free function shortcut, picking up the involved types automaticall...
object-like record of data.
virtual bool injectNew(GenNode const &n) override
record in the test target that a new child element is being inserted at current position ...
generic data element node within a tree
virtual bool acceptSrc(GenNode const &n) override
accept existing element, when matching the given spec