Lumiera  0.pre.03
»edit your freedom«
model-port-registry-test.cpp
Go to the documentation of this file.
1 /*
2  ModelPortRegistry(Test) - verify handling of model ports
3 
4  Copyright (C)
5  2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
19 #include "lib/test/run.hpp"
20 #include "lib/test/test-helper.hpp"
22 #include "steam/asset/timeline.hpp"
23 #include "steam/asset/pipe.hpp"
24 #include "common/query.hpp"
25 #include "lib/util.hpp"
26 
27 
28 namespace steam {
29 namespace fixture {
30 namespace test {
31 
32  using util::isSameObject;
33  using util::isnil;
34 
35  using asset::Pipe;
36  using asset::PPipe;
37  using asset::Struct;
38  using asset::Timeline;
39  using asset::PTimeline;
40  using mobject::ModelPort;
41  using lumiera::Query;
42 
43  using PID = asset::ID<Pipe>;
44  using TID = asset::ID<Struct>;
45 
46  using MPDescriptor = ModelPortRegistry::ModelPortDescriptor const&;
47 
48  using mobject::LUMIERA_ERROR_INVALID_MODEL_PORT;
49  using mobject::LUMIERA_ERROR_UNCONNECTED_MODEL_PORT;
50 
51 
52  namespace { // test environment
53 
54  inline PID
55  getPipe (string id)
56  {
57  return Pipe::query ("id("+id+")");
58  }
59 
60  inline TID
61  getTimeline (string id)
62  {
63  return asset::Struct::retrieve (Query<Timeline> ("id("+id+")"))->getID();
64  }
65 
66  struct TestContext
67  {
68  ModelPortRegistry registry_;
69  ModelPortRegistry* previous_;
70 
73  : registry_()
74  , previous_(ModelPortRegistry::setActiveInstance (registry_))
75  { }
76 
79  {
80  if (previous_)
82  else
84  }
85  };
86  }
87 
88 
89 
90 
91  /*****************************************************************************/
102  class ModelPortRegistry_test : public Test
103  {
104 
105  virtual void
106  run (Arg)
107  {
108  TestContext ctx;
109 
110  fabricating_ModelPorts (ctx.registry_);
111  accessing_ModelPorts();
112  transactionalSwitch (ctx.registry_);
113  }
114 
115 
116  void
117  fabricating_ModelPorts (ModelPortRegistry& registry)
118  {
119  /* == some Assets to play with == */
120  PID pipeA = getPipe ("pipeA");
121  PID pipeB = getPipe ("pipeB");
122  TID someTimeline = getTimeline ("some_test_Timeline");
123 
124  // start out with defining some new model ports......
125  MPDescriptor p1 = registry.definePort (pipeA, someTimeline);
126  MPDescriptor p2 = registry.definePort (pipeB, someTimeline);
127 
128  CHECK (registry.contains (pipeA));
129  CHECK (registry.contains (pipeB));
130 
131  VERIFY_ERROR (DUPLICATE_MODEL_PORT, registry.definePort(pipeB, someTimeline) );
132  CHECK (registry.contains (pipeB));
133 
134  CHECK (pipeA == p1.id());
135  CHECK (pipeB == p2.id());
136  CHECK (someTimeline == p1.holder());
137  CHECK (someTimeline == p2.holder());
138 
139  registry.commit();
140  }
141 
142 
143  void
144  accessing_ModelPorts ()
145  {
146  PID pipeA = getPipe ("pipeA");
147  PID pipeB = getPipe ("pipeB");
148  PID pipeWC = getPipe ("WCpipe");
149 
150  ModelPort mp1(pipeA);
151  ModelPort mp2(pipeB);
152 
153  VERIFY_ERROR (INVALID_MODEL_PORT, ModelPort unbefitting(pipeWC) );
154 
155  ModelPort mp1x(pipeA); // can be created multiple times
156  ModelPort mp2x(mp1x); // can be copied at will
157  ModelPort mpNull; // can be default constructed (->unconnected)
158 
159  CHECK (mp1);
160  CHECK (mp2);
161  CHECK (mp1x);
162  CHECK (mp2x);
163  CHECK (!mpNull); // bool check verifies setup and connected state
164 
165  CHECK ( ModelPort::exists (pipeA)); // this is the same check, but invoked just with an pipe-ID
166  CHECK ( ModelPort::exists (pipeB));
167  CHECK (!ModelPort::exists (pipeWC));
168 
169  CHECK (mp1 == mp1x);
170  CHECK (!isSameObject (mp1, mp1x));
171  CHECK (mp1 != mp2);
172  CHECK (mp2 != mp1);
173  CHECK (mp1 != mpNull);
174  CHECK (mp2 != mpNull);
175 
176  CHECK (mp1.pipe() == pipeA);
177  CHECK (mp2.pipe() == pipeB);
178  CHECK (mp1x.pipe() == pipeA);
179  VERIFY_ERROR (UNCONNECTED_MODEL_PORT, mpNull.pipe()); // any further operations on an unconnected port will throw
180  VERIFY_ERROR (UNCONNECTED_MODEL_PORT, mpNull.holder());
181 
182  CHECK (mp1.streamType() == pipeA.streamType());
183  }
184 
185 
186  void
187  transactionalSwitch (ModelPortRegistry& registry)
188  {
189  PID pipeA = getPipe ("pipeA");
190  PID pipeB = getPipe ("pipeB");
191  PID pipeWC = getPipe ("WCpipe");
192 
193  CHECK ( ModelPort::exists (pipeB));
194  CHECK (!ModelPort::exists (pipeWC));
195 
196  CHECK (ModelPort::exists (pipeA));
197  CHECK (registry.contains (pipeA));
198  registry.remove (pipeA);
199  CHECK (!registry.contains (pipeA)); // removed from the current (pending) transaction
200  CHECK ( ModelPort::exists (pipeA)); // but not yet publicly visible
201 
202  // now create a new and differing definition of port A
203  TID anotherTimeline = getTimeline ("another_test_Timeline");
204  MPDescriptor p1 = registry.definePort (pipeA, anotherTimeline);
205  CHECK (registry.contains (pipeA));
206  CHECK (anotherTimeline == p1.holder());
207  CHECK (ModelPort(pipeA).holder() != anotherTimeline);
208 
209  registry.remove (pipeB); // some more wired definitions
210  registry.definePort (pipeWC, anotherTimeline);
211  CHECK (!registry.contains (pipeB));
212  CHECK ( registry.contains (pipeWC));
213  CHECK ( ModelPort::exists (pipeB));
214  CHECK (!ModelPort::exists (pipeWC));
215  CHECK ( registry.isRegistered (pipeB)); // this is the same as ModelPort::exists
216  CHECK (!registry.isRegistered (pipeWC)); //
217  // Note: pending transaction not yet committed
218  ModelPort portA(pipeA); // ...... thus the changes aren't reflected to client code
219  ModelPort portB(pipeB);
220  VERIFY_ERROR (INVALID_MODEL_PORT, ModelPort ineptly(pipeWC));
221  CHECK (portA);
222  CHECK (portB);
223  CHECK (portA.pipe() == pipeA);
224  CHECK (portB.pipe() == pipeB);
225  CHECK (portA.holder() != anotherTimeline);
226 
227  registry.commit();
228  CHECK ( ModelPort::exists (pipeA)); // now all our changes got publicly visible
229  CHECK (!ModelPort::exists (pipeB));
230  CHECK ( ModelPort::exists (pipeWC));
231  CHECK ( portA);
232  CHECK (!portB);
233  CHECK (portA.holder() == anotherTimeline);
234  CHECK (portA.pipe() == pipeA);
235  VERIFY_ERROR (INVALID_MODEL_PORT, portB.pipe());
236 
237  ModelPort pwc(pipeWC); // now clients may also use the now officially promoted new port
238  CHECK (pwc);
239  CHECK (pwc.pipe() == pipeWC);
240  CHECK (pwc.holder() == anotherTimeline);
241 
242  // Next: doing several changes,
243  // but finally *not* committing them...
244  CHECK ( registry.contains (pipeA));
245  CHECK (!registry.contains (pipeB));
246  CHECK ( registry.contains (pipeWC));
247  registry.remove (pipeA);
248  registry.clear(); // remove everything from the pending transaction
249  CHECK (!registry.contains (pipeA));
250  CHECK (!registry.contains (pipeB));
251  CHECK (!registry.contains (pipeWC));
252 
253  registry.definePort (pipeB, anotherTimeline);
254  CHECK ( registry.contains (pipeB));
255  CHECK (!portB); // not committed and thus not visible
256  CHECK (portA);
257  CHECK (pwc);
258 
259  registry.rollback();
260  CHECK ( registry.contains (pipeA)); // no effect to the officially visible state
261  CHECK (!registry.contains (pipeB));
262  CHECK ( registry.contains (pipeWC));
263 
264  VERIFY_ERROR(INVALID_MODEL_PORT, registry.get(pipeB) );
265  CHECK (!portB);
266  }
267  };
268 
269 
271  LAUNCHER (ModelPortRegistry_test, "unit fixture session builder");
272 
273 
274 
275 }}} // namespace steam::fixture::test
ModelPortDescriptor const & get(PID) const
basic access operation: access the descriptor of a currently valid model port.
ModelPortDescriptor const & definePort(PID pipe, StID element_exposing_this_port)
create and register a new model port entry, within the pending transaction
A "processing pipe" represented as Asset.
void clear()
schedule removal of all registry contents.
bool contains(PID) const
does the transaction currently being built already contain a model port registration for the given ID...
Basic and generic representation of an internal query.
void commit()
activate pending model port changes.
static bool exists(ID< asset::Pipe >)
check if the global model port registration contains a mapping for the given pipe-ID ...
Definition: run.hpp:40
Mutation and management facility for model ports within the builder.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Steam-Layer implementation namespace root.
structural asset corresponding to the part of the model forming a processing pipe for generating medi...
Definition: pipe.hpp:70
static StructFactory retrieve
storage for the static StructFactory instance
Definition: struct.hpp:107
ID< asset::Pipe > pipe() const
access the Pipe (ID) of the global model port registered with the ID underlying this model port...
static ModelPortRegistry * setActiveInstance(ModelPortRegistry &newRegistry)
switch the implicit link to the global ModelPort registry to point to the given implementation instan...
static void shutdown()
globally deactivate access to model ports
Management facility for tracking model ports.
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
A collection of frequently used helper functions to support unit testing.
StreamType::ID streamType() const
allows to fetch the StreamType directly just from a Pipe-ID
Definition: pipe.hpp:121
static PPipe query(string const &properties)
convenience shortcut for retrieving default configured pipes
Definition: pipe.cpp:57
Handle designating a point within the model, where actually output data can be pulled.
Definition: model-port.hpp:95
Customised refcounting smart pointer template, built upon std::shared_ptr, but forwarding type relati...
Definition: trait.hpp:71
ID< asset::Struct > holder() const
access the timeline (or similar structural element) holding a global pipe which corresponds to this m...
key abstraction: structural asset Created automatically as a sideeffect of building the structure of ...
Definition: struct.hpp:104
StreamType::ID streamType() const
convenience shortcut to access the stream type associated with the pipe-ID corresponding to this mode...
void rollback()
discard pending changes.
Generic interface to express a query for specifically typed result elements exposing some capabilitie...
Definition: query.hpp:270
void remove(PID)
remove a model port entry from the pending transaction
Top level structural element within the session.
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee&#39;s memory identities. ...
Definition: util.hpp:421