From db1adb63a71f470970013f6cbbcc6e48bb0fe471 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 31 Jul 2023 21:53:16 +0200 Subject: [PATCH] Activity-Lang: draft a diagnostic helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ...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... --- src/lib/meta/variadic-helper.hpp | 4 +- src/lib/test/event-log.hpp | 14 +-- src/lib/wrapper.hpp | 27 ++++- tests/vault/gear/activity-detector-test.cpp | 16 ++- tests/vault/gear/activity-detector.hpp | 109 ++++++++++++++++++-- wiki/thinkPad.ichthyo.mm | 59 ++++++++++- 6 files changed, 204 insertions(+), 25 deletions(-) diff --git a/src/lib/meta/variadic-helper.hpp b/src/lib/meta/variadic-helper.hpp index 23bdda67b..460e9b662 100644 --- a/src/lib/meta/variadic-helper.hpp +++ b/src/lib/meta/variadic-helper.hpp @@ -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 variadic */ template 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 variadic */ template struct StripNullType; diff --git a/src/lib/test/event-log.hpp b/src/lib/test/event-log.hpp index c88042b71..671ba3e07 100644 --- a/src/lib/test/event-log.hpp +++ b/src/lib/test/event-log.hpp @@ -290,12 +290,6 @@ namespace test{ , std::forward(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 diff --git a/src/lib/wrapper.hpp b/src/lib/wrapper.hpp index 6435356ac..2d111dc9f 100644 --- a/src/lib/wrapper.hpp +++ b/src/lib/wrapper.hpp @@ -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`. + * @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 + { + 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 diff --git a/tests/vault/gear/activity-detector-test.cpp b/tests/vault/gear/activity-detector-test.cpp index 6cf059d9b..b0e48063c 100644 --- a/tests/vault/gear/activity-detector-test.cpp +++ b/tests/vault/gear/activity-detector-test.cpp @@ -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("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); } diff --git a/tests/vault/gear/activity-detector.hpp b/tests/vault/gear/activity-detector.hpp index 84741cd40..3efad9b3b 100644 --- a/tests/vault/gear/activity-detector.hpp +++ b/tests/vault/gear/activity-detector.hpp @@ -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 +#include +#include //#include //#include @@ -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 class X, typename...ARGS> + struct _RebindTypeSeq + { + using Type = X; + }; + + template class X + ,template class U + ,typename...ARGS> + struct _RebindTypeSeq> + { + using Type = X; + }; + + } /** @@ -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 + class DiagnosticFun + { + using RetVal = lib::wrapper::ItemWrapper; + + 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 (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 + auto + buildDiagnosticFun (string id) + { + using Ret = typename lib::meta::_Fun::Ret; + using Args = typename lib::meta::_Fun::Args; + using ArgsX = typename lib::meta::StripNullType::Seq; ////////////////////////////////////TICKET #987 : make lib::meta::Types variadic + using SigTypes = typename lib::meta::Prepend::Seq; + using Functor = typename _RebindTypeSeq::Type; + + return Functor{id, eventLog_}; + } + private: }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 26b56a078..6d8280551 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -81627,13 +81627,62 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + + + + + + + + + + + + + + + + + + +

+ stabile Benennung: this = ActivityDetector(ID) +

+ +
+
+
+ + + + + + + + + + + +

+ wieder mal das lästige Problem mit den variadischen Templates: der Argument-Pack ist selber kein Typ, sondern man kann darauf nur matchen +

+ +
+ +
+ + + + + + + - - + +