From 566f73de2abfd24b19895b72b141defb6cd9fed8 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 10 May 2023 03:59:46 +0200 Subject: [PATCH] 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()); --- src/steam/engine/job-ticket.cpp | 2 +- src/steam/engine/job-ticket.hpp | 9 ++- src/steam/fixture/segment.hpp | 6 ++ src/steam/fixture/segmentation.hpp | 8 +++ tests/core/steam/engine/mock-support-test.cpp | 68 ++++++++++++++++++- wiki/renderengine.html | 4 +- wiki/thinkPad.ichthyo.mm | 8 ++- 7 files changed, 96 insertions(+), 9 deletions(-) diff --git a/src/steam/engine/job-ticket.cpp b/src/steam/engine/job-ticket.cpp index 381c6c789..8749fb468 100644 --- a/src/steam/engine/job-ticket.cpp +++ b/src/steam/engine/job-ticket.cpp @@ -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); } diff --git a/src/steam/engine/job-ticket.hpp b/src/steam/engine/job-ticket.hpp index e09036b01..563b385e3 100644 --- a/src/steam/engine/job-ticket.hpp +++ b/src/steam/engine/job-ticket.hpp @@ -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; diff --git a/src/steam/fixture/segment.hpp b/src/steam/fixture/segment.hpp index 09d9fb70b..4e653b8e5 100644 --- a/src/steam/fixture/segment.hpp +++ b/src/steam/fixture/segment.hpp @@ -97,6 +97,12 @@ namespace fixture { REQUIRE (jobTicket_); return *jobTicket_; } + + bool + empty() const + { + return jobTicket().empty(); + } }; diff --git a/src/steam/fixture/segmentation.hpp b/src/steam/fixture/segmentation.hpp index 3fa64ccec..417dbeaae 100644 --- a/src/steam/fixture/segmentation.hpp +++ b/src/steam/fixture/segmentation.hpp @@ -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); diff --git a/tests/core/steam/engine/mock-support-test.cpp b/tests/core/steam/engine/mock-support-test.cpp index 128984ba3..16f6b0720 100644 --- a/tests/core/steam/engine/mock-support-test.cpp +++ b/tests/core/steam/engine/mock-support-test.cpp @@ -39,6 +39,7 @@ //#include using test::Test; +using util::isSameObject; //using std::rand; @@ -52,6 +53,34 @@ namespace test { } // (End) test fixture + + namespace { + template + using cnt_ = std::integral_constant; + + template + auto + _buildSeqTuple (cnt_<0>, SEQ&&) + { + return std::tuple<>{}; + } + + template + auto + _buildSeqTuple (cnt_, SEQ&& iter) + { + auto tPre = std::tie (*iter); + ++iter; + return std::tuple_cat (tPre, _buildSeqTuple (cnt_{}, std::forward (iter))); + } + } + + template + auto + seqTuple (SEQ&& iter) + { + return _buildSeqTuple (cnt_{}, std::forward (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)); } diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 56dc272f3..97343b0e7 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -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]] -
+
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~~
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index bcb738147..d9ef1a59d 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -70519,10 +70519,16 @@
 
 
 
+
+
+
+
+
+
 
 
 
-
+