There are 12 distinct cases regarding the orientation of two intervals; The Segmentation::splitSplice() operation shall insert a new Segment and adjust / truncate / expand / split / delete existing segments such as to retain the *Invariant* (seamless segmentation covering the complete time axis)
255 lines
7.7 KiB
C++
255 lines
7.7 KiB
C++
/*
|
|
DISPATCHER-MOCK.hpp - test scaffolding to verify render job planning and dispatch
|
|
|
|
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 02139, USA.
|
|
|
|
*/
|
|
|
|
/** @file testframe.hpp
|
|
** Unit test helper to generate fake test data frames
|
|
*/
|
|
|
|
|
|
#ifndef STEAM_ENGINE_TEST_DISPATCHER_MOCK_H
|
|
#define STEAM_ENGINE_TEST_DISPATCHER_MOCK_H
|
|
|
|
|
|
////#include "steam/engine/procnode.hpp"
|
|
//#include "steam/play/dummy-play-connection.hpp"
|
|
#include "steam/fixture/segmentation.hpp"
|
|
#include "steam/mobject/model-port.hpp"
|
|
#include "steam/engine/dispatcher.hpp"
|
|
#include "steam/engine/job-ticket.hpp"
|
|
//#include "steam/play/timings.hpp"
|
|
#include "lib/time/timevalue.hpp"
|
|
////#include "lib/time/timequant.hpp"
|
|
////#include "lib/format-cout.hpp"
|
|
#include "lib/diff/gen-node.hpp"
|
|
#include "lib/depend.hpp"
|
|
#include "lib/itertools.hpp"
|
|
//#include "lib/util-coll.hpp"
|
|
#include "vault/real-clock.hpp"
|
|
#include "lib/test/test-helper.hpp"
|
|
#include "vault/engine/job.h"
|
|
#include "vault/engine/dummy-job.hpp"
|
|
#include "lib/util.hpp"
|
|
|
|
//#include <functional>
|
|
//#include <vector>
|
|
#include <tuple>
|
|
#include <deque>
|
|
|
|
//using test::Test;
|
|
//using util::isnil;
|
|
//using util::last;
|
|
//using std::vector;
|
|
//using std::function;
|
|
//using std::rand;
|
|
|
|
//#include <cstdlib>
|
|
//#include <stdint.h>
|
|
|
|
|
|
namespace steam {
|
|
namespace engine {
|
|
namespace test {
|
|
|
|
using lib::diff::GenNode;
|
|
using lib::diff::MakeRec;
|
|
// using lib::time::FrameRate;
|
|
// using lib::time::Duration;
|
|
// using lib::time::Offset;
|
|
// using lib::time::TimeVar;
|
|
using lib::time::TimeValue;
|
|
using lib::time::Time;
|
|
// using mobject::ModelPort;
|
|
// using play::Timings;
|
|
using lib::HashVal;
|
|
using std::make_tuple;
|
|
using std::deque;
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1294 : organisation of namespaces / includes??
|
|
using fixture::Segmentation;
|
|
|
|
namespace { // used internally
|
|
|
|
// using play::PlayTestFrames_Strategy;
|
|
// using play::ModelPorts;
|
|
using vault::engine::JobClosure;
|
|
using vault::engine::JobParameter;
|
|
using vault::engine::DummyJob;
|
|
|
|
// typedef play::DummyPlayConnection<play::PlayTestFrames_Strategy> DummyPlaybackSetup;
|
|
|
|
|
|
class MockDispatcherTable
|
|
: public Dispatcher
|
|
{
|
|
|
|
// DummyPlaybackSetup dummySetup_;
|
|
|
|
|
|
/* == mock Dispatcher implementation == */
|
|
|
|
FrameCoord
|
|
locateRelative (FrameCoord const&, FrameCnt frameOffset)
|
|
{
|
|
UNIMPLEMENTED ("dummy implementation of the core dispatch operation");
|
|
}
|
|
|
|
bool
|
|
isEndOfChunk (FrameCnt, ModelPort port)
|
|
{
|
|
UNIMPLEMENTED ("determine when to finish a planning chunk");
|
|
}
|
|
|
|
JobTicket&
|
|
accessJobTicket (ModelPort, TimeValue nominalTime)
|
|
{
|
|
UNIMPLEMENTED ("dummy implementation of the model backbone / segmentation");
|
|
}
|
|
|
|
public:
|
|
|
|
ModelPort
|
|
provideMockModelPort()
|
|
{
|
|
// ModelPorts mockModelPorts = dummySetup_.provide_testModelPorts();
|
|
// return *mockModelPorts; // using just the first dummy port
|
|
}
|
|
};
|
|
|
|
/// @deprecated this setup is confusing and dangerous (instance identity is ambiguous)
|
|
lib::Depend<MockDispatcherTable> mockDispatcher;
|
|
|
|
|
|
|
|
|
|
|
|
inline auto
|
|
defineBottomSpec()
|
|
{
|
|
auto emptyPrereq = lib::nilIterator<JobTicket&>();
|
|
using Iter = decltype(emptyPrereq);
|
|
using SpecTuple = std::tuple<JobFunctor&, HashVal, Iter>;
|
|
return lib::singleValIterator(
|
|
SpecTuple(DummyJob::getFunctor(), 0, emptyPrereq));
|
|
}
|
|
|
|
inline auto
|
|
defineSimpleSpec (HashVal seed) /////////////////TODO collapse with defineBottomSpec() ??
|
|
{
|
|
auto emptyPrereq = lib::nilIterator<JobTicket&>();
|
|
using Iter = decltype(emptyPrereq);
|
|
using SpecTuple = std::tuple<JobFunctor&, HashVal, Iter>;
|
|
return lib::singleValIterator(
|
|
SpecTuple(DummyJob::getFunctor(), seed, emptyPrereq));
|
|
}
|
|
|
|
}//(End)internal test helpers....
|
|
|
|
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1221
|
|
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1221
|
|
|
|
/**
|
|
* Mock for...
|
|
*
|
|
* @see JobPlanningSetup_test
|
|
* @see DispatcherInterface_test
|
|
*
|
|
*/
|
|
class MockJobTicket
|
|
: public JobTicket
|
|
{
|
|
|
|
public:
|
|
MockJobTicket()
|
|
: JobTicket{defineBottomSpec()}
|
|
{ }
|
|
|
|
MockJobTicket (HashVal seed)
|
|
: JobTicket{defineSimpleSpec (seed)}
|
|
{ }
|
|
|
|
bool verify_associated (Job const&) const;
|
|
static bool isAssociated (Job const&, JobTicket const&);
|
|
private:
|
|
};
|
|
|
|
|
|
class MockSegmentation
|
|
: public Segmentation
|
|
{
|
|
std::deque<MockJobTicket> tickets_;
|
|
|
|
public:
|
|
MockSegmentation()
|
|
: Segmentation{}
|
|
, tickets_{}
|
|
{ }
|
|
|
|
MockSegmentation (std::initializer_list<GenNode> specs)
|
|
: MockSegmentation{}
|
|
{
|
|
for (auto& spec : specs)
|
|
{
|
|
JobTicket* newTicket = nullptr;
|
|
auto seed = spec.retrieveAttribute<HashVal> ("mark");
|
|
tickets_.emplace_back (seed? *seed : HashVal(rand() % 1000));
|
|
newTicket = & tickets_.back();
|
|
|
|
auto start = spec.retrieveAttribute<Time> ("start");
|
|
auto after = spec.retrieveAttribute<Time> ("after");
|
|
Segmentation::splitSplice (start, after, newTicket);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* verify the given job instance was actually generated from this JobTicket.
|
|
* @remark this test support function actually relies on some specific rigging,
|
|
* which typically is prepared by setup of a MockJobTicket.
|
|
*/
|
|
inline bool
|
|
MockJobTicket::verify_associated (Job const& job) const
|
|
{
|
|
JobFunctor& functor = dynamic_cast<JobFunctor&> (static_cast<JobClosure&> (*job.jobClosure));
|
|
Time nominalTime {TimeValue{job.parameter.nominalTime}};
|
|
InvocationInstanceID const& invoKey = job.parameter.invoKey;
|
|
return this->isValid()
|
|
and this->verifyInstance(functor, invoKey, nominalTime);
|
|
}
|
|
|
|
/**
|
|
* convenience shortcut to perform [this test](\ref MockJobTicket::verify_associated)
|
|
* on arbitrary JobTicket and Job instances.
|
|
* @warning a positive test result however relies on some casting trickery and there is no
|
|
* guarantee this test works if the JobTicket was not created from this mock framework.
|
|
*/
|
|
inline bool
|
|
MockJobTicket::isAssociated (Job const& job, JobTicket const& ticket)
|
|
{ // should work always, since storage is the same
|
|
MockJobTicket const& backdoor = static_cast<MockJobTicket const&> (ticket);
|
|
return backdoor.verify_associated (job);
|
|
}
|
|
|
|
|
|
|
|
}}} // namespace steam::engine::test
|
|
#endif /*STEAM_ENGINE_TEST_DISPATCHER_MOCK_H*/
|