Activity-Lang: draft a diagnostic helper
...for coverage of the Activity-Language, various invocations of unspecific functions must be verified, with the additional twist that the implementation avoids indirections and is thus hard to rig for tests. Solution-Idea: provide a λ-mock to log any invocation into the Event-Log helper, which was created some years ago to trace GUI communication...
This commit is contained in:
parent
26c2e835c3
commit
db1adb63a7
6 changed files with 204 additions and 25 deletions
|
|
@ -70,7 +70,7 @@ namespace meta {
|
|||
* prior to C++11. Unfortunately these trailing NullType
|
||||
* entries do not play well with other variadic defs.
|
||||
* @deprecated when we switch our primary type sequence type
|
||||
* to variadic parameters, this type will be obsoleted.
|
||||
* to variadic parameters, this type will be obsoleted. ////////////////////////////////////TICKET #987 : make lib::meta::Types<TYPES...> variadic
|
||||
*/
|
||||
template<typename...TYPES>
|
||||
struct TySeq
|
||||
|
|
@ -99,7 +99,7 @@ namespace meta {
|
|||
* template definitions.
|
||||
* @note the result type is a TySec, to keep it apart from our
|
||||
* legacy (non-variadic) lib::meta::Types
|
||||
* @deprecated necessary for the transition to variadic sequences
|
||||
* @deprecated necessary for the transition to variadic sequences ////////////////////////////////////TICKET #987 : make lib::meta::Types<TYPES...> variadic
|
||||
*/
|
||||
template<typename SEQ>
|
||||
struct StripNullType;
|
||||
|
|
|
|||
|
|
@ -290,12 +290,6 @@ namespace test{
|
|||
, std::forward<ARGS>(args));
|
||||
}
|
||||
|
||||
string
|
||||
getID() const
|
||||
{
|
||||
return log_->front().get("this");
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
explicit
|
||||
|
|
@ -316,6 +310,14 @@ namespace test{
|
|||
// standard copy operations acceptable
|
||||
|
||||
|
||||
/// @return logID defined with the ctor to distinguish this log instance
|
||||
string
|
||||
getID() const
|
||||
{
|
||||
return log_->front().get("this");
|
||||
}
|
||||
|
||||
|
||||
/** Merge this log into another log, forming a combined log
|
||||
* @param otherLog target to integrate this log's contents into.
|
||||
* @return reference to the merged new log instance
|
||||
|
|
|
|||
|
|
@ -269,8 +269,8 @@ namespace wrapper {
|
|||
discard();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Specialisation of the ItemWrapper to deal with references,
|
||||
* as if they were pointer values. Allows the reference value
|
||||
|
|
@ -332,6 +332,29 @@ 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.
|
||||
*/
|
||||
template<>
|
||||
class ItemWrapper<void>
|
||||
{
|
||||
public:
|
||||
ItemWrapper()
|
||||
{ }
|
||||
|
||||
// using default copy and assignment
|
||||
|
||||
operator bool() const { return true; }
|
||||
bool isValid () const { return true; }
|
||||
void reset () { /* NOP */ }
|
||||
|
||||
/** @warning does nothing */
|
||||
void operator*() const { /* NOP */ }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** allow equality comparison if the wrapped types are comparable */
|
||||
template<typename TY>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@
|
|||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "activity-detector.hpp"
|
||||
//#include "lib/time/timevalue.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
//#include "lib/format-cout.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
|
||||
|
|
@ -46,7 +47,8 @@ namespace test {
|
|||
|
||||
// using lib::time::FrameRate;
|
||||
// using lib::time::Offset;
|
||||
// using lib::time::Time;
|
||||
using lib::time::Time;
|
||||
using lib::time::FSecs;
|
||||
|
||||
|
||||
|
||||
|
|
@ -77,7 +79,15 @@ namespace test {
|
|||
void
|
||||
simpleUsage()
|
||||
{
|
||||
ActivityDetector spectre;
|
||||
ActivityDetector detector("spectre");
|
||||
|
||||
auto trap = detector.buildDiagnosticFun<int(double,Time)>("trap")
|
||||
.returning(55);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@
|
|||
|
||||
#include "vault/common.hpp"
|
||||
//#include "lib/test/test-helper.hpp"
|
||||
#include "lib/test/event-log.hpp"
|
||||
|
||||
//#include "steam/play/dummy-play-connection.hpp"
|
||||
//#include "steam/fixture/node-graph-attachment.hpp"
|
||||
//#include "steam/fixture/segmentation.hpp"
|
||||
|
|
@ -58,10 +60,16 @@
|
|||
//#include "lib/time/timevalue.hpp"
|
||||
//#include "lib/diff/gen-node.hpp"
|
||||
//#include "lib/linked-elements.hpp"
|
||||
#include "lib/meta/variadic-helper.hpp"
|
||||
#include "lib/wrapper.hpp"
|
||||
#include "lib/format-util.hpp"
|
||||
//#include "lib/itertools.hpp"
|
||||
//#include "lib/depend.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
//#include <tuple>
|
||||
//#include <map>
|
||||
|
||||
|
|
@ -70,19 +78,36 @@ namespace vault{
|
|||
namespace gear {
|
||||
namespace test {
|
||||
|
||||
using std::string;
|
||||
// using std::make_tuple;
|
||||
// using lib::diff::GenNode;
|
||||
// using lib::diff::MakeRec;
|
||||
// using lib::time::TimeValue;
|
||||
// using lib::time::Time;
|
||||
// using lib::HashVal;
|
||||
// using util::isnil;
|
||||
using util::isnil;
|
||||
// using util::isSameObject;
|
||||
// using fixture::Segmentation;
|
||||
// using vault::RealClock;
|
||||
// using vault::gear::Job;
|
||||
// using vault::gear::JobClosure;
|
||||
|
||||
namespace {
|
||||
template<template<typename...> class X, typename...ARGS>
|
||||
struct _RebindTypeSeq
|
||||
{
|
||||
using Type = X<ARGS...>;
|
||||
};
|
||||
|
||||
template<template<typename...> class X
|
||||
,template<typename...> class U
|
||||
,typename...ARGS>
|
||||
struct _RebindTypeSeq<X, U<ARGS...>>
|
||||
{
|
||||
using Type = X<ARGS...>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -92,15 +117,85 @@ namespace test {
|
|||
class ActivityDetector
|
||||
: util::NonCopyable
|
||||
{
|
||||
void* zombiePoolFactor_;
|
||||
using EventLog = lib::test::EventLog;
|
||||
|
||||
EventLog eventLog_;
|
||||
|
||||
/**
|
||||
* A Mock functor, logging all invocations into the EventLog
|
||||
*/
|
||||
template<typename RET, typename...ARGS>
|
||||
class DiagnosticFun
|
||||
{
|
||||
using RetVal = lib::wrapper::ItemWrapper<RET>;
|
||||
|
||||
string id_;
|
||||
EventLog* log_;
|
||||
RetVal retVal_;
|
||||
|
||||
public:
|
||||
DiagnosticFun (string id, EventLog& masterLog)
|
||||
: id_{id}
|
||||
, log_{&masterLog}
|
||||
, retVal_{}
|
||||
{ }
|
||||
|
||||
/** prepare a response value to return from the mock invocation */
|
||||
DiagnosticFun&&
|
||||
returning (RET&& riggedResponse)
|
||||
{
|
||||
retVal_ = std::forward<RET> (riggedResponse);
|
||||
return std::move (*this);
|
||||
}
|
||||
|
||||
/** mock function call operator: logs all invocations */
|
||||
RET
|
||||
operator() (ARGS const& ...args)
|
||||
{
|
||||
log_->call (log_->getID(), id_, args...);
|
||||
return *retVal_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
/* == walking deadline implementation == */
|
||||
|
||||
ActivityDetector()
|
||||
: zombiePoolFactor_{}
|
||||
ActivityDetector(string id)
|
||||
: eventLog_{"ActivityDetector" + (isnil (id)? string{}: "("+id+")")}
|
||||
{ }
|
||||
|
||||
operator string() const
|
||||
{
|
||||
return util::join (eventLog_);
|
||||
}
|
||||
|
||||
void
|
||||
clear(string newID)
|
||||
{
|
||||
if (isnil (newID))
|
||||
eventLog_.clear();
|
||||
else
|
||||
eventLog_.clear (newID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic testing helper: build a λ-mock, logging all invocations
|
||||
* @tparam SIG signature of the functor to be generated
|
||||
* @param id human readable ID, to designate invocations in the log
|
||||
* @return a function object with signature #SIG
|
||||
*/
|
||||
template<typename SIG>
|
||||
auto
|
||||
buildDiagnosticFun (string id)
|
||||
{
|
||||
using Ret = typename lib::meta::_Fun<SIG>::Ret;
|
||||
using Args = typename lib::meta::_Fun<SIG>::Args;
|
||||
using ArgsX = typename lib::meta::StripNullType<Args>::Seq; ////////////////////////////////////TICKET #987 : make lib::meta::Types<TYPES...> variadic
|
||||
using SigTypes = typename lib::meta::Prepend<Ret, ArgsX>::Seq;
|
||||
using Functor = typename _RebindTypeSeq<DiagnosticFun, SigTypes>::Type;
|
||||
|
||||
return Functor{id, eventLog_};
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -81627,13 +81627,62 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689204967974" ID="ID_284088835" MODIFIED="1690070044262" TEXT="ActivityDetector">
|
||||
<linktarget COLOR="#794f4b" DESTINATION="ID_284088835" ENDARROW="Default" ENDINCLINATION="-685;-107;" ID="Arrow_ID_1213725911" SOURCE="ID_1647246120" STARTARROW="None" STARTINCLINATION="518;48;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689204985122" ID="ID_1020676746" MODIFIED="1689204995475" TEXT="Rahmen schaffen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689205014901" ID="ID_221497246" MODIFIED="1689205024996" TEXT="Instantiierung und Lebenszyklus">
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1689204985122" ID="ID_1020676746" MODIFIED="1690832427037" TEXT="Rahmen schaffen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1689205014901" ID="ID_221497246" MODIFIED="1690832378644" TEXT="Instantiierung und Lebenszyklus">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1690817530037" ID="ID_497096743" MODIFIED="1690832373134" TEXT="kopierbares Objekt auf dem Stack">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1690817567303" ID="ID_258782505" MODIFIED="1690832374652" TEXT="default: this = ActivityDetector">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1690817626368" ID="ID_865927183" MODIFIED="1690832375691" TEXT="operator string() ⟼ join (event log)">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1689205007909" ID="ID_403603899" MODIFIED="1690832380383" TEXT="EventLog einbinden">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1690832456039" ID="ID_314321104" MODIFIED="1690832525330">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
stabile Benennung: <font color="#1c5d6a" face="Monospaced">this = ActivityDetector(ID)</font>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1690832398754" ID="ID_864386000" MODIFIED="1690832423318" TEXT="logging mock-λ">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1690832539878" ID="ID_1163728085" MODIFIED="1690832566800" TEXT="Problem: brauche einen generischen Funktor mit vorgegebener Signatur">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1690832634093" ID="ID_1752068820" MODIFIED="1690832811893" TEXT="Problem²: _Fun liefert Types<ARGS...>">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1690832673285" ID="ID_1336668998" MODIFIED="1690832758349" TEXT="daraus kann ich nicht ohne Weiteres einen Funktions-Operator gewinnen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
wieder mal das lästige Problem mit den variadischen Templates: der Argument-Pack ist selber kein Typ, sondern man kann darauf nur matchen
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1690832692447" ID="ID_1143189958" MODIFIED="1690832715493" TEXT="Lösung: generisches Argument-Pack-Rebinding">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1690832761614" ID="ID_1920220300" MODIFIED="1690832775036" TEXT="Template-Template-Parameter">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1690832776060" ID="ID_135731051" MODIFIED="1690832801676" TEXT="X<ARGS...> ⟼ U<ARGS...>"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1690832821366" ID="ID_958989562" MODIFIED="1690832834253" TEXT="als generisches Util extrahieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689205007909" ID="ID_403603899" MODIFIED="1689205011845" TEXT="EventLog einbinden">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1689205029658" ID="ID_1144318045" MODIFIED="1689205033146" TEXT="Verifikationen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue