Activity-Lang: switch invocation detection to delegated matcher
ActivityMatch inherits privately from the EventMatch object, and is thus able to delegate relevant matching queries, but also to provide high-level special matchers. This new design resolves the ambiguity regarding function arguments. Moreover, we can now record the current sequence-Number as *attribute* in the respective log record (this is the benefit of using structured log entries instead of just a textual log), thereby avoiding the various pitfalls with explicit bracketing sequence-number log entries bottom line: this reworked design seems to be a better fit, even while technically the implementation with the wrapped matcher is somewhat ugly...
This commit is contained in:
parent
ff4acb04d7
commit
25ad461a28
4 changed files with 147 additions and 50 deletions
|
|
@ -415,6 +415,18 @@ namespace test{
|
|||
EventLog& destroy (string text);
|
||||
|
||||
|
||||
/** Qualify the latest entry: set further attribute(s) */
|
||||
template<typename X, typename...ARGS>
|
||||
EventLog&
|
||||
addAttrib (string const& key, X&& initialiser, ARGS&& ...args)
|
||||
{
|
||||
REQUIRE (not isnil (*log_));
|
||||
mutateInPlace (log_->back())
|
||||
.attrib(key,initialiser, std::forward<ARGS>(args)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ==== Iteration ==== */
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace test {
|
|||
CHECK (55 == trap (1.23, Time{FSecs{3,2}}));
|
||||
|
||||
CHECK (detector == "Rec(EventLogHeader| this = ActivityDetector(spectre) ), "
|
||||
"Rec(call| fun = trap, this = ActivityDetector(spectre) |{1.23, 0:00:01.500})"_expect);
|
||||
"Rec(call| fun = trap, this = ActivityDetector(spectre), Seq = 0 |{1.23, 0:00:01.500})"_expect);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -109,14 +109,16 @@ namespace test {
|
|||
|
||||
detector.markSequence();
|
||||
fun(rnd);
|
||||
CHECK (detector.verifyCall ("funny"));
|
||||
CHECK (detector.verifyCall ("funny").arg(rnd));
|
||||
CHECK (detector.verifyInvocation ("funny", Seq(1)));
|
||||
CHECK (detector.verifyInvocation ("funny", Seq(1), rnd));
|
||||
CHECK (detector.verifyInvocation ("funny"));
|
||||
CHECK (detector.verifyInvocation ("funny").arg(rnd));
|
||||
CHECK (detector.verifyInvocation ("funny").seq(2));
|
||||
CHECK (detector.verifyInvocation ("funny").arg(rnd).seq(2));
|
||||
CHECK (detector.verifyInvocation ("funny").seq(2).arg(rnd));
|
||||
CHECK (not detector.verifyInvocation ("bunny"));
|
||||
CHECK (not detector.verifyInvocation ("funny", -rnd));
|
||||
CHECK (not detector.verifyInvocation ("funny", Seq(5)));
|
||||
CHECK (not detector.verifyInvocation ("funny", rnd, Seq(1)));
|
||||
CHECK (not detector.verifyInvocation ("funny").arg());
|
||||
CHECK (not detector.verifyInvocation ("funny").arg(-rnd));
|
||||
CHECK (not detector.verifyInvocation ("funny").seq(5));
|
||||
CHECK (not detector.verifyInvocation ("funny").arg(rnd).seq(1));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -155,12 +155,6 @@ namespace test {
|
|||
|
||||
operator bool() const { return _Parent::operator bool(); }
|
||||
|
||||
template<typename...ARGS>
|
||||
ActivityMatch&
|
||||
arg (ARGS const& ...args)
|
||||
{
|
||||
return delegate (&EventMatch::arg<ARGS...>, args...);
|
||||
}
|
||||
|
||||
// EventMatch& locate (string match);
|
||||
// EventMatch& locateMatch (string regExp);
|
||||
|
|
@ -175,7 +169,7 @@ namespace test {
|
|||
// EventMatch& beforeMatch (string regExp);
|
||||
// EventMatch& beforeEvent (string match);
|
||||
// EventMatch& beforeEvent (string classifier, string match);
|
||||
ActivityMatch& beforeCall (string match) { return delegate (&EventMatch::beforeCall, move(match)); }
|
||||
ActivityMatch& beforeInvocation (string match) { return delegate (&EventMatch::beforeCall, move(match)); }
|
||||
//
|
||||
//
|
||||
// /* query builders to find a match stepping backwards */
|
||||
|
|
@ -186,6 +180,22 @@ namespace test {
|
|||
// EventMatch& afterEvent (string classifier, string match);
|
||||
// EventMatch& afterCall (string match);
|
||||
|
||||
/** qualifier: additionally match the function arguments */
|
||||
template<typename...ARGS>
|
||||
ActivityMatch&
|
||||
arg (ARGS const& ...args)
|
||||
{
|
||||
return delegate (&EventMatch::arg<ARGS...>, args...);
|
||||
}
|
||||
|
||||
/** qualifier: additionally require the indicated sequence number */
|
||||
ActivityMatch&
|
||||
seq (uint seqNr)
|
||||
{
|
||||
_Parent::attrib (MARK_SEQ, util::toString (seqNr));
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename...ARGS>
|
||||
ActivityMatch&
|
||||
|
|
@ -219,12 +229,14 @@ namespace test {
|
|||
|
||||
string id_;
|
||||
EventLog* log_;
|
||||
Seq const* seqNr_;
|
||||
RetVal retVal_;
|
||||
|
||||
public:
|
||||
DiagnosticFun (string id, EventLog& masterLog)
|
||||
DiagnosticFun (string id, EventLog& masterLog, Seq const& seqNr)
|
||||
: id_{id}
|
||||
, log_{&masterLog}
|
||||
, seqNr_{&seqNr}
|
||||
, retVal_{}
|
||||
{ }
|
||||
|
||||
|
|
@ -241,7 +253,8 @@ namespace test {
|
|||
RET
|
||||
operator() (ARGS const& ...args)
|
||||
{
|
||||
log_->call (log_->getID(), id_, args...);
|
||||
log_->call (log_->getID(), id_, args...)
|
||||
.addAttrib (MARK_SEQ, *seqNr_);
|
||||
return *retVal_;
|
||||
}
|
||||
};
|
||||
|
|
@ -305,43 +318,26 @@ namespace test {
|
|||
using SigTypes = typename lib::meta::Prepend<Ret, ArgsX>::Seq;
|
||||
using Functor = typename RebindVariadic<DiagnosticFun, SigTypes>::Type;
|
||||
|
||||
return Functor{id, eventLog_};
|
||||
return Functor{id, eventLog_, invocationSeq_};
|
||||
}
|
||||
|
||||
|
||||
template<typename...ARGS>
|
||||
bool
|
||||
verifyInvocation (string fun, Seq const& seq, ARGS const& ...args)
|
||||
{
|
||||
bool valid = eventLog_.verifyEvent(seq).id(MARK_INC)
|
||||
.beforeCall(fun).arg(args...)
|
||||
.beforeEvent(seq).id(MARK_SEQ);
|
||||
if (not valid)
|
||||
{
|
||||
cerr << "FAIL___Function_invocation___________"
|
||||
<< "\nfunction:"<<fun<<util::joinArgList (args...)
|
||||
<< "\nsequence:"<<seq
|
||||
<< "\n_______Event-Log_____________________\n"
|
||||
<< util::join(eventLog_, "\n")
|
||||
<< "\n───────╼━━━━━━━━╾────────────────────"
|
||||
<< endl;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
template<typename...ARGS>
|
||||
bool
|
||||
verifyInvocation (string fun, ARGS const& ...args)
|
||||
{
|
||||
return verifyInvocation (fun, invocationSeq_, args...);
|
||||
}
|
||||
|
||||
ActivityMatch
|
||||
verifyCall (string fun)
|
||||
verifyInvocation (string fun)
|
||||
{
|
||||
return ActivityMatch{move (eventLog_.verifyCall(fun))};
|
||||
}
|
||||
|
||||
string
|
||||
getLog() const
|
||||
{
|
||||
return "\n_______Event-Log_____________________\n"
|
||||
+ util::join (eventLog_, "\n")
|
||||
+ "\n───────╼━━━━━━━━╾────────────────────"
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
|
|||
|
|
@ -81743,7 +81743,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node COLOR="#338800" CREATED="1690900159528" ID="ID_689193567" MODIFIED="1690918955037" TEXT="Wrapper-Typ verwenden (keinen primitiven Typ)">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1690899920322" ID="ID_67461983" MODIFIED="1690899953072" TEXT="den Einzel-Aufruf mit der Nummer einklammern">
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1690899920322" ID="ID_67461983" MODIFIED="1691967256168" TEXT="den Einzel-Aufruf mit der Sequenz-Nummer markieren">
|
||||
<arrowlink COLOR="#fddadc" DESTINATION="ID_67251959" ENDARROW="Default" ENDINCLINATION="250;-68;" ID="Arrow_ID_996698966" STARTARROW="None" STARTINCLINATION="142;7;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -81782,19 +81783,88 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1691876841330" ID="ID_1105562804" MODIFIED="1691877303577" TEXT="die EventLog-DSL verwendet dafür einen EventMatch(Builder)">
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1691877252417" ID="ID_1984871622" MODIFIED="1691951648662" TEXT="diesen könnte man dekorieren und erweitern">
|
||||
<node COLOR="#435e98" CREATED="1691877252417" ID="ID_1984871622" MODIFIED="1691970627322" TEXT="diesen könnte man dekorieren und erweitern">
|
||||
<linktarget COLOR="#ebfec9" DESTINATION="ID_1984871622" ENDARROW="Default" ENDINCLINATION="-28;49;" ID="Arrow_ID_850495720" SOURCE="ID_761662231" STARTARROW="None" STARTINCLINATION="-304;29;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1691970693305" ID="ID_19920544" MODIFIED="1691970777582" TEXT="nicht ganz einfach...">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...das war vom Design her nicht vorgesehen, und wäre auch nicht ganz einfach zu realisieren; man müßte den EventMatch per CRTP definieren (und damit müßte er Header-only sein, mit den bekannten Folgen für die Größe des Debug-Build)
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1691970806346" ID="ID_1508518510" MODIFIED="1691970872329" TEXT="kann aber den Rückgabewert downcasten">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...denn dies hier ist ein geschlossenes Ökosystem; daher ist sichergestellt, daß *this stets ein ActivityMatch ist
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1691970781106" ID="ID_411948478" MODIFIED="1691970802181" TEXT="verwende abkürzende Notation mit Argument-Forwarding">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1691970876168" ID="ID_1869522832" MODIFIED="1691970894037" TEXT="besser: privat erben und nur die wirklich benötigten Funktionen forwarden">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1690899978840" ID="ID_70827658" MODIFIED="1690899987515" TEXT="einen Funktionsaufruf verifizieren">
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1690900023906" ID="ID_1470650457" MODIFIED="1690918796008" TEXT="markSequence()">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1691967036611" ID="ID_1281722986" MODIFIED="1691967047702" TEXT="was bedeutet das überhaupt?"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1691967048250" ID="ID_1226565848" MODIFIED="1691967068615" TEXT="Ansatz: eine interne Sequenznummer hochsetzen">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1690900069493" ID="ID_917256156" MODIFIED="1690900150148" TEXT="verifyInvocation(fun, Seq(i), args...)">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1691622557790" ID="ID_307528565" MODIFIED="1691622593416" TEXT="lenient arguments?">
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1691967069495" ID="ID_67251959" MODIFIED="1691967245462" TEXT="wie/wo kann die zuverlässig geprüft werden?">
|
||||
<linktarget COLOR="#fddadc" DESTINATION="ID_67251959" ENDARROW="Default" ENDINCLINATION="250;-68;" ID="Arrow_ID_996698966" SOURCE="ID_67461983" STARTARROW="None" STARTINCLINATION="142;7;"/>
|
||||
<icon BUILTIN="help"/>
|
||||
<node COLOR="#5b280f" CREATED="1691967116385" ID="ID_1378863406" MODIFIED="1691967128672" TEXT="erste Idee: zusätzliche Einträge im Log">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1691967129967" ID="ID_904829426" MODIFIED="1691967134017" TEXT="einfach umzusetzen"/>
|
||||
<node CREATED="1691967134523" ID="ID_564127342" MODIFIED="1691967140537" TEXT="aber umständlich in der Handhabung"/>
|
||||
<node CREATED="1691967149276" ID="ID_291271617" MODIFIED="1691967157215" TEXT="und noch schlimmer: nicht eindeutig"/>
|
||||
<node CREATED="1691967141625" ID="ID_1932163820" MODIFIED="1691967147977" TEXT="und müllt das Log zu"/>
|
||||
</node>
|
||||
<node CREATED="1691967161499" ID="ID_368230212" MODIFIED="1691967174065" TEXT="das strukturierte EventLog nutzen">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1691967175689" ID="ID_746233199" MODIFIED="1691967185000" TEXT="Attribut "Seq" einführen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1691967277027" ID="ID_1776684493" MODIFIED="1691967284636" TEXT="Problem: Logging API">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1691967309343" ID="ID_244666662" MODIFIED="1691967318610" TEXT="hat typischerweise bereits eine offene Argumentliste"/>
|
||||
<node CREATED="1691967323722" ID="ID_137219277" MODIFIED="1691967342183" TEXT="man müßte Ergänzungen oder Qualifier nutzen"/>
|
||||
<node CREATED="1691967444533" ID="ID_1942563471" MODIFIED="1691967456767" TEXT="würde dann auf den letzten Eintrag wirken"/>
|
||||
</node>
|
||||
<node CREATED="1691967345874" ID="ID_1693656780" MODIFIED="1691967361490" TEXT="Record-Typ ist eigentlich immutable">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node COLOR="#fe2ee7" CREATED="1691967494714" ID="ID_1135212108" MODIFIED="1691967548854" TEXT="(es gäbe eine Hintertür....)">
|
||||
<font NAME="SansSerif" SIZE="11"/>
|
||||
<icon BUILTIN="smiley-oh"/>
|
||||
</node>
|
||||
<node COLOR="#5b280f" CREATED="1691967521418" ID="ID_1774670461" MODIFIED="1691967534653" TEXT="was sagt uns das??">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1691967188541" ID="ID_190903532" MODIFIED="1691967210908" TEXT="dieses dann per Zusatz-Match prüfbar machen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#5b280f" CREATED="1690900069493" ID="ID_917256156" MODIFIED="1691966998192" TEXT="verifyInvocation(fun, Seq(i), args...)">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node COLOR="#5b280f" CREATED="1691622557790" ID="ID_307528565" MODIFIED="1691966784058" TEXT="lenient arguments?">
|
||||
<icon BUILTIN="help"/>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1691622603918" ID="ID_85657456" MODIFIED="1691622614224" TEXT="manchmal sind die Argumente egal"/>
|
||||
<node CREATED="1691622615042" ID="ID_1956964914" MODIFIED="1691622630486" TEXT="oder man weiß sie nicht einmal..."/>
|
||||
<node CREATED="1691622633914" ID="ID_1240512860" MODIFIED="1691622650564" TEXT="Lösung-1">
|
||||
|
|
@ -81807,7 +81877,24 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="stop-sign"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1691966737035" ID="ID_367147170" MODIFIED="1691966774672" TEXT="Nein! warum überhaupt diese Frage? ⟹ das ganze Design ist schlecht">
|
||||
<icon BUILTIN="stop-sign"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1691966791292" ID="ID_761662231" MODIFIED="1691966961557" TEXT="besser: Matcher verfeinern">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Der Ansatz, alles ein einen Prüf-Aufruf zu packen, ist insgeseamt ungeschickt; genau deshalb wurde doch für das EventLog dieser komplizierte Builder / Verfeinerungs-Ansatz gemacht: darüber kann man ganz natürlich ausdrücken, wenn man etwas über die Argumente speziell geprüft haben möchte, oder eben nicht...
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#ebfec9" DESTINATION="ID_1984871622" ENDARROW="Default" ENDINCLINATION="-28;49;" ID="Arrow_ID_850495720" STARTARROW="None" STARTINCLINATION="-304;29;"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1690900069493" ID="ID_1755197034" MODIFIED="1691967022305" TEXT="verifyInvocation(fun).args(args...).seq(i)">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue