Lumiera  0.pre.03
»edityourfreedom«
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  {
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
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:812
Service abstraction within the render engine for generating render jobs.
Time getNominalTime() const
Definition: job.h:271
LAUNCHER(BuffTable_test,"unit engine")
Register this test class...
Individual frame rendering task, forwarding to a closure.
Definition: job.h:248
Access point to singletons and other kinds of dependencies designated by type.
Definition: depend.hpp:275
static const Time ZERO
Definition: timevalue.hpp:238
JobTicket & getJobTicketFor(FrameCoord const &location)
InvocationInstanceID getInvocationInstanceID() const
Definition: job.h:277
Lumiera's internal time value datatype.
Definition: timevalue.hpp:226
void triggerJob() const
Definition: job.cpp:76
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...
JobKind getKind() const
find out about the classification of this job.
Definition: job.cpp:95
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.
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.
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:821
lib::IterSource< mobject::ModelPort >::iterator ModelPorts