Dispatcher-Pipeline: mocked Dispatcher implementation complete (closes: #1294)
`steam/engine/mock-dispatcher.hpp |cpp` now integrates this ''complete mock setup for render jobs and frame dispatching.'' The exising `DummyJob` has been slightly adapted and renamed to `MockJob` and is tightly integrated with the other mocks. The implementation of a `MockDispatcher` necessitated to change the use of `MockJobTicket`. The initial attempts used a complete mock implementation, but this approach turned out not to be viable. Instead — based on the ideas developed for the mock setup — now the prospective real implementation of `JobTicket` is available and will be used by the mock setup too. Instead of a synthetic spec, now a setup of recursively connected `ExitNode`(s) is used; the latter seems to develop into some kind of Facade for the render node network. Based on this mock setup, we can now demonstrate the (mostly) complete Job-Planning pipeline, starting from a segmentation up to render jobs, and verify proper connectivity and job invocation. ✔
This commit is contained in:
parent
0b9705692b
commit
542017aa65
13 changed files with 231 additions and 276 deletions
|
|
@ -48,41 +48,11 @@
|
|||
|
||||
#include "lib/iter-adapter.hpp"
|
||||
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace std {
|
||||
template <typename _Tp, typename _Dp>
|
||||
class unique_ptr;
|
||||
}
|
||||
|
||||
namespace lib {
|
||||
|
||||
namespace {
|
||||
|
||||
/** helper to remove pointer,
|
||||
* while retaining const */
|
||||
template<typename T>
|
||||
struct RemovePtr { typedef T Type; };
|
||||
|
||||
template<typename T>
|
||||
struct RemovePtr<T*> { typedef T Type; };
|
||||
|
||||
template<typename T>
|
||||
struct RemovePtr<const T*> { typedef const T Type; };
|
||||
|
||||
template<typename T>
|
||||
struct RemovePtr<T* const> { typedef const T Type; };
|
||||
|
||||
template<typename T>
|
||||
struct RemovePtr<const T* const> { typedef const T Type; };
|
||||
|
||||
/** allow automatic dereferencing of std::unique_ptr */
|
||||
template<typename T, typename D>
|
||||
struct RemovePtr<std::unique_ptr<T,D>> { typedef T Type; };
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* wrapper for an existing Iterator type,
|
||||
|
|
@ -98,26 +68,30 @@ namespace lib {
|
|||
|
||||
|
||||
public:
|
||||
typedef typename IT::value_type pointer;
|
||||
typedef typename RemovePtr<pointer>::Type value_type;
|
||||
typedef value_type& reference;
|
||||
/** this iterator adapter is meant to wrap an iterator yielding pointer values */
|
||||
using pointer = typename meta::ValueTypeBinding<IT>::value_type;
|
||||
static_assert(std::is_pointer_v<pointer>);
|
||||
|
||||
using value_type = typename std::remove_pointer_t<pointer>;
|
||||
using reference = value_type&;
|
||||
|
||||
|
||||
ENABLE_USE_IN_STD_RANGE_FOR_LOOPS (PtrDerefIter);
|
||||
|
||||
|
||||
// the purpose of the following typedefs is to ease building a correct "const iterator"
|
||||
// the purpose of the following typedefs is to support building a correct "const iterator"
|
||||
|
||||
typedef typename boost::remove_const<value_type>::type ValueTypeBase; // value_type without const
|
||||
using ValueTypeBase = typename std::remove_const_t<value_type>; // value_type without const
|
||||
|
||||
typedef typename IterType<IT>::template SimilarIter< ValueTypeBase* * >::Type WrappedIterType;
|
||||
typedef typename IterType<IT>::template SimilarIter<const ValueTypeBase* * >::Type WrappedConstIterType;
|
||||
using WrappedIterType = typename IterType<IT>::template SimilarIter< ValueTypeBase* * >::Type;
|
||||
using WrappedConstIterType = typename IterType<IT>::template SimilarIter<const ValueTypeBase* * >::Type;
|
||||
|
||||
typedef PtrDerefIter<WrappedIterType> IterType;
|
||||
typedef PtrDerefIter<WrappedConstIterType> ConstIterType;
|
||||
using IterType = PtrDerefIter<WrappedIterType>;
|
||||
using ConstIterType = PtrDerefIter<WrappedConstIterType>;
|
||||
|
||||
|
||||
|
||||
/** PtrDerefIter is always created
|
||||
/** PtrDerefIter is always created
|
||||
* by wrapping an existing iterator.
|
||||
*/
|
||||
explicit
|
||||
|
|
@ -244,7 +218,7 @@ namespace lib {
|
|||
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* wrapper for an existing Iterator type to expose the address of each value yielded.
|
||||
* Typically this can be used to build visitation sequences based on values living
|
||||
* within a stable data structure (e.g. unmodifiable STL vector)
|
||||
|
|
@ -280,7 +254,7 @@ namespace lib {
|
|||
ENABLE_USE_IN_STD_RANGE_FOR_LOOPS (AddressExposingIter);
|
||||
|
||||
|
||||
/** AddressExposingIter is always created
|
||||
/** AddressExposingIter is always created
|
||||
* by wrapping an existing iterator.
|
||||
*/
|
||||
explicit
|
||||
|
|
@ -304,7 +278,7 @@ namespace lib {
|
|||
/** @return address of the source iteraor's current result
|
||||
* @warning exposing a reference to an internal pointer for sake of compatibility.
|
||||
* Clients must not store that reference, but rather use it to initialise
|
||||
* a copy. The internal pointer exposed here will be changed on increment.
|
||||
* a copy. The internal pointer exposed here will be changed on increment.
|
||||
*/
|
||||
reference
|
||||
operator*() const
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
#include "steam/common.hpp"
|
||||
#include "steam/mobject/model-port.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
#include "lib/time/timequant.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,19 +36,14 @@
|
|||
#define STEAM_ENGINE_JOB_TICKET_H
|
||||
|
||||
#include "steam/common.hpp"
|
||||
//#include "steam/state.hpp"
|
||||
#include "vault/engine/job.h"
|
||||
#include "steam/engine/frame-coord.hpp"
|
||||
#include "steam/engine/exit-node.hpp"
|
||||
//#include "lib/time/timevalue.hpp"
|
||||
//#include "lib/time/timequant.hpp"
|
||||
#include "lib/hierarchy-orientation-indicator.hpp"
|
||||
#include "lib/linked-elements.hpp"
|
||||
#include "lib/util-foreach.hpp"
|
||||
#include "lib/iter-adapter.hpp"
|
||||
#include "lib/itertools.hpp"
|
||||
#include "lib/util-foreach.hpp"
|
||||
#include "lib/meta/tuple-helper.hpp"
|
||||
#include "lib/meta/trait.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
|
@ -58,10 +53,6 @@
|
|||
namespace steam {
|
||||
namespace engine {
|
||||
|
||||
//using lib::time::TimeSpan;
|
||||
//using lib::time::Duration;
|
||||
//using lib::time::FSecs;
|
||||
//using lib::time::Time;
|
||||
using vault::engine::Job;
|
||||
using vault::engine::JobFunctor;
|
||||
using vault::engine::JobClosure; /////////////////////////////////////////////////////////////////////TICKET #1287 : fix actual interface down to JobFunctor (after removing C structs)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
#include "steam/engine/job-ticket.hpp"
|
||||
#include "lib/allocator-handle.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
#include "lib/itertools.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
|
||||
#include <list>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
|
||||
|
||||
namespace steam {
|
||||
|
|
@ -83,19 +84,17 @@ namespace fixture {
|
|||
class Segmentation
|
||||
: util::NonCopyable
|
||||
{
|
||||
protected:
|
||||
/** segments of the engine in ordered sequence. */
|
||||
list<Segment> segments_;
|
||||
|
||||
public:
|
||||
virtual ~Segmentation(); ///< this is an interface
|
||||
|
||||
protected:
|
||||
Segmentation() ///< there is always a single cover-all Segment initially
|
||||
: segments_{1}
|
||||
{ }
|
||||
|
||||
public:
|
||||
virtual ~Segmentation(); ///< this is an interface
|
||||
|
||||
size_t
|
||||
size() const
|
||||
{
|
||||
|
|
@ -121,6 +120,16 @@ namespace fixture {
|
|||
/** rework the existing Segmentation to include a new Segment as specified */
|
||||
Segment const&
|
||||
splitSplice (OptTime start, OptTime after, engine::ExitNodes&& modelLink =ExitNodes{});
|
||||
|
||||
|
||||
protected:
|
||||
/** @internal rewrite the NodeGraphAttachment in each Segment */
|
||||
void
|
||||
adaptSpecification (std::function<NodeGraphAttachment(NodeGraphAttachment const&)> rewrite)
|
||||
{
|
||||
for (fixture::Segment& seg : segments_)
|
||||
seg.exitNode = move(rewrite (seg.exitNode));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,16 +29,18 @@
|
|||
#include "lib/util.hpp"
|
||||
|
||||
#include "vault/real-clock.hpp"
|
||||
#include "vault/engine/dummy-job.hpp"
|
||||
#include "steam/engine/mock-dispatcher.hpp"
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
|
||||
namespace vault {
|
||||
namespace engine {
|
||||
namespace test {
|
||||
namespace steam {
|
||||
namespace engine{
|
||||
namespace test {
|
||||
|
||||
using util::isSameObject;
|
||||
using vault::engine::Job;
|
||||
using vault::engine::JobParameter;
|
||||
|
||||
|
||||
|
||||
|
|
@ -67,23 +69,23 @@ namespace test {
|
|||
void
|
||||
verify_simple_job_properties()
|
||||
{
|
||||
Job job = DummyJob::build();
|
||||
MockJob job;
|
||||
CHECK (job.isValid());
|
||||
|
||||
Time beforeInvocation = RealClock::now();
|
||||
job.triggerJob();
|
||||
|
||||
CHECK (DummyJob::was_invoked (job));
|
||||
CHECK (RealClock::now() > DummyJob::invocationTime (job));
|
||||
CHECK (beforeInvocation < DummyJob::invocationTime (job));
|
||||
CHECK (MockJob::was_invoked (job));
|
||||
CHECK (RealClock::now() > MockJob::invocationTime (job));
|
||||
CHECK (beforeInvocation < MockJob::invocationTime (job));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
verify_job_identity()
|
||||
{
|
||||
Job job1 = DummyJob::build();
|
||||
Job job2 = DummyJob::build();
|
||||
MockJob job1;
|
||||
MockJob job2;
|
||||
|
||||
CHECK (job1 != job2, "random test data clash");
|
||||
|
||||
|
|
@ -130,4 +132,4 @@ namespace test {
|
|||
/** Register this test class... */
|
||||
LAUNCHER(JobHash_test, "unit engine");
|
||||
|
||||
}}} // namespace vault::engine::test
|
||||
}}} // namespace steam::engine::test
|
||||
|
|
@ -28,19 +28,14 @@
|
|||
#include "lib/test/run.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
#include "steam/engine/mock-dispatcher.hpp"
|
||||
#include "vault/engine/dummy-job.hpp"
|
||||
|
||||
#include "lib/format-cout.hpp"///////////////////////TODO
|
||||
#include "lib/iter-tree-explorer.hpp"
|
||||
#include "lib/format-util.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
//#include "steam/engine/job-planning.hpp"
|
||||
|
||||
//#include <ctime>
|
||||
|
||||
using test::Test;
|
||||
//using std::rand;
|
||||
using lib::eachNum;
|
||||
using lib::treeExplore;
|
||||
using lib::time::PQuant;
|
||||
|
|
@ -52,7 +47,6 @@ namespace steam {
|
|||
namespace engine{
|
||||
namespace test {
|
||||
|
||||
using vault::engine::DummyJob;
|
||||
using lib::time::FixedFrameQuantiser;
|
||||
|
||||
namespace { // test fixture...
|
||||
|
|
@ -83,7 +77,7 @@ namespace test {
|
|||
* - integration: generate a complete sequence of (dummy)Jobs
|
||||
* - scaffolding and mocking used for this test
|
||||
*
|
||||
* @todo WIP-WIP-WIP 4/2023
|
||||
* @todo WIP-WIP 4/2023
|
||||
*
|
||||
* @see DispatcherInterface_test
|
||||
* @see MockSupport_test
|
||||
|
|
@ -112,12 +106,12 @@ namespace test {
|
|||
Time nominalTime = lib::test::randTime();
|
||||
int additionalKey = rand() % 5000;
|
||||
|
||||
Job mockJob = DummyJob::build (nominalTime, additionalKey);
|
||||
MockJob mockJob{nominalTime, additionalKey};
|
||||
mockJob.triggerJob();
|
||||
CHECK (DummyJob::was_invoked (mockJob));
|
||||
CHECK (RealClock::wasRecently (DummyJob::invocationTime (mockJob)));
|
||||
CHECK (nominalTime == DummyJob::invocationNominalTime (mockJob) );
|
||||
CHECK (additionalKey == DummyJob::invocationAdditionalKey(mockJob));
|
||||
CHECK (MockJob::was_invoked (mockJob));
|
||||
CHECK (RealClock::wasRecently (MockJob::invocationTime (mockJob)));
|
||||
CHECK (nominalTime == MockJob::invocationNominalTime (mockJob) );
|
||||
CHECK (additionalKey == MockJob::invocationAdditionalKey(mockJob));
|
||||
|
||||
// Build a simple Segment at [10s ... 20s[
|
||||
MockSegmentation mockSegs{MakeRec()
|
||||
|
|
@ -143,10 +137,15 @@ namespace test {
|
|||
|
||||
jobP.triggerJob();
|
||||
jobM.triggerJob();
|
||||
CHECK (123 == DummyJob::invocationAdditionalKey (jobM)); // verify each job was invoked and linked to the correct spec,
|
||||
CHECK (555 == DummyJob::invocationAdditionalKey (jobP)); // indicating that in practice it will activate the proper render node
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////TODO: extract Dispatcher-Mock from DispatcherInterface_test
|
||||
CHECK (123 == MockJob::invocationAdditionalKey (jobM)); // verify each job was invoked and linked to the correct spec,
|
||||
CHECK (555 == MockJob::invocationAdditionalKey (jobP)); // indicating that in practice it will activate the proper render node
|
||||
|
||||
coord.modelPortIDX = 1;
|
||||
coord.absoluteNominalTime = Time{0,30};
|
||||
MockDispatcher dispatcher; // a complete dispatcher backed by a mock Segment for the whole timeline
|
||||
auto [port1,sink1] = dispatcher.getDummyConnection(1); // also some fake ModelPort and DataSink entries are registered
|
||||
Job jobD = dispatcher.getJobTicketFor(coord).createJobFor(coord);
|
||||
CHECK (dispatcher.verify(jobD, port1, sink1)); // the generated job uses the associated ModelPort and DataSink and JobTicket
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
DummyJob - diagnostic job for unit tests
|
||||
MockDispatcher - diagnostic render job and frame dispatcher
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2013, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
* *****************************************************/
|
||||
|
||||
/** @file dummy-job.cpp
|
||||
/** @file mock-dispatcher.cpp
|
||||
** Implementation of a dummy render job for unit tests.
|
||||
** Based on using a specifically rigged DummyClosure as JobFunctor,
|
||||
** where the actual Job invocation does nothing other than storing
|
||||
|
|
@ -32,14 +32,14 @@
|
|||
**
|
||||
** # Usage front-end
|
||||
**
|
||||
** The static functions in vault::engine::DummyJob allow to
|
||||
** - build such a mock job, possibly with random (or well defined) parameters
|
||||
** - when passing back this job instance, verify invocation and extract data
|
||||
** A MockJob can directly created, and then sliced down to the Job baseclass,
|
||||
** since it has no additional data fields. The static functions in MockJob allow
|
||||
** to verify that a given job instance was created from this setup, that it was
|
||||
** invoked, and verify invocation time and extract data
|
||||
*/
|
||||
|
||||
|
||||
#include "vault/engine/dummy-job.hpp"
|
||||
|
||||
#include "steam/engine/mock-dispatcher.hpp"
|
||||
#include "vault/engine/nop-job-functor.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
|
|
@ -50,14 +50,15 @@
|
|||
#include "lib/util.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
namespace vault{
|
||||
namespace engine {
|
||||
namespace steam {
|
||||
namespace engine{
|
||||
namespace test {
|
||||
|
||||
namespace { // DummyJob implementation details...
|
||||
namespace { // MockJob and DummyClosure implementation details...
|
||||
|
||||
using lib::HashVal;
|
||||
using lib::NullValue;
|
||||
|
|
@ -65,14 +66,16 @@ namespace engine {
|
|||
using std::unordered_map;
|
||||
using util::access_or_default;
|
||||
|
||||
using vault::engine::JobParameter;
|
||||
|
||||
|
||||
const int MAX_PARAM_A(1000); ///< random test values 0...1000
|
||||
const int MAX_PARAM_B(10); ///< random test values -10...+10
|
||||
|
||||
|
||||
/**
|
||||
* test dummy jobs are backed by this closure.
|
||||
* DummyJob invocations are recorded in a hashtable
|
||||
* MockJob objects are backed by this closure.
|
||||
* Invocations of this job functor are recorded in a hashtable
|
||||
* @note as of 5/2023, we use a simplistic map-based implementation,
|
||||
* causing a consecutive invocation of the same job instance
|
||||
* with identical JobParameter to overwrite the previous log entry.
|
||||
|
|
@ -158,7 +161,7 @@ namespace engine {
|
|||
{ }
|
||||
};
|
||||
|
||||
/** recording DummyJob invocations */
|
||||
/** recording MockJob invocations */
|
||||
unordered_map<HashVal,Invocation> invocationLog_;
|
||||
|
||||
|
||||
|
|
@ -195,7 +198,7 @@ namespace engine {
|
|||
|
||||
|
||||
Job
|
||||
DummyJob::build()
|
||||
MockJob::build()
|
||||
{
|
||||
InvocationInstanceID invoKey;
|
||||
invoKey.part.a = rand() % MAX_PARAM_A;
|
||||
|
|
@ -208,7 +211,7 @@ namespace engine {
|
|||
|
||||
|
||||
Job
|
||||
DummyJob::build (Time nominalTime, int additionalKey)
|
||||
MockJob::build (Time nominalTime, int additionalKey)
|
||||
{
|
||||
InvocationInstanceID invoKey;
|
||||
invoKey.part.a = additionalKey;
|
||||
|
|
@ -219,7 +222,7 @@ namespace engine {
|
|||
|
||||
|
||||
bool
|
||||
DummyJob::was_invoked (Job const& job)
|
||||
MockJob::was_invoked (Job const& job)
|
||||
{
|
||||
REQUIRE (job.usesClosure (dummyClosure));
|
||||
|
||||
|
|
@ -228,7 +231,7 @@ namespace engine {
|
|||
|
||||
|
||||
Time
|
||||
DummyJob::invocationTime (Job const& job)
|
||||
MockJob::invocationTime (Job const& job)
|
||||
{
|
||||
REQUIRE (job.usesClosure (dummyClosure));
|
||||
|
||||
|
|
@ -237,7 +240,7 @@ namespace engine {
|
|||
|
||||
|
||||
Time
|
||||
DummyJob::invocationNominalTime (Job const& job)
|
||||
MockJob::invocationNominalTime (Job const& job)
|
||||
{
|
||||
REQUIRE (job.usesClosure (dummyClosure));
|
||||
|
||||
|
|
@ -246,7 +249,7 @@ namespace engine {
|
|||
|
||||
|
||||
int
|
||||
DummyJob::invocationAdditionalKey (Job const& job)
|
||||
MockJob::invocationAdditionalKey (Job const& job)
|
||||
{
|
||||
REQUIRE (job.usesClosure (dummyClosure));
|
||||
|
||||
|
|
@ -256,7 +259,7 @@ namespace engine {
|
|||
|
||||
/** @internal for collaboration with other Mock/Dummy facilities */
|
||||
JobClosure&
|
||||
DummyJob::getFunctor()
|
||||
MockJob::getFunctor()
|
||||
{
|
||||
return dummyClosure;
|
||||
}
|
||||
|
|
@ -268,7 +271,7 @@ namespace engine {
|
|||
* @see JobTicket::JobTicket::createJobFor(FrameCoord)
|
||||
*/
|
||||
bool
|
||||
DummyJob::isNopJob (Job const& job)
|
||||
MockJob::isNopJob (Job const& job)
|
||||
{
|
||||
InvocationInstanceID empty; ///////////////////////////////////////////////////////////////////////TICKET #1287 : temporary workaround until we get rid of the C base structs
|
||||
JobClosure& jobFunctor = static_cast<JobClosure&> (*job.jobClosure); //////////////////////////TICKET #1287 : fix actual interface down to JobFunctor (after removing C structs)
|
||||
|
|
@ -278,4 +281,4 @@ namespace engine {
|
|||
|
||||
|
||||
|
||||
}} // namespace vault::engine
|
||||
}}} // namespace steam::engine::test
|
||||
|
|
@ -22,19 +22,25 @@
|
|||
|
||||
/** @file mock-dispatcher.hpp
|
||||
** Mock data structures to support implementation testing of render job
|
||||
** planning and frame dispatch. Together with dummy-job.hpp, this provides
|
||||
** a specifically rigged test setup, allowing to investigate and verify
|
||||
** designated functionality in isolation, without backing by the actual
|
||||
** render engine implementation.
|
||||
** - the MockDispatcherTable emulates the frame dispatch from the Fixture
|
||||
** planning and frame dispatch. This specifically rigged test setup allows to
|
||||
** investigate and verify designated functionality in isolation, without backing
|
||||
** by the actual render engine and low-level-Model implementation.
|
||||
** - a MockJob is a render Job, wired to a DummyFunctor, which does nothing,
|
||||
** but records any invocation into an internal diagnostics Map.
|
||||
** - MockJobTicket is a builder / adapter on top of the actual steam::engine::JobTicket,
|
||||
** allowing to generate simple JobTicket instances with an embedded ExitNode and
|
||||
** a (configurable) pipelineID. From this setup, »mock jobs« can be generated,
|
||||
** which use the MockJob functor and thus record any invocation without performing
|
||||
** actual work. The internal connection to the MockJobTicket can then be verified.
|
||||
** - MockSegmentation is a mocked variant of the »Segmentation« datastructure,
|
||||
** which forms the backbone of the Fixture and is the top-level attachment
|
||||
** point for the »low-level-Model« (the render nodes network)
|
||||
** - MockJobTicket is a builder / adapter on top of the actual steam::engine::JobTicket,
|
||||
** allowing to generate a complete rigged MockSegmentation setup from a generic
|
||||
** test specification written as nested lib::diff::GenNode elements. From this
|
||||
** setup, »mock jobs« can be generated, which use the DummyJob functor and
|
||||
** just record any invocation without performing actual work.
|
||||
** point for the »low-level-Model« (the render nodes network). It can be
|
||||
** configured with a test specification of ExitNode(s) defined by a
|
||||
** GenNode tree, and defining Segments of the timeline and prerequisites.
|
||||
** - finally, the MockDispatcher combines all these facilities to emulate
|
||||
** frame dispatch from the Fixture without actually using any data model.
|
||||
** Similar to MockSegmentation, a GenNode-based specification is used.
|
||||
**
|
||||
** @remark in spring 2023, this setup was created as a means to define and
|
||||
** then build the actual implementation of frame dispatch and scheduling.
|
||||
** @see MockSupport_test
|
||||
|
|
@ -53,7 +59,6 @@
|
|||
#include "steam/engine/dispatcher.hpp"
|
||||
#include "steam/engine/job-ticket.hpp"
|
||||
#include "vault/engine/job.h"
|
||||
#include "vault/engine/dummy-job.hpp"
|
||||
#include "vault/real-clock.hpp"
|
||||
#include "lib/allocator-handle.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
|
|
@ -79,45 +84,57 @@ namespace test {
|
|||
using lib::HashVal;
|
||||
using util::isnil;
|
||||
using util::isSameObject;
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1294 : organisation of namespaces / includes??
|
||||
using fixture::Segmentation;
|
||||
using vault::engine::Job;
|
||||
using vault::engine::JobClosure;
|
||||
|
||||
namespace { // used internally
|
||||
|
||||
using play::test::ModelPorts;
|
||||
using play::test::PlayTestFrames_Strategy;
|
||||
using vault::engine::JobClosure;
|
||||
using vault::engine::JobParameter;
|
||||
using vault::engine::DummyJob;
|
||||
|
||||
using DummyPlaybackSetup = play::test::DummyPlayConnection<PlayTestFrames_Strategy>;
|
||||
|
||||
|
||||
|
||||
|
||||
/* ===== specify a mock JobTicket setup for tests ===== */
|
||||
|
||||
inline ExitNode
|
||||
defineSimpleSpec (HashVal seed = 1+rand())
|
||||
{
|
||||
return ExitNode{seed
|
||||
,ExitNodes{}
|
||||
,& DummyJob::getFunctor()};
|
||||
}
|
||||
|
||||
}//(End)internal test helpers....
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Mock setup for a JobTicket to generate DummyJob invocations.
|
||||
* Mock setup for a render Job with NO action but built-in diagnostics.
|
||||
* Each invocation of such a MockJob will be logged internally
|
||||
* and can be investigated and verified afterwards.
|
||||
*/
|
||||
class MockJob
|
||||
: public Job
|
||||
{
|
||||
static Job build(); ///< uses random job definition values
|
||||
static Job build (Time nominalTime, int additionalKey);
|
||||
|
||||
public:
|
||||
MockJob()
|
||||
: Job{build()}
|
||||
{ }
|
||||
|
||||
MockJob (Time nominalTime, int additionalKey)
|
||||
: Job{build (nominalTime,additionalKey)}
|
||||
{ }
|
||||
|
||||
|
||||
static bool was_invoked (Job const& job);
|
||||
static Time invocationTime (Job const& job);
|
||||
static Time invocationNominalTime (Job const& job);
|
||||
static int invocationAdditionalKey (Job const& job);
|
||||
|
||||
static bool isNopJob (Job const&);
|
||||
static JobClosure& getFunctor();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Mock setup for a JobTicket to generate dummy render Job invocations.
|
||||
* Implemented as subclass, it provides a specification DSL for tests,
|
||||
* and is able to probe some otherwise opaque internals of JobTicket.
|
||||
* Beyond that, MockJobTicket has the same storage size; and behaves
|
||||
* like the regular JobTicket after construction -- but any Job
|
||||
* created by JobTicket::createJobFor(FrameCoord) will be wired
|
||||
* with the DummyJob functor and can thus be related back to
|
||||
* with the MockJob functor and can thus be related back to
|
||||
* the test specification setup.
|
||||
* @see JobPlanningSetup_test
|
||||
* @see DispatcherInterface_test
|
||||
|
|
@ -132,6 +149,15 @@ namespace test {
|
|||
return static_cast<lib::AllocatorHandle<JobTicket>&> (*this);
|
||||
}
|
||||
|
||||
/** provide a test specification wired to MockJob */
|
||||
static ExitNode
|
||||
defineSimpleSpec (HashVal seed = 1+rand())
|
||||
{
|
||||
return ExitNode{seed
|
||||
,ExitNodes{}
|
||||
,& MockJob::getFunctor()};
|
||||
}
|
||||
|
||||
public:
|
||||
MockJobTicket()
|
||||
: JobTicket{defineSimpleSpec(), allocator()}
|
||||
|
|
@ -157,14 +183,14 @@ namespace test {
|
|||
* test, by passing a test specification in »GenNode« notation to the
|
||||
* constructor. This specification defines the segments to create
|
||||
* and allows to associate a marker number, which can later be
|
||||
* verified from the actual DummyJob invocation.
|
||||
* verified from the actual DummyClosure invocation.
|
||||
* - the ctor accepts a sequence of GenNode elements,
|
||||
* each corresponding to a segment to created
|
||||
* - optionally, attributes "start" and "after" can be defined
|
||||
* to provide the lib::time::Time values of segment start/end
|
||||
* - in addition, optionally a "mark" attribute can be defined;
|
||||
* the given integer number will be "hidden" in the job instance
|
||||
* hash, and can be [verified](\ref DummyJob::invocationAdditionalKey)
|
||||
* hash, and can be [verified](\ref MockJob::invocationAdditionalKey)
|
||||
* - the _scope_ of each top-level GenNode may hold a sequence of
|
||||
* nested nodes corresponding to _prerequisite_ JobTicket instances
|
||||
* - these can in turn hold further nested prerequisites, and so on
|
||||
|
|
@ -198,7 +224,7 @@ namespace test {
|
|||
{
|
||||
return ExitNode{buildSeed (spec)
|
||||
,buildPrerequisites (spec)
|
||||
,& DummyJob::getFunctor()};
|
||||
,& MockJob::getFunctor()};
|
||||
}
|
||||
|
||||
/** @internal helper for MockDispatcher */
|
||||
|
|
@ -238,8 +264,12 @@ namespace test {
|
|||
inline void
|
||||
MockSegmentation::duplicateExitNodeSpec (uint times)
|
||||
{
|
||||
for (fixture::Segment& seg : segments_)
|
||||
seg.exitNode = move(fixture::NodeGraphAttachment{ExitNodes{times, seg.exitNode[0]}});
|
||||
using Spec = fixture::NodeGraphAttachment;
|
||||
|
||||
Segmentation::adaptSpecification ([times](Spec const& spec)
|
||||
{
|
||||
return Spec{ExitNodes{times, spec[0]}};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -273,6 +303,28 @@ namespace test {
|
|||
|
||||
|
||||
|
||||
namespace { // used internally by MockDispatcher....
|
||||
using play::test::ModelPorts;
|
||||
using play::test::PlayTestFrames_Strategy;
|
||||
|
||||
using DummyPlaybackSetup = play::test::DummyPlayConnection<PlayTestFrames_Strategy>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A mocked frame Dispatcher setup without any backing model.
|
||||
* Instantiating such a MockDispatcher will automatically create some fake
|
||||
* model structures and some ModelPort and DisplaySink handles (and thereby
|
||||
* push aside and shadow any existing ModelPort registry).
|
||||
*
|
||||
* The configuration is similar to MockSegmentation, using a test spec
|
||||
* given as GenNode-tree to define Segments of the timeline and possibly
|
||||
* pipeline-IDs and prerequisites. One notable difference is that here
|
||||
* the default ctor always creates a single Segment covering the whole
|
||||
* time axis, and that the ExitNode specification is automatically
|
||||
* duplicated for all faked ModelPort(s).
|
||||
*/
|
||||
class MockDispatcher
|
||||
: public Dispatcher
|
||||
{
|
||||
|
|
@ -285,8 +337,9 @@ namespace test {
|
|||
const PortIdxMap portIdx_;
|
||||
|
||||
public:
|
||||
/* == mock Dispatcher implementation == */
|
||||
/* == mock implementation of the Dispatcher interface == */
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete
|
||||
FrameCoord
|
||||
locateRelative (FrameCoord const&, FrameCnt frameOffset) override
|
||||
{
|
||||
|
|
@ -298,7 +351,7 @@ namespace test {
|
|||
{
|
||||
UNIMPLEMENTED ("determine when to finish a planning chunk");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1276 : likely to become obsolete
|
||||
|
||||
size_t
|
||||
resolveModelPort (ModelPort modelPort) override
|
||||
|
|
@ -319,6 +372,7 @@ namespace test {
|
|||
}
|
||||
|
||||
|
||||
public:
|
||||
MockDispatcher()
|
||||
: dummySetup_{}
|
||||
, mockSeg_{MakeRec().genNode()} // Node: generate a single active Segment to cover all
|
||||
|
|
@ -368,7 +422,7 @@ namespace test {
|
|||
TimeValue nominalTime{job.parameter.nominalTime};
|
||||
size_t portIDX = resolveModelPort (port);
|
||||
JobTicket& ticket = accessJobTicket (portIDX, nominalTime);
|
||||
return isnil (ticket)? DummyJob::isNopJob (job)
|
||||
return isnil (ticket)? MockJob::isNopJob (job)
|
||||
: MockJobTicket::isAssociated (job, ticket);
|
||||
}
|
||||
|
||||
|
|
@ -388,9 +442,6 @@ namespace test {
|
|||
}
|
||||
};
|
||||
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1221
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1221
|
||||
|
||||
|
||||
}}} // namespace steam::engine::test
|
||||
#endif /*STEAM_ENGINE_TEST_MOCK_DISPATCHER_H*/
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include "lib/test/test-helper.hpp"
|
||||
#include "steam/engine/mock-dispatcher.hpp"
|
||||
#include "vault/engine/nop-job-functor.hpp"
|
||||
#include "vault/engine/dummy-job.hpp"
|
||||
#include "lib/iter-tree-explorer.hpp"
|
||||
#include "lib/util-tuple.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
|
@ -43,7 +42,6 @@ namespace engine{
|
|||
namespace test {
|
||||
|
||||
using steam::fixture::Segment;
|
||||
using vault::engine::DummyJob;
|
||||
using lib::singleValIterator;
|
||||
using util::isSameObject;
|
||||
using util::seqTuple;
|
||||
|
|
@ -55,6 +53,7 @@ namespace test {
|
|||
* - creating and invoking mock render jobs
|
||||
* - a mocked JobTicket, generating mock render jobs
|
||||
* - configurable test setup for a mocked Segmentation datastructure
|
||||
* - configurable setup of a complete frame Dispatcher
|
||||
* @see JobPlanningSetup_test
|
||||
* @see Dispatcher
|
||||
* @see vault::engine::Job
|
||||
|
|
@ -95,7 +94,7 @@ namespace test {
|
|||
CHECK (MockJobTicket::isAssociated (job, ticket));
|
||||
|
||||
job.triggerJob();
|
||||
CHECK (DummyJob::was_invoked (job));
|
||||
CHECK (MockJob::was_invoked (job));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -107,21 +106,21 @@ namespace test {
|
|||
{
|
||||
Time nominalTime = lib::test::randTime();
|
||||
int additionalKey = rand() % 5000;
|
||||
Job mockJob = DummyJob::build (nominalTime, additionalKey);
|
||||
MockJob mockJob{nominalTime, additionalKey};
|
||||
CHECK (mockJob.getNominalTime() == nominalTime);
|
||||
CHECK (not DummyJob::was_invoked (mockJob));
|
||||
CHECK (not MockJob::was_invoked (mockJob));
|
||||
|
||||
mockJob.triggerJob();
|
||||
CHECK (DummyJob::was_invoked (mockJob));
|
||||
CHECK (RealClock::wasRecently (DummyJob::invocationTime (mockJob)));
|
||||
CHECK (nominalTime == DummyJob::invocationNominalTime (mockJob) );
|
||||
CHECK (additionalKey == DummyJob::invocationAdditionalKey(mockJob));
|
||||
CHECK (MockJob::was_invoked (mockJob));
|
||||
CHECK (RealClock::wasRecently (MockJob::invocationTime (mockJob)));
|
||||
CHECK (nominalTime == MockJob::invocationNominalTime (mockJob) );
|
||||
CHECK (additionalKey == MockJob::invocationAdditionalKey(mockJob));
|
||||
|
||||
Time prevInvocation = DummyJob::invocationTime (mockJob);
|
||||
Time prevInvocation = MockJob::invocationTime (mockJob);
|
||||
mockJob.triggerJob();
|
||||
CHECK (prevInvocation < DummyJob::invocationTime (mockJob)); // invoked again, recorded new invocation time
|
||||
CHECK (nominalTime == DummyJob::invocationNominalTime (mockJob) ); // all other Job parameter recorded again unaltered
|
||||
CHECK (additionalKey == DummyJob::invocationAdditionalKey(mockJob));
|
||||
CHECK (prevInvocation < MockJob::invocationTime (mockJob)); // invoked again, recorded new invocation time
|
||||
CHECK (nominalTime == MockJob::invocationNominalTime (mockJob) ); // all other Job parameter recorded again unaltered
|
||||
CHECK (additionalKey == MockJob::invocationAdditionalKey(mockJob));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -182,12 +181,12 @@ namespace test {
|
|||
Job someJob = ticket.createJobFor(coord); // JobTicket uses, but does not check the time given in FrameCoord
|
||||
CHECK (someJob.parameter.nominalTime == _raw(coord.absoluteNominalTime));
|
||||
CHECK (MockJobTicket::isAssociated (someJob, ticket)); // but the generated Job is linked to the Closure backed by the JobTicket
|
||||
CHECK (not DummyJob::was_invoked (someJob));
|
||||
CHECK (not MockJob::was_invoked (someJob));
|
||||
|
||||
someJob.triggerJob();
|
||||
CHECK (DummyJob::was_invoked (someJob));
|
||||
CHECK (RealClock::wasRecently (DummyJob::invocationTime (someJob)));
|
||||
CHECK (someTime == DummyJob::invocationNominalTime (someJob));
|
||||
CHECK (MockJob::was_invoked (someJob));
|
||||
CHECK (RealClock::wasRecently (MockJob::invocationTime (someJob)));
|
||||
CHECK (someTime == MockJob::invocationNominalTime (someJob));
|
||||
}
|
||||
//-----------------------------------------------------------------/// Segmentation with a segment spanning part of the timeline > 10s
|
||||
{
|
||||
|
|
@ -214,9 +213,9 @@ namespace test {
|
|||
CHECK (marker == job.parameter.invoKey.part.a);
|
||||
|
||||
job.triggerJob();
|
||||
CHECK (DummyJob::was_invoked (job));
|
||||
CHECK (RealClock::wasRecently (DummyJob::invocationTime (job)));
|
||||
CHECK (marker == DummyJob::invocationAdditionalKey (job)); // DummyClosure is rigged such as to feed back the seed in `part.a`
|
||||
CHECK (MockJob::was_invoked (job));
|
||||
CHECK (RealClock::wasRecently (MockJob::invocationTime (job)));
|
||||
CHECK (marker == MockJob::invocationAdditionalKey (job)); // DummyClosure is rigged such as to feed back the seed in `part.a`
|
||||
// and thus we can prove this job really belongs to the marked segment
|
||||
// create another job from the (empty) seg1
|
||||
job = seg1.jobTicket(0).createJobFor (coord);
|
||||
|
|
@ -250,7 +249,7 @@ namespace test {
|
|||
|
||||
Job job = s2.jobTicket(0).createJobFor(coord);
|
||||
job.triggerJob();
|
||||
CHECK (marker == DummyJob::invocationAdditionalKey (job));
|
||||
CHECK (marker == MockJob::invocationAdditionalKey (job));
|
||||
}
|
||||
//-----------------------------------------------------------------/// Segmentation with several segments built in specific order
|
||||
{
|
||||
|
|
@ -293,10 +292,10 @@ namespace test {
|
|||
|
||||
Job job = segment.jobTicket(0).createJobFor(coord);
|
||||
job.triggerJob();
|
||||
CHECK (DummyJob::was_invoked (job));
|
||||
CHECK (RealClock::wasRecently (DummyJob::invocationTime (job)));
|
||||
CHECK (MockJob::was_invoked (job));
|
||||
CHECK (RealClock::wasRecently (MockJob::invocationTime (job)));
|
||||
|
||||
return DummyJob::invocationAdditionalKey (job);
|
||||
return MockJob::invocationAdditionalKey (job);
|
||||
};
|
||||
CHECK (2 == probeKey(s1)); // verify all generated jobs are wired back to the correct segment
|
||||
CHECK (3 == probeKey(s2));
|
||||
|
|
@ -339,8 +338,8 @@ namespace test {
|
|||
|
||||
job1.triggerJob();
|
||||
job2.triggerJob();
|
||||
CHECK (23 == DummyJob::invocationAdditionalKey (job1));
|
||||
CHECK (11 == DummyJob::invocationAdditionalKey (job2));
|
||||
CHECK (23 == MockJob::invocationAdditionalKey (job1));
|
||||
CHECK (11 == MockJob::invocationAdditionalKey (job2));
|
||||
}
|
||||
//-----------------------------------------------------------------/// a tree of deep nested prerequisites
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#include "vault/real-clock.hpp"
|
||||
#include "vault/engine/scheduler-frontend.hpp"
|
||||
#include "vault/engine/scheduler-diagnostics.hpp"
|
||||
#include "vault/engine/dummy-job.hpp"
|
||||
#include "steam/engine/mock-dispatcher.hpp"
|
||||
|
||||
|
||||
namespace vault {
|
||||
|
|
@ -44,6 +44,8 @@ namespace test {
|
|||
using lib::time::Offset;
|
||||
using lib::time::FSecs;
|
||||
|
||||
using steam::engine::test::MockJob;
|
||||
|
||||
|
||||
namespace { // test fixture: scheduling a dummy job operation...
|
||||
|
||||
|
|
@ -92,7 +94,7 @@ namespace test {
|
|||
{
|
||||
SchedulerDiagnostics monitor(scheduler);
|
||||
|
||||
Job job = DummyJob::build();
|
||||
MockJob job;
|
||||
Time deadline(TEST_START_TIME);
|
||||
|
||||
scheduler.startJobTransaction()
|
||||
|
|
@ -112,8 +114,8 @@ namespace test {
|
|||
|
||||
JobTransaction tx = scheduler.startJobTransaction();
|
||||
|
||||
Job job1 = DummyJob::build();
|
||||
Job job2 = DummyJob::build();
|
||||
MockJob job1;
|
||||
MockJob job2;
|
||||
|
||||
tx.addFreewheeling(job1);
|
||||
tx.addBackground (job2);
|
||||
|
|
@ -178,7 +180,7 @@ namespace test {
|
|||
Time nominalTime(dummyFrameStart(frameNr));
|
||||
Time deadline(TEST_START_TIME + nominalTime);
|
||||
|
||||
Job job = DummyJob::build(nominalTime, frameNr);
|
||||
MockJob job{nominalTime, frameNr};
|
||||
|
||||
currentTx.addJob (deadline, job);
|
||||
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
DUMMY-JOB.hpp - diagnostic job for unit tests
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2013, 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 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
/** @file dummy-job.hpp
|
||||
** Unit test helper to generate dummy render jobs.
|
||||
** Render Jobs generated from this setup will not actually perform
|
||||
** any action, other than recording this invocation and the used
|
||||
** parameters into a map table managed behind the scenes. Using
|
||||
** the provided query function, it is possible to probe for such
|
||||
** an invocation and to extract the recorded parameter data.
|
||||
**
|
||||
** This setup is used both for stand-alone tests, which just require
|
||||
** "some job", but also as part of a complete hierarchy of mocked
|
||||
** data structures related to frame job dispatch and invocation
|
||||
** @see mock-dispatcher.hpp
|
||||
** @see MockSupport_test
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#ifndef VAULT_ENGINE_DUMMY_JOB_H
|
||||
#define VAULT_ENGINE_DUMMY_JOB_H
|
||||
|
||||
|
||||
|
||||
#include "vault/engine/job.h"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
|
||||
|
||||
namespace vault{
|
||||
namespace engine {
|
||||
|
||||
using lib::time::Time;
|
||||
|
||||
|
||||
/**
|
||||
* Test helper: generate test dummy jobs with built-in diagnostics.
|
||||
* Each invocation of such a dummy job will be logged internally
|
||||
* and can be investigated and verified afterwards.
|
||||
*/
|
||||
struct DummyJob
|
||||
{
|
||||
static Job build(); ///< uses random job definition values
|
||||
static Job build (Time nominalTime, int additionalKey);
|
||||
|
||||
static bool was_invoked (Job const& job);
|
||||
static Time invocationTime (Job const& job);
|
||||
static Time invocationNominalTime (Job const& job);
|
||||
static int invocationAdditionalKey (Job const& job);
|
||||
|
||||
static JobClosure& getFunctor();
|
||||
static bool isNopJob (Job const&);
|
||||
};
|
||||
|
||||
}} // namespace vault::engine
|
||||
#endif
|
||||
|
|
@ -70119,7 +70119,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1681742255171" ID="ID_1531898349" MODIFIED="1681744077783" TEXT="Draft im Test-Setup">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#435e98" CREATED="1681742836996" FOLDED="true" ID="ID_1978512771" MODIFIED="1686608177837" TEXT="scaffolding and mocking used for this test">
|
||||
<node COLOR="#435e98" CREATED="1681742836996" FOLDED="true" ID="ID_1978512771" MODIFIED="1686679637400" TEXT="scaffolding and mocking used for this test">
|
||||
<icon BUILTIN="full-1"/>
|
||||
<node CREATED="1681742863121" ID="ID_101929835" MODIFIED="1684878277170" TEXT="benötigte Mocks">
|
||||
<icon BUILTIN="info"/>
|
||||
|
|
@ -70128,9 +70128,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1684878221645" ID="ID_1469919037" MODIFIED="1684878223961" TEXT="neu bauen"/>
|
||||
<node CREATED="1684878224453" ID="ID_1519678460" LINK="#ID_1176991982" MODIFIED="1684878249666" TEXT="dabei Grundlage schaffen: SplitSplice-Algo"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1681742879175" ID="ID_1375353236" MODIFIED="1684878270195" TEXT="Dispatcher">
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<node COLOR="#338800" CREATED="1681742879175" ID="ID_1375353236" MODIFIED="1686679650140" TEXT="Dispatcher">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1681743458393" ID="ID_891681445" MODIFIED="1681743469323" TEXT="extrahieren aus DispatcherInterface_test"/>
|
||||
<node CREATED="1686679652411" ID="ID_111433590" MODIFIED="1686679666968" TEXT="MockDispatcher nun integriert mit dem sonstigen Mock setup"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1681742890385" ID="ID_1681918468" MODIFIED="1684878273498" TEXT="JobTicket">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
|
|
@ -70277,7 +70278,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1682384630010" ID="ID_1719484347" MODIFIED="1682385357439" TEXT="Struktur">
|
||||
<node COLOR="#435e98" CREATED="1682384630010" ID="ID_1719484347" MODIFIED="1686679804479" TEXT="Test-Spezifikation">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<icon BUILTIN="info"/>
|
||||
<node CREATED="1682384645189" ID="ID_384048903" MODIFIED="1682384657607" TEXT="1 Record pro Segment">
|
||||
<node CREATED="1682384866271" ID="ID_1100765917" MODIFIED="1682384873170" TEXT="start=Time"/>
|
||||
|
|
@ -70316,7 +70318,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="button_cancel"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1682384817342" ID="ID_1041945883" MODIFIED="1683809828917" TEXT="Channel-Zuordnung nur per Filter/Marker">
|
||||
<node COLOR="#5b280f" CREATED="1682384817342" ID="ID_1041945883" MODIFIED="1686679760838" TEXT="Channel-Zuordnung nur per Filter/Marker">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
|
|
@ -70327,17 +70329,18 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node COLOR="#435e98" CREATED="1683809711717" ID="ID_1916276594" LINK="#ID_1346581014" MODIFIED="1685987685173" TEXT="Channel sind tatsächlich ModelPorts">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1683809741762" ID="ID_610603117" MODIFIED="1686581258295" TEXT="daher wandern sie vom JobTicket in das Segment">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1683809804057" ID="ID_733275282" MODIFIED="1683809818893" TEXT="Thema vorerst ignorieren (immer ein Channel und gut is)">
|
||||
<icon BUILTIN="bell"/>
|
||||
<node COLOR="#338800" CREATED="1686679744191" ID="ID_1546924020" MODIFIED="1686679756422" TEXT="Channel-Differenzierung wurde aus dem JobTicket entfernt">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1685988083711" ID="ID_1973560674" MODIFIED="1686581324371" TEXT="Differenzierung nach Channel schwer umsetzbar">
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1685988083711" ID="ID_1973560674" MODIFIED="1686679703593" TEXT="Differenzierung nach ModelPort schwer umsetzbar">
|
||||
<linktarget COLOR="#811354" DESTINATION="ID_1973560674" ENDARROW="Default" ENDINCLINATION="-1463;83;" ID="Arrow_ID_345386605" SOURCE="ID_1499657819" STARTARROW="None" STARTINCLINATION="-217;-8;"/>
|
||||
<icon BUILTIN="hourglass"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1686498710958" ID="ID_200132237" MODIFIED="1686498774995" TEXT="nicht klar ob das für die Mock-Lösung überhaupt gebraucht wird">
|
||||
|
|
@ -70379,7 +70382,6 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1685987717673" ID="ID_1636681352" MODIFIED="1685987743599" TEXT="Umgang mit ModelPorts">
|
||||
<node CREATED="1685987749304" ID="ID_771112192" MODIFIED="1685987767020" TEXT="das Haupt-Ticket ist für jeden ModelPort stets vorhanden"/>
|
||||
<node CREATED="1685987950917" ID="ID_1508383680" MODIFIED="1685988010119" TEXT="Prerequisites standardmäßig auch aufdoppeln">
|
||||
|
|
|
|||
Loading…
Reference in a new issue