Activity-Lang: ability to hook in a fake implementation

Up to now, the DiagnosticFun mock in ActivityDetector only
created an EventLog entry on invocation and was able to retunr
a canned result value. Yet for the job invocation scenario test,
it would be desirable to hook-in a λ with a fake implementation
into the ExecutionContext. As a further convenience, the
return value is now default initialised, instead of being
marked as uninitialised until invocation of "returning(val)"
This commit is contained in:
Fischlurch 2023-09-01 21:59:25 +02:00
parent fd8716d398
commit f3cf178388
5 changed files with 105 additions and 5 deletions

View file

@ -235,6 +235,15 @@ namespace wrapper {
return *this;
}
/** implant a default-initialised instance of the payload type */
ItemWrapper&
defaultInit()
{
discard();
build (TY());
return *this;
}
operator bool() const
{
return isValid();
@ -306,6 +315,12 @@ namespace wrapper {
return *this;
}
ItemWrapper&
defaultInit() ///< @note just reset for this specialisation
{
reset();
return *this;
}
/* == value access == */
@ -335,7 +350,7 @@ namespace wrapper {
/**
* Fallback-specialisation for `ItemWrapper<void>`.
* @remark This can be relevant when ItemWrapper is used to capture function results,
* yet the given function has return type `void` and used for its side-effects.
* yet the given function has return type `void` and is used for side-effects.
*/
template<>
class ItemWrapper<void>
@ -352,6 +367,12 @@ namespace wrapper {
/** @warning does nothing */
void operator*() const { /* NOP */ }
ItemWrapper&
defaultInit() ///< no effect for this specialisation
{
return *this;
}
};

View file

@ -186,7 +186,7 @@ namespace gear {
{
#define ASSERT_MEMBER_FUNCTOR(_EXPR_, _SIG_) \
static_assert (lib::meta::has_Sig<decltype(_EXPR_), _SIG_>(), \
"Execution-Context: " STRINGIFY(_FUN_) " expect function with signature: " STRINGIFY(_SIG_));
"Execution-Context: " STRINGIFY(_EXPR_) " expect function with signature: " STRINGIFY(_SIG_));
ASSERT_MEMBER_FUNCTOR (EXE::post, Proc(Time, Activity&, EXE&));

View file

@ -71,6 +71,7 @@ namespace test {
simpleUsage();
verifyMockInvocation();
verifyFakeInvocation();
verifyMockJobFunctor();
verifyFakeExeContext();
watch_activation();
@ -149,6 +150,33 @@ namespace test {
/** @test verify a variation of the instrumented functor
* to call into a custom provided _fake implementation._
*/
void
verifyFakeInvocation()
{
ActivityDetector detector;
auto fun = detector.buildDiagnosticFun<int(uint)> ("fakeFun");
uint rnd = rand() % 10000;
CHECK (0 == fun (rnd));
fun.returning(42);
detector.incrementSeq();
CHECK (42 == fun (rnd));
fun.implementedAs ([](uint i){ return -i; });
detector.incrementSeq();
CHECK (-int(rnd) == fun (rnd));
CHECK (detector.verifyInvocation("fakeFun").seq(0)
.beforeInvocation("fakeFun").seq(1)
.beforeInvocation("fakeFun").seq(2));
}
/** @test diagnostic setup to detect a JobFunctor activation
* - the ActivityDetector provides specifically rigged JobFunctor instances
* - these capture all invocations, based on generic invocation logging
@ -389,7 +417,7 @@ namespace test {
CHECK (detector.verifyInvocation("tap-GATE").seq(0).timeArg(tt)
.beforeSeqIncrement(1)
.beforeInvocation("afterGATE").seq(1).timeArg(tt)
.beforeInvocation("after-GATE").seq(1).timeArg(tt)
.beforeInvocation("CTX-tick").seq(1).timeArg(tt));
}
};

View file

@ -268,10 +268,12 @@ namespace test {
class DiagnosticFun
{
using RetVal = lib::wrapper::ItemWrapper<RET>;
using ImplFun = std::function<RET(ARGS...)>;
string id_;
EventLog* log_;
uint const* seqNr_;
ImplFun implFun_;
RetVal retVal_;
public:
@ -279,8 +281,11 @@ namespace test {
: id_{id}
, log_{&masterLog}
, seqNr_{&invocationSeqNr}
, implFun_{}
, retVal_{}
{ }
{
retVal_.defaultInit();
}
/** prepare a response value to return from the mock invocation */
template<typename VAL>
@ -291,6 +296,15 @@ namespace test {
return std::move (*this);
}
/** use the given λ to provide (optional) implementation logic */
template<class FUN>
DiagnosticFun&&
implementedAs (FUN&& customImpl)
{
implFun_ = std::forward<FUN> (customImpl);
return std::move (*this);
}
// default copyable
/** mock function call operator: logs all invocations */
@ -299,7 +313,8 @@ namespace test {
{
log_->call (log_->getID(), id_, args...)
.addAttrib (MARK_SEQ, util::toString(*seqNr_));
return *retVal_;
return implFun_? implFun_(std::forward<ARGS>(args)...)
: *retVal_;
}
operator string() const

View file

@ -80185,6 +80185,42 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1693603368706" ID="ID_1497162884" MODIFIED="1693603379725" TEXT="komplette Aufrufkette verifizieren">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1693603380721" ID="ID_1170059404" MODIFIED="1693603902911" TEXT="geht so nicht, wegen FakeExecutionCtx">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Im ActivityDetector sind normalerweise die ctx-&#955; als reine Logging-Funktionen implementiert; aber die nun konstruierte Ausf&#252;hrungs-Logik setzt fest darauf, da&#223; ein Aufruf von ctx.post() sofort in einen ActivityLang::dispatchChain() umgesetzt wird <i><font size="2" color="#562275">(allerdings nicht wirklich immer, sondern nur in dem Fall, da&#223; wir das GroomingToken halten und die im post() gegebene Zeit die aktuelle Zeit ist)</font></i>
</p>
</body>
</html>
</richcontent>
<arrowlink COLOR="#8f4550" DESTINATION="ID_1373519941" ENDARROW="Default" ENDINCLINATION="-166;-6;" ID="Arrow_ID_1164574930" STARTARROW="None" STARTINCLINATION="191;13;"/>
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1693603571349" ID="ID_1256896805" MODIFIED="1693603880201" TEXT="im vorliegenden Testfall k&#xf6;nnte man eigentlich diesen Aufruf durchreichen...">
<icon BUILTIN="idea"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1693603663534" ID="ID_1373519941" MODIFIED="1693603891817" TEXT="dem steht aber der feste Datentyp entgegen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
<font color="#7b4438" face="Monospaced">FakeExecutionCtx</font>&#160;bzw. die dort verwendete <font color="#7b4438" face="Monospaced">DiagnosticFun</font>, auf die man ja tats&#228;chlich zugreifen k&#246;nnen sollte (um den R&#252;ckgabewert zu manipulieren) &#8212; und das w&#228;re bei einer <font face="Monospaced" color="#2f1687">std::function</font>&#160; nicht mehr m&#246;glich...
</p>
</body>
</html>
</richcontent>
<linktarget COLOR="#8f4550" DESTINATION="ID_1373519941" ENDARROW="Default" ENDINCLINATION="-166;-6;" ID="Arrow_ID_1164574930" SOURCE="ID_1170059404" STARTARROW="None" STARTINCLINATION="191;13;"/>
<icon BUILTIN="broken-line"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689200553782" ID="ID_1346681233" MODIFIED="1689200586861" TEXT="scenario_IOJob">
<icon BUILTIN="flag-yellow"/>