2023-07-13 01:51:21 +02:00
/*
ACTIVITY - DETECTOR . hpp - test scaffolding to observe activities within the scheduler
Copyright ( C ) Lumiera . org
2023 , Hermann Vosseler < Ichthyostega @ web . de >
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation ; either version 2 of
the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
/** @file activity-detector.hpp
* * Diagnostic setup to instrument and observe \ ref Activity activations .
* * The [ Scheduler ] ( \ ref scheduler . hpp ) powering the Lumiera render engine
* * is implemented in terms of Activities , which can be time - bound and depend
* * on each other . For performance reasons , these _operational atoms_ must be
* * implemented as a tightly knit network of lightweight POD records without
* * much indirection . This setup poses a challenge for unit tests and similar
* * white box testing , due to the lack of a managed platform and any further
* * means of indirection and extension . As a remedy , a set of preconfigured
* * _detector Activity records_ is provided , which drop off event log messages
* * by side effect . These detector probes can be wired in as decorators into
2023-08-15 02:23:40 +02:00
* * an otherwise valid Activity - Term , allowing to watch and verify patterns
2023-09-03 01:50:50 +02:00
* * of invocation .
2023-08-15 02:23:40 +02:00
* *
* * # Usage
* *
* * An ActivityDetector instance can be created in local storage to get an arsenal
* * of probing tools and detectors , which are internally wired to record activation
* * into an lib : : test : : EventLog embedded into the ActivityDetector instance . A
* * _verification DSL_ is provided , internally relying on the building blocks and
* * the chained - search mechanism known from the EventLog . To distinguish similar
* * invocations and activations , a common _sequence number_ is maintained within
* * the ActivityDetector instance , which can be incremented explicitly . All
* * relevant events also capture the current sequence number as an attribute
* * of the generated log record .
* *
* * # # Observation tools
* * - ActivityDetector : : buildDiadnosticFun ( id ) generates a functor object with
* * _arbitrary signature , _ which records any invocation and arguments .
* * The corresponding verification matcher is # verifyInvocation ( id )
2023-09-03 01:50:50 +02:00
* * - ActivityDetector : : buildMockJobFunctor ( id ) a JobFunctor implementation
* * suitably rigged to record invocations and arguments
* * - ActivityDetector : : buildActivationProbe a debugging Activity to record activation
* * - ActivityDetector : : insertActivationTap hooks this Activation - Probe before an
* * existing Activity - connection , so that passing on the activation can be detected
* * - ActivityDetector : : watchGate rig a ` GATE ` activity by prepending and appending
* * an Activation - Probe , so that both incoming and outgoing activations can be traced
* * - ActivityDetector : : executionCtx test setup of the execution environment abstraction
* * for performing chains of Activities ; it provides the expected λ - functions as
* * instances of ActivityDetctor : : DiagnosticFun , so that any invocation is recorded
2023-08-15 02:23:40 +02:00
* *
2023-07-13 01:51:21 +02:00
* * @ see SchedulerActivity_test
2023-09-03 01:50:50 +02:00
* * @ see ActivityDetector_test
2023-08-15 02:23:40 +02:00
* * @ see EventLog_test ( demonstration of EventLog capbabilities )
2023-07-13 01:51:21 +02:00
*/
# ifndef VAULT_GEAR_TEST_ACTIVITY_DETECTOR_H
# define VAULT_GEAR_TEST_ACTIVITY_DETECTOR_H
# include "vault/common.hpp"
2023-08-29 02:18:07 +02:00
# include "lib/test/test-helper.hpp"
2023-07-31 21:53:16 +02:00
# include "lib/test/event-log.hpp"
2023-08-15 17:18:30 +02:00
# include "vault/gear/job.h"
# include "vault/gear/activity.hpp"
2023-08-15 18:52:51 +02:00
# include "vault/gear/nop-job-functor.hpp"
# include "lib/time/timevalue.hpp"
2023-07-31 21:53:16 +02:00
# include "lib/meta/variadic-helper.hpp"
2023-08-15 18:52:51 +02:00
# include "lib/meta/function.hpp"
2023-07-31 21:53:16 +02:00
# include "lib/wrapper.hpp"
# include "lib/format-util.hpp"
# include "lib/util.hpp"
2023-07-13 01:51:21 +02:00
2023-07-31 21:53:16 +02:00
# include <functional>
# include <utility>
# include <string>
2023-08-15 18:52:51 +02:00
# include <deque>
2023-07-13 01:51:21 +02:00
namespace vault {
namespace gear {
namespace test {
2023-07-31 21:53:16 +02:00
using std : : string ;
2023-08-31 23:55:42 +02:00
using std : : function ;
2023-08-15 18:52:51 +02:00
using lib : : time : : TimeValue ;
2023-08-18 04:00:21 +02:00
using lib : : time : : Time ;
2023-08-20 02:39:57 +02:00
using lib : : time : : FSecs ;
using lib : : time : : Offset ;
2023-08-01 14:52:20 +02:00
using lib : : meta : : RebindVariadic ;
2023-07-31 21:53:16 +02:00
using util : : isnil ;
2023-08-13 20:49:30 +02:00
using std : : forward ;
using std : : move ;
2023-07-13 01:51:21 +02:00
2023-08-15 20:03:01 +02:00
namespace { // Diagnostic markers
2023-08-14 19:22:18 +02:00
const string MARK_INC { " IncSeq " } ;
2023-08-01 17:53:42 +02:00
const string MARK_SEQ { " Seq " } ;
2023-08-15 20:03:01 +02:00
2023-08-18 04:00:21 +02:00
using SIG_JobDiagnostic = void ( Time , int32_t ) ;
2023-08-15 20:03:01 +02:00
const size_t JOB_ARG_POS_TIME = 0 ;
2023-08-17 19:37:38 +02:00
2023-08-18 04:00:21 +02:00
const string CTX_POST { " CTX-post " } ;
const string CTX_WORK { " CTX-work " } ;
const string CTX_DONE { " CTX-done " } ;
const string CTX_TICK { " CTX-tick " } ;
2023-08-20 02:39:57 +02:00
2023-10-21 01:01:00 +02:00
Offset POLL_WAIT_DELAY { FSecs ( 1 ) } ;
2023-09-01 19:23:27 +02:00
Time SCHED_TIME_MARKER { 555 , 5 } ; ///< marker value for "current scheduler time" used in tests
2023-08-01 17:53:42 +02:00
}
2023-08-13 20:49:30 +02:00
class ActivityDetector ;
2023-08-15 02:23:40 +02:00
/**
* @ internal ongoing evaluation and match of observed activities .
* @ remark this temporary object provides a builder API for creating
* chained verifications , similar to the usage of lib : : test : : EventLog .
* Moreover , it is convertible to ` bool ` to retrieve the verification result .
*/
2023-08-13 20:49:30 +02:00
class ActivityMatch
: private lib : : test : : EventMatch
{
using _Parent = lib : : test : : EventMatch ;
ActivityMatch ( lib : : test : : EventMatch & & matcher )
: _Parent { move ( matcher ) }
{ }
friend class ActivityDetector ;
public :
// standard copy acceptable
2023-08-15 02:23:40 +02:00
/** final evaluation of the verification query,
* usually triggered from the unit test ` CHECK ( ) ` .
* @ note failure cause is printed to STDERR .
*/
2023-08-13 20:49:30 +02:00
operator bool ( ) const { return _Parent : : operator bool ( ) ; }
2023-09-03 01:50:50 +02:00
/* query builder(s) to find a match stepping forwards */
2023-08-13 23:42:04 +02:00
ActivityMatch & beforeInvocation ( string match ) { return delegate ( & EventMatch : : beforeCall , move ( match ) ) ; }
2023-09-03 01:50:50 +02:00
// more here...
/* query builders to find a match stepping backwards */
2023-08-15 02:23:40 +02:00
ActivityMatch & afterInvocation ( string match ) { return delegate ( & EventMatch : : afterCall , move ( match ) ) ; }
2023-09-03 01:50:50 +02:00
// more here...
2023-08-13 20:49:30 +02:00
2023-08-13 23:42:04 +02:00
/** 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 ;
}
2023-08-15 02:23:40 +02:00
/** special query to match an increment of the sequence number */
2023-08-14 19:22:18 +02:00
ActivityMatch &
beforeSeqIncrement ( uint seqNr )
{
_Parent : : beforeEvent ( MARK_INC , util : : toString ( seqNr ) ) ;
return * this ;
}
2023-08-15 20:03:01 +02:00
ActivityMatch &
afterSeqIncrement ( uint seqNr )
{
_Parent : : afterEvent ( MARK_INC , util : : toString ( seqNr ) ) ;
return * this ;
}
/** qualifier: additionally match the nominal time argument of JobFunctor invocation */
ActivityMatch &
2023-08-19 17:48:38 +02:00
timeArg ( Time const & time )
2023-08-15 20:03:01 +02:00
{
2023-08-18 04:00:21 +02:00
return delegate ( & EventMatch : : argPos < Time const & > , size_t ( JOB_ARG_POS_TIME ) , time ) ;
2023-08-15 20:03:01 +02:00
}
2023-08-14 19:22:18 +02:00
2023-08-15 02:23:40 +02:00
2023-08-13 20:49:30 +02:00
private :
2023-08-15 02:23:40 +02:00
/** @internal helper to delegate to the inherited matcher building blocks
* @ note since ActivityMatch can only be created by ActivityDetector ,
* we can be sure the EventMatch reference returned from these calls
* is actually a reference to ` * this ` , and can thus be downcasted .
* */
2023-08-13 20:49:30 +02:00
template < typename . . . ARGS >
ActivityMatch &
delegate ( _Parent & ( _Parent : : * fun ) ( ARGS . . . ) , ARGS & & . . . args )
{
return static_cast < ActivityMatch & > (
( this - > * fun ) ( forward < ARGS > ( args ) . . . ) ) ;
}
} ;
2023-07-13 01:51:21 +02:00
2023-09-03 01:50:50 +02:00
2023-07-13 01:51:21 +02:00
/**
* Diagnostic context to record and evaluate activations within the Scheduler .
2023-08-15 02:23:40 +02:00
* The provided tools and detectors are wired back internally , such as to record
* any observations into an lib : : test : : EventLog instance . Thus , after performing
* rigged functionality , the expected activities and their order can be verified .
* @ see ActivityDetector_test
2023-07-13 01:51:21 +02:00
*/
class ActivityDetector
: util : : NonCopyable
{
2023-07-31 21:53:16 +02:00
using EventLog = lib : : test : : EventLog ;
EventLog eventLog_ ;
2023-08-15 02:23:40 +02:00
uint invocationSeq_ ;
2023-07-31 21:53:16 +02:00
/**
* A Mock functor , logging all invocations into the EventLog
*/
template < typename RET , typename . . . ARGS >
class DiagnosticFun
{
using RetVal = lib : : wrapper : : ItemWrapper < RET > ;
2023-09-01 21:59:25 +02:00
using ImplFun = std : : function < RET ( ARGS . . . ) > ;
2023-07-31 21:53:16 +02:00
string id_ ;
EventLog * log_ ;
2023-08-15 02:23:40 +02:00
uint const * seqNr_ ;
2023-09-01 21:59:25 +02:00
ImplFun implFun_ ;
2023-07-31 21:53:16 +02:00
RetVal retVal_ ;
public :
2023-08-15 02:23:40 +02:00
DiagnosticFun ( string id , EventLog & masterLog , uint const & invocationSeqNr )
2023-07-31 21:53:16 +02:00
: id_ { id }
, log_ { & masterLog }
2023-08-15 02:23:40 +02:00
, seqNr_ { & invocationSeqNr }
2023-09-01 21:59:25 +02:00
, implFun_ { }
2023-07-31 21:53:16 +02:00
, retVal_ { }
2023-09-01 21:59:25 +02:00
{
retVal_ . defaultInit ( ) ;
}
2023-07-31 21:53:16 +02:00
/** prepare a response value to return from the mock invocation */
2023-08-01 17:53:42 +02:00
template < typename VAL >
2023-07-31 21:53:16 +02:00
DiagnosticFun & &
2023-08-01 17:53:42 +02:00
returning ( VAL & & riggedResponse )
2023-07-31 21:53:16 +02:00
{
2023-08-01 17:53:42 +02:00
retVal_ = std : : forward < VAL > ( riggedResponse ) ;
2023-07-31 21:53:16 +02:00
return std : : move ( * this ) ;
}
2023-09-01 21:59:25 +02:00
/** use the given λ to provide (optional) implementation logic */
template < class FUN >
DiagnosticFun & &
implementedAs ( FUN & & customImpl )
{
implFun_ = std : : forward < FUN > ( customImpl ) ;
return std : : move ( * this ) ;
}
2023-08-18 19:37:44 +02:00
// default copyable
2023-07-31 21:53:16 +02:00
/** mock function call operator: logs all invocations */
RET
2023-10-18 23:02:29 +02:00
operator ( ) ( ARGS . . . args ) const
2023-07-31 21:53:16 +02:00
{
2023-08-13 23:42:04 +02:00
log_ - > call ( log_ - > getID ( ) , id_ , args . . . )
2023-08-15 02:23:40 +02:00
. addAttrib ( MARK_SEQ , util : : toString ( * seqNr_ ) ) ;
2023-09-01 21:59:25 +02:00
return implFun_ ? implFun_ ( std : : forward < ARGS > ( args ) . . . )
: * retVal_ ;
2023-07-31 21:53:16 +02:00
}
2023-08-18 19:37:44 +02:00
operator string ( ) const
{
return log_ - > getID ( ) + " . " + id_ ;
}
2023-07-31 21:53:16 +02:00
} ;
2023-07-13 01:51:21 +02:00
2023-08-15 18:52:51 +02:00
/** @internal type rebinding helper */
template < typename SIG >
struct _DiagnosticFun
{
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 Type = typename RebindVariadic < DiagnosticFun , SigTypes > : : Type ;
} ;
2023-08-18 19:37:44 +02:00
using Logger = _DiagnosticFun < void ( string ) > : : Type ;
2023-08-15 18:52:51 +02:00
/**
* A Mocked job operation to detect any actual invocation
*/
class MockJobFunctor
: public NopJobFunctor
{
2023-08-15 20:03:01 +02:00
using MockOp = typename _DiagnosticFun < SIG_JobDiagnostic > : : Type ;
2023-08-15 18:52:51 +02:00
MockOp mockOperation_ ;
/** rigged diagnostic implementation of job invocation
* @ note only data relevant for diagnostics is explicitly unpacked
*/
void
invokeJobOperation ( JobParameter param ) override
{
2023-08-18 04:00:21 +02:00
mockOperation_ ( Time { TimeValue { param . nominalTime } } , param . invoKey . part . a ) ;
2023-08-15 18:52:51 +02:00
}
2023-08-19 19:06:44 +02:00
string diagnostic ( ) const override
{
return " JobFun- " + string { mockOperation_ } ;
}
2023-08-15 18:52:51 +02:00
public :
MockJobFunctor ( MockOp mockedJobOperation )
: mockOperation_ { move ( mockedJobOperation ) }
{ }
} ;
2023-08-18 19:37:44 +02:00
/**
* A rigged CALLBACK - Activity to watch passing of activations .
*/
class ActivityProbe
: public Activity
, activity : : Hook
{
Logger log_ ;
activity : : Proc
activation ( Activity & thisHook
, Time now
, void * executionCtx ) override
{
2023-09-01 17:39:55 +02:00
REQUIRE ( thisHook . is ( Activity : : HOOK ) ) ;
2023-08-18 19:37:44 +02:00
if ( data_ . callback . arg = = 0 )
{ // no adapted target; just record this activation
log_ ( util : : toString ( now ) + " ⧐ " ) ;
return activity : : PASS ;
}
else
{ // forward activation to the adapted target Activity
Activity & target = * reinterpret_cast < Activity * > ( data_ . callback . arg ) ;
auto ctx = * static_cast < FakeExecutionCtx * > ( executionCtx ) ;
log_ ( util : : toString ( now ) + " ⧐ " + util : : toString ( target ) ) ;
return target . activate ( now , ctx ) ;
}
}
2023-08-21 17:32:52 +02:00
activity : : Proc
notify ( Activity & thisHook
, Time now
, void * executionCtx ) override
{
2023-09-01 17:39:55 +02:00
REQUIRE ( thisHook . is ( Activity : : HOOK ) ) ;
2023-08-21 17:32:52 +02:00
if ( data_ . callback . arg = = 0 )
{ // no adapted target; just record this notification
log_ ( util : : toString ( now ) + " --notify-↯• " ) ;
return activity : : PASS ;
}
else
{ // forward notification-dispatch to the adapted target Activity
Activity & target = * reinterpret_cast < Activity * > ( data_ . callback . arg ) ;
auto ctx = * static_cast < FakeExecutionCtx * > ( executionCtx ) ;
log_ ( util : : toString ( now ) + " --notify-↯> " + util : : toString ( target ) ) ;
2023-08-21 18:23:57 +02:00
return target . notify ( now , ctx ) ;
2023-08-21 17:32:52 +02:00
}
}
2023-08-18 19:37:44 +02:00
std : : string
diagnostic ( ) const override
{
return " Probe( " + string { log_ } + " ) " ;
}
public :
ActivityProbe ( string id , EventLog & masterLog , uint const & invocationSeqNr )
: Activity { * this , 0 }
, log_ { id , masterLog , invocationSeqNr }
{ }
2023-08-19 19:06:44 +02:00
ActivityProbe ( Activity const & subject , string id , EventLog & masterLog , uint const & invocationSeqNr )
: Activity { * this , reinterpret_cast < size_t > ( & subject ) }
, log_ { id , masterLog , invocationSeqNr }
{
next = subject . next ;
}
2023-08-18 19:37:44 +02:00
operator string ( ) const
{
return diagnostic ( ) ;
}
} ;
2023-08-15 18:52:51 +02:00
/* ===== Maintain throw-away mock instances ===== */
std : : deque < MockJobFunctor > mockOps_ { } ;
2023-08-18 19:37:44 +02:00
std : : deque < ActivityProbe > mockActs_ { } ;
2023-08-15 18:52:51 +02:00
2023-07-13 01:51:21 +02:00
2023-07-31 21:53:16 +02:00
public :
2023-08-01 17:53:42 +02:00
ActivityDetector ( string id = " " )
2023-07-31 21:53:16 +02:00
: eventLog_ { " ActivityDetector " + ( isnil ( id ) ? string { } : " ( " + id + " ) " ) }
2023-08-01 17:53:42 +02:00
, invocationSeq_ { 0 }
2023-07-13 01:51:21 +02:00
{ }
2023-07-31 21:53:16 +02:00
operator string ( ) const
{
return util : : join ( eventLog_ ) ;
}
2023-08-15 02:23:40 +02:00
string
showLog ( ) const
{
return " \n ____Event-Log___________________________ \n "
+ util : : join ( eventLog_ , " \n " )
+ " \n ────╼━━━━━━━━╾────────────────────────── "
;
}
2023-07-31 21:53:16 +02:00
void
clear ( string newID )
{
if ( isnil ( newID ) )
eventLog_ . clear ( ) ;
else
eventLog_ . clear ( newID ) ;
}
2023-08-15 02:23:40 +02:00
/** increment the internal invocation sequence number */
2023-08-01 17:53:42 +02:00
uint
2023-08-22 20:13:13 +02:00
incrementSeq ( )
2023-08-01 17:53:42 +02:00
{
+ + invocationSeq_ ;
2023-08-15 02:23:40 +02:00
eventLog_ . event ( MARK_INC , util : : toString ( invocationSeq_ ) ) ;
2023-08-01 17:53:42 +02:00
return invocationSeq_ ;
}
uint
currSeq ( ) const
{
return invocationSeq_ ;
}
2023-07-31 21:53:16 +02:00
/**
* 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 )
{
2023-08-15 18:52:51 +02:00
using Functor = typename _DiagnosticFun < SIG > : : Type ;
2023-08-13 23:42:04 +02:00
return Functor { id , eventLog_ , invocationSeq_ } ;
2023-07-31 21:53:16 +02:00
}
2023-08-15 18:52:51 +02:00
JobClosure & ///////////////////////////////////////////////////////////////////TICKET #1287 : fix actual interface down to JobFunctor (after removing C structs)
2023-08-15 17:18:30 +02:00
buildMockJobFunctor ( string id )
{
2023-08-15 18:52:51 +02:00
return mockOps_ . emplace_back (
2023-08-15 20:03:01 +02:00
buildDiagnosticFun < SIG_JobDiagnostic > ( id ) ) ;
2023-08-15 17:18:30 +02:00
}
2023-08-13 20:49:30 +02:00
2023-08-29 02:18:07 +02:00
Job
buildMockJob ( string id = " "
, Time nominal = lib : : test : : randTime ( )
, size_t extra = rand ( ) )
{
InvocationInstanceID invoKey ;
invoKey . part . a = extra ;
invoKey . part . t = _raw ( nominal ) ;
return Job { buildMockJobFunctor ( isnil ( id ) ? " mockJob- " + util : : toString ( nominal ) : id )
, invoKey
, nominal } ;
}
2023-08-19 19:06:44 +02:00
/** build a rigged HOOK-Activity to record each invocation */
2023-08-18 19:37:44 +02:00
Activity &
buildActivationProbe ( string id )
{
return mockActs_ . emplace_back ( id , eventLog_ , invocationSeq_ ) ;
2023-08-19 19:06:44 +02:00
}
/** build ActivationProbe to record each activation before passing it to the subject */
Activity &
buildActivationTap ( Activity const & subject , string id = " " )
{
return mockActs_ . emplace_back ( subject
, isnil ( id ) ? " tap- " + subject . showVerb ( ) + util : : showAddr ( subject )
: id
, eventLog_
, invocationSeq_ ) ;
2023-08-18 19:37:44 +02:00
}
2023-08-01 17:53:42 +02:00
2023-08-19 23:59:18 +02:00
/** build ActivationProbe to record each activation before passing it to the subject */
Activity &
insertActivationTap ( Activity * & wiring , string id = " " )
{
wiring = wiring ? & buildActivationTap ( * wiring , id )
: & buildActivationProbe ( isnil ( id ) ? " tail- " + util : : showAddr ( & wiring ) : id ) ;
return * wiring ;
2023-08-20 01:35:14 +02:00
}
Activity &
2023-08-20 02:39:57 +02:00
buildGateWatcher ( Activity & gate , string id = " " )
2023-08-20 01:35:14 +02:00
{
2023-08-30 22:19:57 +02:00
insertActivationTap ( gate . next , " after- " + ( isnil ( id ) ? gate . showVerb ( ) + util : : showAddr ( gate ) : id ) ) ;
2023-08-20 02:39:57 +02:00
return buildActivationTap ( gate , id ) ;
2023-08-20 01:35:14 +02:00
}
Activity &
2023-08-20 02:39:57 +02:00
watchGate ( Activity * & wiring , string id = " " )
2023-08-20 01:35:14 +02:00
{
2023-08-20 02:39:57 +02:00
wiring = wiring ? & buildGateWatcher ( * wiring , id )
: & buildActivationProbe ( isnil ( id ) ? " tail- " + util : : showAddr ( & wiring ) : id ) ;
2023-08-20 01:35:14 +02:00
return * wiring ;
2023-08-19 23:59:18 +02:00
}
2023-08-17 19:37:38 +02:00
struct FakeExecutionCtx ;
2023-10-23 01:48:46 +02:00
using SIG_post = activity : : Proc ( Time , Activity * , FakeExecutionCtx & ) ;
2023-08-17 19:37:38 +02:00
using SIG_work = void ( Time , size_t ) ;
using SIG_done = void ( Time , size_t ) ;
using SIG_tick = activity : : Proc ( Time ) ;
/**
* Mock setup of the execution context for Activity activation .
* The instance # executionCtx is wired back with the # eventLog_
* and allows thus to detect and verify all callbacks from the Activities .
* @ note the return value of the # post and # tick functions can be changed
* to another fixed response by calling DiagnosticFun : : returning
*/
struct FakeExecutionCtx
{
_DiagnosticFun < SIG_post > : : Type post ;
_DiagnosticFun < SIG_work > : : Type work ;
_DiagnosticFun < SIG_done > : : Type done ;
_DiagnosticFun < SIG_tick > : : Type tick ;
2023-10-21 01:01:00 +02:00
function < Offset ( ) > getWaitDelay = [ ] { return POLL_WAIT_DELAY ; } ;
2023-09-01 17:18:32 +02:00
function < Time ( ) > getSchedTime = [ this ] { return SCHED_TIME_MARKER ; } ;
2023-08-20 02:39:57 +02:00
2023-08-31 23:55:42 +02:00
FakeExecutionCtx ( ActivityDetector & detector )
: post { detector . buildDiagnosticFun < SIG_post > ( CTX_POST ) . returning ( activity : : PASS ) }
, work { detector . buildDiagnosticFun < SIG_work > ( CTX_WORK ) }
, done { detector . buildDiagnosticFun < SIG_done > ( CTX_DONE ) }
, tick { detector . buildDiagnosticFun < SIG_tick > ( CTX_TICK ) . returning ( activity : : PASS ) }
2023-08-17 19:37:38 +02:00
{ }
2023-08-18 04:00:21 +02:00
operator string ( ) const { return " ≺test::CTX≻ " ; }
2023-08-17 19:37:38 +02:00
} ;
FakeExecutionCtx executionCtx { * this } ;
2023-08-13 23:42:04 +02:00
ActivityMatch
verifyInvocation ( string fun )
2023-08-01 17:53:42 +02:00
{
2023-08-13 23:42:04 +02:00
return ActivityMatch { move ( eventLog_ . verifyCall ( fun ) ) } ;
2023-08-13 20:49:30 +02:00
}
2023-08-14 19:22:18 +02:00
ActivityMatch
ensureNoInvocation ( string fun )
{
return ActivityMatch { move ( eventLog_ . ensureNot ( fun ) . locateCall ( fun ) ) } ;
}
ActivityMatch
verifySeqIncrement ( uint seqNr )
{
return ActivityMatch { move ( eventLog_ . verifyEvent ( MARK_INC , util : : toString ( seqNr ) ) ) } ;
}
2023-07-13 01:51:21 +02:00
private :
} ;
} } } // namespace vault::gear::test
# endif /*VAULT_GEAR_TEST_ACTIVITY_DETECTOR_H*/