2023-04-27 19:38:37 +02:00
/*
MockSupport ( Test ) - verify test support for fixture and job 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 0213 9 , USA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/** @file mock-support-test.cpp
* * unit test \ ref MockSupport_test
*/
# include "lib/test/run.hpp"
2023-05-23 06:40:18 +02:00
# include "lib/test/test-helper.hpp"
2023-04-27 19:38:37 +02:00
# include "steam/engine/mock-dispatcher.hpp"
2023-06-24 03:14:17 +02:00
# include "vault/gear/nop-job-functor.hpp"
2023-06-22 20:23:55 +02:00
# include "lib/iter-explorer.hpp"
2023-05-10 13:50:19 +02:00
# include "lib/util-tuple.hpp"
2023-04-27 22:30:49 +02:00
# include "lib/util.hpp"
2023-05-23 06:40:18 +02:00
2023-04-27 19:38:37 +02:00
using test : : Test ;
2023-05-10 13:50:19 +02:00
2023-04-27 19:38:37 +02:00
namespace steam {
namespace engine {
namespace test {
2023-05-10 14:57:41 +02:00
using steam : : fixture : : Segment ;
2023-05-15 23:25:29 +02:00
using lib : : singleValIterator ;
2023-05-10 14:57:41 +02:00
using util : : isSameObject ;
using util : : seqTuple ;
2023-05-10 03:59:46 +02:00
2023-04-27 19:38:37 +02:00
/**********************************************************************/ /**
* @ test validate test support for render job planning and dispatch .
* - creating and invoking mock render jobs
* - a mocked JobTicket , generating mock render jobs
* - configurable test setup for a mocked Segmentation datastructure
2023-06-13 20:23:33 +02:00
* - configurable setup of a complete frame Dispatcher
2023-06-17 03:10:57 +02:00
* @ see JobPlanningPipeline_test
2023-04-27 19:38:37 +02:00
* @ see Dispatcher
2023-06-24 03:14:17 +02:00
* @ see vault : : gear : : Job
2023-04-27 19:38:37 +02:00
* @ see steam : : fixture : : Segmentation
*/
class MockSupport_test : public Test
{
virtual void
2023-05-10 14:57:41 +02:00
run ( Arg )
2023-04-27 19:38:37 +02:00
{
simpleUsage ( ) ;
verify_MockJob ( ) ;
verify_MockJobTicket ( ) ;
verify_MockSegmentation ( ) ;
2023-05-11 22:47:56 +02:00
verify_MockPrerequisites ( ) ;
2023-06-12 23:15:39 +02:00
verify_MockDispatcherSetup ( ) ;
2023-04-27 19:38:37 +02:00
}
/** @test simple usage example of the test helpers */
void
simpleUsage ( )
{
2023-05-10 14:57:41 +02:00
// Build a simple Segment at [10s ... 20s[
MockSegmentation mockSegs { MakeRec ( )
. attrib ( " start " , Time { 0 , 10 }
, " after " , Time { 0 , 20 } )
. genNode ( ) } ;
CHECK ( 3 = = mockSegs . size ( ) ) ;
fixture : : Segment const & seg = mockSegs [ Time { 0 , 15 } ] ; // access anywhere 10s <= t < 20s
2023-06-16 04:09:38 +02:00
JobTicket & ticket = seg . jobTicket ( 0 ) ;
2023-05-10 14:57:41 +02:00
2023-06-18 03:50:48 +02:00
Job job = ticket . createJobFor ( Time { 0 , 15 } ) ;
2023-05-10 14:57:41 +02:00
CHECK ( MockJobTicket : : isAssociated ( job , ticket ) ) ;
job . triggerJob ( ) ;
2023-06-13 20:23:33 +02:00
CHECK ( MockJob : : was_invoked ( job ) ) ;
2023-04-27 19:38:37 +02:00
}
2023-05-10 14:57:41 +02:00
2023-04-27 19:38:37 +02:00
/** @test document and verify usage of a mock render job */
void
verify_MockJob ( )
{
Time nominalTime = lib : : test : : randTime ( ) ;
int additionalKey = rand ( ) % 5000 ;
2023-06-13 20:23:33 +02:00
MockJob mockJob { nominalTime , additionalKey } ;
2023-04-27 19:38:37 +02:00
CHECK ( mockJob . getNominalTime ( ) = = nominalTime ) ;
2023-06-13 20:23:33 +02:00
CHECK ( not MockJob : : was_invoked ( mockJob ) ) ;
2023-04-27 19:38:37 +02:00
mockJob . triggerJob ( ) ;
2023-06-13 20:23:33 +02:00
CHECK ( MockJob : : was_invoked ( mockJob ) ) ;
CHECK ( RealClock : : wasRecently ( MockJob : : invocationTime ( mockJob ) ) ) ;
CHECK ( nominalTime = = MockJob : : invocationNominalTime ( mockJob ) ) ;
CHECK ( additionalKey = = MockJob : : invocationAdditionalKey ( mockJob ) ) ;
2023-04-27 19:38:37 +02:00
2023-06-13 20:23:33 +02:00
Time prevInvocation = MockJob : : invocationTime ( mockJob ) ;
2023-04-27 19:38:37 +02:00
mockJob . triggerJob ( ) ;
2023-06-13 20:23:33 +02:00
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 ) ) ;
2023-04-27 19:38:37 +02:00
}
/** @test document and verify usage of a mock JobTicket for frame dispatch */
void
verify_MockJobTicket ( )
{
2023-06-18 03:50:48 +02:00
auto frameTime = lib : : test : : randTime ( ) ;
2023-05-01 01:48:36 +02:00
// build a render job to do nothing....
2023-06-18 03:50:48 +02:00
Job nopJob = JobTicket : : NOP . createJobFor ( frameTime ) ;
2023-06-24 03:14:17 +02:00
CHECK ( INSTANCEOF ( vault : : gear : : NopJobFunctor , static_cast < JobClosure * > ( nopJob . jobClosure ) ) ) ; //////////TICKET #1287 : fix actual interface down to JobFunctor (after removing C structs)
2023-06-18 03:50:48 +02:00
CHECK ( nopJob . parameter . nominalTime = = frameTime ) ;
2023-05-01 14:07:21 +02:00
InvocationInstanceID empty ; ///////////////////////////////////////////////////////////////////////TICKET #1287 : temporary workaround until we get rid of the C base structs
CHECK ( lumiera_invokey_eq ( & nopJob . parameter . invoKey , & empty ) ) ;
2023-06-15 03:51:07 +02:00
CHECK ( MockJob : : isNopJob ( nopJob ) ) ; // this diagnostic helper checks the same conditions as done here explicitly
2023-05-01 01:48:36 +02:00
2023-04-30 02:18:56 +02:00
MockJobTicket mockTicket ;
2023-06-15 03:51:07 +02:00
CHECK ( not mockTicket . empty ( ) ) ;
2023-06-18 03:50:48 +02:00
Job mockJob = mockTicket . createJobFor ( frameTime ) ;
2023-05-01 14:07:21 +02:00
CHECK ( mockTicket . verify_associated ( mockJob ) ) ; // proof by invocation hash : is indeed backed by this JobTicket
CHECK ( not mockTicket . verify_associated ( nopJob ) ) ; // ...while some random other job is not related
2023-06-15 03:51:07 +02:00
CHECK ( not MockJob : : isNopJob ( mockJob ) ) ;
2023-04-27 19:38:37 +02:00
}
2023-05-24 03:38:12 +02:00
2023-05-10 14:57:41 +02:00
/** @test document and verify usage of a complete mocked Segmentation
* to back frame dispatch
2023-05-24 03:38:12 +02:00
* - default constructed : empty Segmentation
* - cover the whole axis with one segment
* - partition axis and verify the association of generated jobs
* - a fully defined segment within an otherwise empty axis
* - complex partitioning ( using the » split - splice « mechanism
2023-05-10 14:57:41 +02:00
*/
2023-04-27 19:38:37 +02:00
void
verify_MockSegmentation ( )
{
2023-05-01 17:02:11 +02:00
Time someTime = lib : : test : : randTime ( ) ;
2023-05-24 03:38:12 +02:00
//
2023-05-10 03:59:46 +02:00
//-----------------------------------------------------------------/// Empty default Segmentation
2023-05-01 17:02:11 +02:00
{
MockSegmentation mockSeg ;
CHECK ( 1 = = mockSeg . size ( ) ) ;
2023-06-09 02:48:38 +02:00
JobTicket const & ticket = mockSeg [ someTime ] . jobTicket ( 0 ) ; // just probe JobTicket generated for Model-Port-Nr.0
2023-05-01 17:02:11 +02:00
CHECK ( util : : isSameObject ( ticket , JobTicket : : NOP ) ) ;
}
2023-05-10 03:59:46 +02:00
//-----------------------------------------------------------------/// Segmentation with one default segment spanning complete timeline
2023-05-01 17:02:11 +02:00
{
2023-05-05 03:46:42 +02:00
MockSegmentation mockSegs { MakeRec ( ) . genNode ( ) } ;
CHECK ( 1 = = mockSegs . size ( ) ) ;
CHECK ( Time : : MIN = = mockSegs [ someTime ] . start ( ) ) ;
CHECK ( Time : : MAX = = mockSegs [ someTime ] . after ( ) ) ;
2023-06-16 04:09:38 +02:00
JobTicket & ticket = mockSegs [ someTime ] . jobTicket ( 0 ) ;
2023-05-01 17:02:11 +02:00
CHECK ( not util : : isSameObject ( ticket , JobTicket : : NOP ) ) ;
2023-06-18 03:50:48 +02:00
Job someJob = ticket . createJobFor ( someTime ) ; // JobTicket uses, but does not check the time given
CHECK ( someJob . parameter . nominalTime = = someTime ) ;
2023-05-10 03:59:46 +02:00
CHECK ( MockJobTicket : : isAssociated ( someJob , ticket ) ) ; // but the generated Job is linked to the Closure backed by the JobTicket
2023-06-13 20:23:33 +02:00
CHECK ( not MockJob : : was_invoked ( someJob ) ) ;
2023-05-01 17:02:11 +02:00
someJob . triggerJob ( ) ;
2023-06-13 20:23:33 +02:00
CHECK ( MockJob : : was_invoked ( someJob ) ) ;
CHECK ( RealClock : : wasRecently ( MockJob : : invocationTime ( someJob ) ) ) ;
CHECK ( someTime = = MockJob : : invocationNominalTime ( someJob ) ) ;
2023-05-01 17:02:11 +02:00
}
2023-05-10 03:59:46 +02:00
//-----------------------------------------------------------------/// Segmentation with a segment spanning part of the timeline > 10s
2023-05-05 03:46:42 +02:00
{
// Marker to verify the job calls back into the right segment
int marker = rand ( ) % 1000 ;
2023-05-24 03:38:12 +02:00
//
2023-05-05 03:46:42 +02:00
// Build a Segmentation partitioned at 10s
MockSegmentation mockSegs { MakeRec ( )
. attrib ( " start " , Time { 0 , 10 }
, " mark " , marker )
. genNode ( ) } ;
CHECK ( 2 = = mockSegs . size ( ) ) ;
// since only start-time was given, the SplitSplice-Algo will attach
// the new Segment starting at 10s and expand towards +∞,
// while the left part of the axis is marked as NOP / empty
fixture : : Segment const & seg1 = mockSegs [ Time : : ZERO ] ; // access anywhere < 10s
fixture : : Segment const & seg2 = mockSegs [ Time { 0 , 20 } ] ; // access anywhere >= 10s
2023-06-09 02:48:38 +02:00
CHECK ( util : : isSameObject ( seg1 . jobTicket ( 0 ) , JobTicket : : NOP ) ) ;
CHECK ( not util : : isSameObject ( seg2 . jobTicket ( 0 ) , JobTicket : : NOP ) ) ; // this one is the active segment
2023-05-05 03:46:42 +02:00
2023-06-18 03:50:48 +02:00
Job job = seg2 . jobTicket ( 0 ) . createJobFor ( someTime ) ;
2023-06-09 02:48:38 +02:00
CHECK ( not MockJobTicket : : isAssociated ( job , seg1 . jobTicket ( 0 ) ) ) ;
CHECK ( MockJobTicket : : isAssociated ( job , seg2 . jobTicket ( 0 ) ) ) ;
2023-05-05 03:46:42 +02:00
CHECK ( marker = = job . parameter . invoKey . part . a ) ;
job . triggerJob ( ) ;
2023-06-13 20:23:33 +02:00
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`
2023-05-05 03:46:42 +02:00
// and thus we can prove this job really belongs to the marked segment
// create another job from the (empty) seg1
2023-06-18 03:50:48 +02:00
job = seg1 . jobTicket ( 0 ) . createJobFor ( someTime ) ;
2023-05-05 03:46:42 +02:00
InvocationInstanceID empty ; /////////////////////////////////////////////////////////////////////TICKET #1287 : temporary workaround until we get rid of the C base structs
2023-05-10 03:59:46 +02:00
CHECK ( lumiera_invokey_eq ( & job . parameter . invoKey , & empty ) ) ; // indicates that it's just a placeholder to mark a "NOP"-Job
2023-06-09 02:48:38 +02:00
CHECK ( seg1 . jobTicket ( 0 ) . empty ( ) ) ;
2023-05-10 03:59:46 +02:00
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 ( ) ) ;
2023-06-18 03:50:48 +02:00
Job job = s2 . jobTicket ( 0 ) . createJobFor ( someTime ) ;
2023-05-10 03:59:46 +02:00
job . triggerJob ( ) ;
2023-06-13 20:23:33 +02:00
CHECK ( marker = = MockJob : : invocationAdditionalKey ( job ) ) ;
2023-05-05 03:46:42 +02:00
}
2023-05-10 14:57:41 +02:00
//-----------------------------------------------------------------/// Segmentation with several segments built in specific order
{
// Build Segmentation by partitioning in several steps
MockSegmentation mockSegs { MakeRec ( )
. attrib ( " start " , Time { 0 , 20 } // note: inverted segment definition is rectified automatically
, " after " , Time { 0 , 10 }
, " mark " , 1 )
. genNode ( )
, MakeRec ( )
. attrib ( " after " , Time : : ZERO
, " mark " , 2 )
. genNode ( )
, MakeRec ( )
. attrib ( " start " , Time { FSecs { - 5 } }
, " mark " , 3 )
. genNode ( ) } ;
CHECK ( 5 = = mockSegs . size ( ) ) ;
auto const & [ s1 , s2 , s3 , s4 , s5 ] = seqTuple < 5 > ( mockSegs . eachSeg ( ) ) ;
CHECK ( not s1 . empty ( ) ) ;
CHECK ( not s2 . empty ( ) ) ;
CHECK ( s3 . empty ( ) ) ;
CHECK ( not s4 . empty ( ) ) ;
CHECK ( s5 . empty ( ) ) ;
CHECK ( Time : : MIN = = s1 . start ( ) ) ; // the second added segment has covered the whole negative axis
CHECK ( - Time ( 0 , 5 ) = = s1 . after ( ) ) ; // ..up to the partitioning point -5
CHECK ( - Time ( 0 , 5 ) = = s2 . start ( ) ) ; // ...while the rest was taken up by the third added segment
CHECK ( Time ( 0 , 0 ) = = s2 . after ( ) ) ;
CHECK ( Time ( 0 , 0 ) = = s3 . start ( ) ) ; // an empty gap remains between [0 ... 10[
CHECK ( Time ( 0 , 10 ) = = s3 . after ( ) ) ;
CHECK ( Time ( 0 , 10 ) = = s4 . start ( ) ) ; // here is the first added segment
CHECK ( Time ( 0 , 20 ) = = s4 . after ( ) ) ;
CHECK ( Time ( 0 , 20 ) = = s5 . start ( ) ) ; // and the remaining part of the positive axis is empty
CHECK ( Time : : MAX = = s5 . after ( ) ) ;
auto probeKey = [ & ] ( Segment const & segment )
{
if ( segment . empty ( ) ) return 0 ;
2023-06-18 03:50:48 +02:00
Job job = segment . jobTicket ( 0 ) . createJobFor ( someTime ) ;
2023-05-10 14:57:41 +02:00
job . triggerJob ( ) ;
2023-06-13 20:23:33 +02:00
CHECK ( MockJob : : was_invoked ( job ) ) ;
CHECK ( RealClock : : wasRecently ( MockJob : : invocationTime ( job ) ) ) ;
2023-05-10 14:57:41 +02:00
2023-06-13 20:23:33 +02:00
return MockJob : : invocationAdditionalKey ( job ) ;
2023-05-10 14:57:41 +02:00
} ;
CHECK ( 2 = = probeKey ( s1 ) ) ; // verify all generated jobs are wired back to the correct segment
CHECK ( 3 = = probeKey ( s2 ) ) ;
CHECK ( 0 = = probeKey ( s3 ) ) ;
CHECK ( 1 = = probeKey ( s4 ) ) ;
CHECK ( 0 = = probeKey ( s5 ) ) ;
}
2023-04-27 19:38:37 +02:00
}
2023-05-11 22:47:56 +02:00
/**
* @ test build a Segment with additional prerequisites ,
* resulting in additional JobTickets to explore and
* additional prerequisite Jobs to build for each frame .
*/
void
verify_MockPrerequisites ( )
{
2023-06-18 03:50:48 +02:00
Time someTime = lib : : test : : randTime ( ) ;
2023-05-11 22:47:56 +02:00
//-----------------------------------------------------------------/// one Segment with one additional prerequisite
{
MockSegmentation mockSegs { MakeRec ( )
. attrib ( " mark " , 11 )
. scope ( MakeRec ( )
. attrib ( " mark " , 23 )
. genNode ( ) )
. genNode ( ) } ;
CHECK ( 1 = = mockSegs . size ( ) ) ;
2023-06-13 03:47:42 +02:00
JobTicket & ticket = mockSegs [ Time : : ZERO ] . jobTicket ( 0 ) ; // Model-PortNr.0
2023-05-11 22:47:56 +02:00
auto prereq = ticket . getPrerequisites ( ) ;
CHECK ( not isnil ( prereq ) ) ;
2023-06-16 04:09:38 +02:00
JobTicket & preTicket = * prereq ;
2023-05-11 22:47:56 +02:00
+ + prereq ;
CHECK ( isnil ( prereq ) ) ;
2023-06-18 03:50:48 +02:00
Job job1 = preTicket . createJobFor ( someTime ) ;
Job job2 = ticket . createJobFor ( someTime ) ;
2023-05-11 22:47:56 +02:00
job1 . triggerJob ( ) ;
job2 . triggerJob ( ) ;
2023-06-13 20:23:33 +02:00
CHECK ( 23 = = MockJob : : invocationAdditionalKey ( job1 ) ) ;
CHECK ( 11 = = MockJob : : invocationAdditionalKey ( job2 ) ) ;
2023-05-11 22:47:56 +02:00
}
2023-05-23 06:40:18 +02:00
//-----------------------------------------------------------------/// a tree of deep nested prerequisites
2023-05-15 23:25:29 +02:00
{
MockSegmentation mockSegs { MakeRec ( )
2023-05-23 06:40:18 +02:00
. attrib ( " mark " , 11 )
. scope ( MakeRec ( )
. attrib ( " mark " , 33 )
. scope ( MakeRec ( )
. attrib ( " mark " , 55 )
. genNode ( )
, MakeRec ( )
. attrib ( " mark " , 44 )
. genNode ( )
)
. genNode ( )
, MakeRec ( )
. attrib ( " mark " , 22 )
. genNode ( ) )
2023-05-15 23:25:29 +02:00
. genNode ( ) } ;
2023-06-09 02:48:38 +02:00
auto start = singleValIterator ( mockSegs [ Time : : ZERO ] . jobTicket ( 0 ) ) ;
2023-05-15 23:25:29 +02:00
2023-05-23 06:40:18 +02:00
auto it = lib : : explore ( start )
2023-06-13 03:47:42 +02:00
. expand ( [ ] ( JobTicket & ticket )
2023-05-15 23:25:29 +02:00
{
2023-05-23 01:06:22 +02:00
return ticket . getPrerequisites ( ) ;
2023-05-23 06:40:18 +02:00
} )
2023-05-15 23:25:29 +02:00
. expandAll ( )
2023-06-16 04:09:38 +02:00
. transform ( [ & ] ( JobTicket & ticket )
2023-05-15 23:25:29 +02:00
{
2023-06-18 03:50:48 +02:00
return ticket . createJobFor ( someTime ) . parameter . invoKey . part . a ;
2023-05-15 23:25:29 +02:00
} ) ;
2023-05-23 06:40:18 +02:00
CHECK ( util : : join ( it , " - " ) = = " 11-22-33-44-55 " _expect ) ;
} // Note: Prerequisites are prepended (LinkedElements)
} // thus at each level the last ones appear first
2023-06-12 23:15:39 +02:00
/** @test verify setup of a mocked Dispatcher instance
* - by default , MockDispatcher generates a single segment
* to span the whole Time - axis and with some random yet valid pipeline - ID ,
* so that a single job ticket can be generated for each port everywhere
* - in addition , it is possible to use the same specification language
* as for Segmentation to define a more complex ( mock ) processing graph
* @ note lacklustre ModelPort handling : processing graph is just duplicated for
* each valid model port — not clear yet if we ever need something better . . .
*/
void
verify_MockDispatcherSetup ( )
{
{
MockDispatcher dispatcher ;
// automatically generates some fake connection points...
auto [ port0 , sink0 ] = dispatcher . getDummyConnection ( 0 ) ;
auto [ port1 , sink1 ] = dispatcher . getDummyConnection ( 1 ) ;
CHECK ( port0 ! = port1 ) ;
CHECK ( sink0 ! = sink1 ) ;
CHECK ( port0 . isValid ( ) ) ;
CHECK ( port1 . isValid ( ) ) ;
CHECK ( sink0 . isValid ( ) ) ;
CHECK ( sink1 . isValid ( ) ) ;
CHECK ( not ModelPort ( ) . isValid ( ) ) ;
CHECK ( not DataSink ( ) . isValid ( ) ) ;
CHECK ( 0 = = dispatcher . resolveModelPort ( port0 ) ) ;
CHECK ( 1 = = dispatcher . resolveModelPort ( port1 ) ) ;
2023-06-18 03:50:48 +02:00
Time frameTime { 0 , 30 } ;
size_t modelPortIDX = 0 ;
Job job0 = dispatcher . createJobFor ( modelPortIDX , frameTime ) ;
modelPortIDX = 1 ;
Job job1 = dispatcher . createJobFor ( modelPortIDX , frameTime ) ;
2023-06-12 23:15:39 +02:00
CHECK ( dispatcher . verify ( job0 , port0 , sink0 ) ) ;
CHECK ( dispatcher . verify ( job1 , port1 , sink1 ) ) ;
}
//-----------------------------------------------------------------/// can define multiple Segments
{
MockDispatcher dispatcher { MakeRec ( )
. attrib ( " mark " , 11 )
. genNode ( )
, MakeRec ( )
. attrib ( " mark " , 22 )
. attrib ( " start " , Time { 0 , 10 } ) // second segment covers 10s … +Time::MAX
. genNode ( ) } ;
2023-06-18 03:50:48 +02:00
size_t modelPortIDX = 1 ;
Job job0 = dispatcher . createJobFor ( modelPortIDX , Time { 0 , 5 } ) ;
Job job1 = dispatcher . createJobFor ( modelPortIDX , Time { 0 , 25 } ) ;
2023-06-12 23:15:39 +02:00
CHECK ( 11 = = job0 . parameter . invoKey . part . a ) ;
CHECK ( 22 = = job1 . parameter . invoKey . part . a ) ;
}
}
2023-04-27 19:38:37 +02:00
} ;
/** Register this test class... */
LAUNCHER ( MockSupport_test , " unit engine " ) ;
} } } // namespace steam::engine::test