Segmentation: verify standard cases..
Testcase: A simple Sementation with a single and bounded Segment As aside, figured out how to unpack an iterator such as to tie a fixed number of references through a structural binding: auto const& [s1,s2,s3] = seqTuple<3> (mockSegs.eachSeg());
This commit is contained in:
parent
e5cdb86ac3
commit
566f73de2a
7 changed files with 96 additions and 9 deletions
|
|
@ -122,7 +122,7 @@ namespace engine {
|
|||
JobTicket::createJobFor (FrameCoord coordinates) const
|
||||
{
|
||||
Time nominalTime = coordinates.absoluteNominalTime;
|
||||
if (isnil (provision_))
|
||||
if (this->empty())
|
||||
{ //////////////////////////////////////////////////////////////////////////////////TICKET #1296 : can we get away just with a do-nothing functor?
|
||||
return Job(nopFunctor(), InvocationInstanceID(), nominalTime);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,11 +150,16 @@ using lib::LUID;
|
|||
Job createJobFor (FrameCoord coordinates) const;
|
||||
|
||||
|
||||
bool
|
||||
empty() const
|
||||
{
|
||||
return isnil (provision_);
|
||||
}
|
||||
|
||||
bool
|
||||
isValid() const
|
||||
{
|
||||
if (isnil (provision_))
|
||||
return false;
|
||||
if (empty()) return false;
|
||||
|
||||
TODO ("validity self check");
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -97,6 +97,12 @@ namespace fixture {
|
|||
REQUIRE (jobTicket_);
|
||||
return *jobTicket_;
|
||||
}
|
||||
|
||||
bool
|
||||
empty() const
|
||||
{
|
||||
return jobTicket().empty();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
#include "steam/fixture/segment.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
#include "lib/iter-adapter-stl.hpp"
|
||||
#include "lib/format-string.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
|
||||
|
|
@ -111,6 +112,13 @@ namespace fixture {
|
|||
throw error::State (_Fmt{"Fixture datastructure corrupted: Time %s not covered"} % time);
|
||||
}
|
||||
|
||||
auto
|
||||
eachSeg() const ///< @return iterator to enumerate each segment in ascending time order
|
||||
{
|
||||
return lib::iter_stl::eachElm (segments_);
|
||||
}
|
||||
|
||||
|
||||
/** rework the existing Segmentation to include a new Segment as specified */
|
||||
Segment const&
|
||||
splitSplice (OptTime start, OptTime after, const engine::JobTicket* =nullptr);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
//#include <ctime>
|
||||
|
||||
using test::Test;
|
||||
using util::isSameObject;
|
||||
//using std::rand;
|
||||
|
||||
|
||||
|
|
@ -52,6 +53,34 @@ namespace test {
|
|||
|
||||
} // (End) test fixture
|
||||
|
||||
|
||||
namespace {
|
||||
template<size_t N>
|
||||
using cnt_ = std::integral_constant<size_t, N>;
|
||||
|
||||
template<class SEQ>
|
||||
auto
|
||||
_buildSeqTuple (cnt_<0>, SEQ&&)
|
||||
{
|
||||
return std::tuple<>{};
|
||||
}
|
||||
|
||||
template<size_t N, class SEQ>
|
||||
auto
|
||||
_buildSeqTuple (cnt_<N>, SEQ&& iter)
|
||||
{
|
||||
auto tPre = std::tie (*iter);
|
||||
++iter;
|
||||
return std::tuple_cat (tPre, _buildSeqTuple (cnt_<N-1>{}, std::forward<SEQ> (iter)));
|
||||
}
|
||||
}
|
||||
|
||||
template<size_t N, class SEQ>
|
||||
auto
|
||||
seqTuple (SEQ&& iter)
|
||||
{
|
||||
return _buildSeqTuple (cnt_<N>{}, std::forward<SEQ> (iter));
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
@ -142,12 +171,14 @@ namespace test {
|
|||
FrameCoord coord;
|
||||
Time someTime = lib::test::randTime();
|
||||
coord.absoluteNominalTime = someTime;
|
||||
//-----------------------------------------------------------------/// Empty default Segmentation
|
||||
{
|
||||
MockSegmentation mockSeg;
|
||||
CHECK (1 == mockSeg.size());
|
||||
JobTicket const& ticket = mockSeg[someTime].jobTicket();
|
||||
CHECK (util::isSameObject (ticket, JobTicket::NOP));
|
||||
}
|
||||
//-----------------------------------------------------------------/// Segmentation with one default segment spanning complete timeline
|
||||
{
|
||||
MockSegmentation mockSegs{MakeRec().genNode()};
|
||||
CHECK (1 == mockSegs.size());
|
||||
|
|
@ -156,8 +187,9 @@ namespace test {
|
|||
JobTicket const& ticket = mockSegs[someTime].jobTicket();
|
||||
CHECK (not util::isSameObject (ticket, JobTicket::NOP));
|
||||
|
||||
Job someJob = ticket.createJobFor(coord);
|
||||
CHECK (MockJobTicket::isAssociated (someJob, ticket));
|
||||
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));
|
||||
|
||||
someJob.triggerJob();
|
||||
|
|
@ -165,6 +197,7 @@ namespace test {
|
|||
CHECK (RealClock::wasRecently (DummyJob::invocationTime (someJob)));
|
||||
CHECK (someTime == DummyJob::invocationNominalTime (someJob));
|
||||
}
|
||||
//-----------------------------------------------------------------/// Segmentation with a segment spanning part of the timeline > 10s
|
||||
{
|
||||
// Marker to verify the job calls back into the right segment
|
||||
int marker = rand() % 1000;
|
||||
|
|
@ -195,7 +228,36 @@ namespace test {
|
|||
// create another job from the (empty) seg1
|
||||
job = seg1.jobTicket().createJobFor (coord);
|
||||
InvocationInstanceID empty; /////////////////////////////////////////////////////////////////////TICKET #1287 : temporary workaround until we get rid of the C base structs
|
||||
CHECK (lumiera_invokey_eq (&job.parameter.invoKey, &empty)); // indiate that it's just a placeholder to mark a "NOP"-Job
|
||||
CHECK (lumiera_invokey_eq (&job.parameter.invoKey, &empty)); // indicates that it's just a placeholder to mark a "NOP"-Job
|
||||
CHECK (seg1.jobTicket().empty());
|
||||
CHECK (seg1.empty());
|
||||
CHECK (not seg2.empty());
|
||||
}
|
||||
//-----------------------------------------------------------------/// Segmentation with one delineated segment, and otherwise empty
|
||||
{
|
||||
int marker = rand() % 1000;
|
||||
// Build Segmentation with one fully defined segment
|
||||
MockSegmentation mockSegs{MakeRec()
|
||||
.attrib ("start", Time{0,10}
|
||||
,"after", Time{0,20}
|
||||
,"mark", marker)
|
||||
.genNode()};
|
||||
CHECK (3 == mockSegs.size());
|
||||
auto const& [s1,s2,s3] = seqTuple<3> (mockSegs.eachSeg());
|
||||
CHECK (s1.empty());
|
||||
CHECK (not s2.empty());
|
||||
CHECK (s3.empty());
|
||||
CHECK (isSameObject (s2, mockSegs[Time{0,10}]));
|
||||
CHECK (Time::MIN == s1.start());
|
||||
CHECK (Time(0,10) == s1.after());
|
||||
CHECK (Time(0,10) == s2.start());
|
||||
CHECK (Time(0,20) == s2.after());
|
||||
CHECK (Time(0,20) == s3.start());
|
||||
CHECK (Time::MAX == s3.after());
|
||||
|
||||
Job job = s2.jobTicket().createJobFor(coord);
|
||||
job.triggerJob();
|
||||
CHECK (marker == DummyJob::invocationAdditionalKey (job));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7141,7 +7141,7 @@ The Fixture is mostly comprised of the Segementation datastructure, but some oth
|
|||
Largely the storage of the render nodes network is hooked up behind the Fixture &rarr; [[storage considerations|FixtureStorage]]
|
||||
</pre>
|
||||
</div>
|
||||
<div title="SegmentationChange" creator="Ichthyostega" modifier="Ichthyostega" created="202305020227" modified="202305021819" tags="spec operational Builder draft" changecount="28">
|
||||
<div title="SegmentationChange" creator="Ichthyostega" modifier="Ichthyostega" created="202305020227" modified="202305022134" tags="spec operational Builder draft" changecount="29">
|
||||
<pre>At the end of the build process, the existing [[Segmentation]] possibly needs to be changed, extended or adapted.
|
||||
This change must be performed as a //transactional switch,// since render or playback processes might be performed concurrently. All Fixture and low-level-Model datastructures are //immutable// -- thus for any changes, suitably adapted structures will be built as a replacement.
|
||||
|
||||
|
|
@ -7161,7 +7161,7 @@ This is an implementation level operation, which analyses the existing Segmentat
|
|||
:* //Successor// is the first one to violate this condition
|
||||
:* //otherwise// Successor == Predecessor (split)
|
||||
;Stage-2
|
||||
:establish {{{start}}} and end point of new segment
|
||||
:establish start and end point of new segment
|
||||
:* explicitly given {{{start}}}/{{{after}}}-points are binding
|
||||
:** missing {{{start}}}<br> {{{sep}}} ≡ {{{after}}}
|
||||
:*** P~~after~~ < {{{sep}}} ⟹ {{{start}}} ≔ P~~after~~
|
||||
|
|
|
|||
|
|
@ -70519,10 +70519,16 @@
|
|||
<node COLOR="#338800" CREATED="1683250843877" ID="ID_608613083" MODIFIED="1683250856171" TEXT="einfache Segmentation mit einem Segment ab 10s">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1683671441771" ID="ID_514353615" MODIFIED="1683683643566" TEXT="ein begrenztes Segment in ansonsten leerer Timeline">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1683683705942" ID="ID_1879543257" MODIFIED="1683683724904" TEXT="drei Segmente mit Lücke und partieller Überlappunt">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1683047063010" ID="ID_1142231389" MODIFIED="1683047144754" TEXT="degenerierte Fälle">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1683047076545" ID="ID_1966654915" MODIFIED="1683047109765" TEXT="weder Start noch Ende ⟹ NOP">
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1683047076545" ID="ID_1966654915" MODIFIED="1683671312706" TEXT="weder Start noch Ende ⟹ ein einziges Segment überspannt ganze Timeline">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1683047111300" ID="ID_1355900780" MODIFIED="1683047141649" TEXT="Ende vor Start ⟹ flip">
|
||||
|
|
|
|||
Loading…
Reference in a new issue