Lumiera  0.pre.03
»edityourfreedom«
dispatcher-interface-test.cpp
Go to the documentation of this file.
1 /*
2  DispatcherInterface(Test) - document and verify dispatcher for frame job creation
3 
4  Copyright (C) Lumiera.org
5  2012, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
28 #include "lib/test/run.hpp"
29 #include "lib/error.hpp"
30 
31 //#include "proc/engine/procnode.hpp"
35 #include "proc/play/timings.hpp"
36 #include "lib/time/timevalue.hpp"
37 //#include "lib/time/timequant.hpp"
38 //#include "lib/format-cout.hpp"
39 #include "lib/depend.hpp"
40 #include "lib/itertools.hpp"
41 #include "lib/util-coll.hpp"
42 #include "lib/util.hpp"
43 
44 #include <functional>
45 #include <vector>
46 
47 using test::Test;
48 using util::isnil;
49 using util::last;
50 using std::vector;
51 using std::function;
52 //using std::rand;
53 
54 
55 namespace proc {
56 namespace engine{
57 namespace test {
58 
60  using lib::time::Duration;
61  using lib::time::Offset;
62  using lib::time::TimeVar;
63  using lib::time::Time;
64  using mobject::ModelPort;
65  using play::Timings;
66 
67  namespace { // used internally
68 
69  using play::PlayTestFrames_Strategy;
70  using play::ModelPorts;
71 
72  typedef play::DummyPlayConnection<play::PlayTestFrames_Strategy> DummyPlaybackSetup;
73 
74 
75  class MockDispatcherTable
76  : public Dispatcher
77  {
78 
79  DummyPlaybackSetup dummySetup_;
80 
81 
82  /* == mock Dispatcher implementation == */
83 
84  FrameCoord
85  locateRelative (FrameCoord const&, FrameCnt frameOffset)
86  {
87  UNIMPLEMENTED ("dummy implementation of the core dispatch operation");
88  }
89 
90  bool
91  isEndOfChunk (FrameCnt, ModelPort port)
92  {
93  UNIMPLEMENTED ("determine when to finish a planning chunk");
94  }
95 
96  JobTicket&
97  accessJobTicket (ModelPort, TimeValue nominalTime)
98  {
99  UNIMPLEMENTED ("dummy implementation of the model backbone / segmentation");
100  }
101 
102  public:
103 
104  ModelPort
105  provideMockModelPort()
106  {
107  ModelPorts mockModelPorts = dummySetup_.provide_testModelPorts();
108  return *mockModelPorts; // using just the first dummy port
109  }
110  };
111 
112  lib::Depend<MockDispatcherTable> mockDispatcher;
113 
114 #if false
115 #endif
116  ModelPort
117  getTestPort()
118  {
119  return mockDispatcher().provideMockModelPort();
120  }
121 
122 
123  /* == test parameters == */
124 
125  const uint START_FRAME(10);
126  const uint CHANNEL(0);
127 
128  bool continuation_has_been_triggered = false;
129 
130  } // (End) internal defs
131 
132 
133 
134 
135 
136 
137 
138  /***************************************************************/
147  {
148 
149  virtual void
150  run (Arg)
151  {
152  verify_basicDispatch();
153  verify_standardDispatcherUsage();
154  check_ContinuationBuilder();
155  }
156 
157 
161  void
163  {
164  Dispatcher& dispatcher = mockDispatcher();
165  ModelPort modelPort (getTestPort());
166  Timings timings (FrameRate::PAL);
167  ENSURE (START_FRAME == 10);
168 
169  TimeAnchor refPoint(timings, START_FRAME);
170  CHECK (refPoint == Time::ZERO + Duration(10, FrameRate::PAL));
171 
172  FrameCoord coordinates = dispatcher.onCalcStream (modelPort,CHANNEL)
173  .relativeFrameLocation (refPoint, 15);
174  CHECK (coordinates.absoluteNominalTime == Time(0,1));
175  CHECK (coordinates.absoluteFrameNumber == 25);
176  CHECK (refPoint.remainingRealTimeFor(coordinates) < Time(FSecs(25,25)));
177  CHECK (refPoint.remainingRealTimeFor(coordinates) >= Time(FSecs(24,25)));
178  CHECK (coordinates.modelPort == modelPort);
179  CHECK (coordinates.channelNr == CHANNEL);
180 
181  JobTicket& executionPlan = dispatcher.getJobTicketFor (coordinates);
182  CHECK (executionPlan.isValid());
183 
184  Job frameJob = executionPlan.createJobFor (coordinates);
185  CHECK (frameJob.getNominalTime() == coordinates.absoluteNominalTime);
186 #if false
187 #endif
188  }
189 
190 
191 
196  void
198  {
199  Dispatcher& dispatcher = mockDispatcher();
200  ModelPort modelPort (getTestPort());
201  Timings timings (FrameRate::PAL);
202 
203  TimeAnchor refPoint = TimeAnchor(timings, START_FRAME);
204 
205  JobPlanningSequence jobs = dispatcher.onCalcStream(modelPort,CHANNEL)
206  .establishNextJobs(refPoint);
207 
208  // Verify the planned Jobs
209 
210  CHECK (!isnil (jobs));
211  vector<Job> plannedChunk;
212  lib::append_all (jobs, plannedChunk);
213 
214  Duration coveredTime (Offset(refPoint, last(plannedChunk).getNominalTime()));
215  CHECK (coveredTime >= timings.getPlanningChunkDuration());
216 
220 
221 #if false
222  TimeVar frameStart (refPoint);
223  InvocationInstanceID prevInvocationID(0);
224  Offset expectedTimeIncrement (1, FrameRate::PAL);
225  for (uint i=0; i < plannedChunk.size(); ++i )
226  {
227  Job& thisJob = plannedChunk[i];
228  CHECK (prevInvocationID < thisJob.getInvocationInstanceID());
229  prevInvocationID = thisJob.getInvocationInstanceID();
230 
231  if (frameStart != thisJob.getNominalTime())
232  {
233  frameStart += expectedTimeIncrement;
234  CHECK (frameStart == thisJob.getNominalTime());
235  }
236  }
237  // now, after having passed over the whole planned chunk
238  CHECK (frameStart == Time(refPoint) + coveredTime);
239  CHECK (frameStart >= Time(refPoint) + timings.getPlanningChunkDuration());
240  CHECK (frameStart + expectedTimeIncrement > Time(refPoint) + timings.getPlanningChunkDuration());
241 #endif
242  }
243 
244 
245 
254  void
256  {
257 #if false
258  Dispatcher& dispatcher = mockDispatcher();
259  ModelPort modelPort (getTestPort());
260  Timings timings (FrameRate::PAL);
261 
262  // prepare the rest of this test to be invoked as "continuation"
263  function<void(TimeAnchor)> testFunc = verify_invocation_of_Continuation;
264 
265  TimeAnchor refPoint = TimeAnchor::build (timings, START_FRAME);
266  JobPlanningSequence jobs = dispatcher.onCalcStream(modelPort,CHANNEL)
267  .establishNextJobs(refPoint)
268  .prepareContinuation(testFunc);
269 
270  // an additional "continuation" Job has been prepared....
271  Job continuation = lib::pull_last(jobs);
272  CHECK (META_JOB == continuation.getKind());
273 
274  // the Continuation will be scheduled sufficiently ahead of the currently planned chunk's end
275  CHECK (continuation.getNominalTime() < Time(refPoint) + timings.getPlanningChunkDuration());
276 
277  // now invoke the rest of this test, which has been embedded into the continuation job.
278  // Since we passed testFunc as action for the continuation, we expect the invocation
279  // of the function verify_invocation_of_Continuation()
280  continuation_has_been_triggered = false;
281 
282  continuation.triggerJob();
283  CHECK (continuation_has_been_triggered);
284 #endif
285  }
286 
291  static void
293  {
294  Timings timings (FrameRate::PAL);
295  Duration frameDuration (1, FrameRate::PAL);
296  Time startAnchor = Time::ZERO + START_FRAME*frameDuration;
297  Duration time_to_cover = timings.getPlanningChunkDuration();
298 
299  CHECK (Time(nextRefPoint) >= startAnchor + time_to_cover);
300  CHECK (Time(nextRefPoint) < startAnchor + time_to_cover + 1*frameDuration);
301  continuation_has_been_triggered = true;
302  }
303  };
304 
305 
307  LAUNCHER (DispatcherInterface_test, "unit engine");
308 
309 
310 
311 }}} // namespace proc::engine::test
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:142
static void verify_invocation_of_Continuation(TimeAnchor nextRefPoint)
action used as "continuation" in check_ContinuationBuilder This function expects to be invoked with a...
Organising the output data calculation possibilities.
int64_t FrameCnt
Definition: job.h:94
Duration getPlanningChunkDuration() const
the minimum time span to be covered by frame calculation jobs planned in one sway.
Definition: timings.cpp:179
InvocationInstanceID getInvocationInstanceID() const
Definition: job.h:277
Offset remainingRealTimeFor(FrameCoord plannedFrame)
convenience shortcut, employing the deadline calculation in relation to current wall clock time ...
Definition: run.hpp:49
Framerate specified as frames per second.
Definition: timevalue.hpp:547
void append_all(IT iter, CON &container)
Definition: itertools.hpp:816
Service abstraction within the render engine for generating render jobs.
Individual frame rendering task, forwarding to a closure.
Definition: job.h:248
Handle denoting a point within the model, where actually output data can be pulled.
Definition: model-port.hpp:104
Access point to singletons and other kinds of dependencies designated by type.
Definition: depend.hpp:289
static const Time ZERO
Definition: timevalue.hpp:238
LAUNCHER(BuffTable_test, "unit engine")
Register this test class...
JobTicket & getJobTicketFor(FrameCoord const &location)
JobKind getKind() const
find out about the classification of this job.
Definition: job.cpp:95
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:226
Abstract Base Class for all testcases.
Definition: run.hpp:62
The process of playback or rendering is a continued series of exploration and evaluation.
Definition: time-anchor.hpp:97
Dummy and test setup of playback and rendering, omitting most of the Lumiera engine.
std::vector< string > & Arg
Definition: run.hpp:54
FrameCoord relativeFrameLocation(TimeAnchor &refPoint, FrameCnt frameCountOffset=0)
Definition: dispatcher.cpp:54
enable_if< can_direct_access_Last< COLL >, typename COLL::reference > last(COLL const &coll)
access the last element of a STL-like container.
Definition: util-coll.hpp:123
boost::rational< long > FSecs
rational representation of fractional seconds
Definition: timevalue.hpp:205
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
void triggerJob() const
Definition: job.cpp:76
bool isnil(lib::time::Duration const &dur)
Definition: timevalue.hpp:642
Job createJobFor(FrameCoord coordinates)
Definition: job-ticket.cpp:100
Singleton services and Dependency Injection.
Lumiera error handling (C++ interface).
opaque ID attached to each individual job invocation.
Definition: job.h:113
Internal abstraction: a service within the engine for translating a logical calculation stream (corre...
Definition: dispatcher.hpp:83
Offset measures a distance in time.
Definition: timevalue.hpp:283
This iterator represents a pipeline to pull planned jobs from.
effective coordinates of a frame to be calculated.
Definition: frame-coord.hpp:65
How to define a timing specification or constraint.
Time getNominalTime() const
Definition: job.h:271
Duration is the internal Lumiera time metric.
Definition: timevalue.hpp:380
Helpers for working with iterators based on the pipeline model.
Some small helpers and convenience shortcuts to ease working with collections and sequences (given by...
Proc-Layer implementation namespace root.
Definition: id-scheme.hpp:63
JobBuilder onCalcStream(ModelPort modelPort, uint channel)
Definition: dispatcher.cpp:45
render process self organisation
Definition: job.h:73
a family of time value like entities and their relationships.
Generic frame timing specification.
Definition: timings.hpp:95
ENSURE(r==&pq)
JobPlanningSequence establishNextJobs(TimeAnchor &refPoint)
Definition: dispatcher.hpp:95
execution plan for pulling a specific exit node.
Definition: job-ticket.hpp:84
static const FrameRate PAL
predefined constant for PAL framerate
Definition: timevalue.hpp:561
IT::value_type pull_last(IT iter)
Definition: itertools.hpp:825
lib::IterSource< mobject::ModelPort >::iterator ModelPorts