Test-driven brainstorming: how should output mapping be used?

This commit is contained in:
Fischlurch 2010-11-23 03:40:11 +01:00
parent a43bd239cb
commit b42e5c859f
4 changed files with 164 additions and 3 deletions

View file

@ -41,7 +41,7 @@ namespace mobject {
* This is an Interface, intended to be used in the signature
* of API functions either providing or requiring a Mapping.
*/
template<class FUNC>
template<class DEF>
class OutputMapping
{
public:

View file

@ -76,6 +76,7 @@ test_components_SOURCES = \
$(testcomponents_srcdir)/proc/mobject/controller/rendersegmenttest.cpp \
$(testcomponents_srcdir)/proc/mobject/mobject-interface-test.cpp \
$(testcomponents_srcdir)/proc/mobject/mobject-ref-test.cpp \
$(testcomponents_srcdir)/proc/mobject/output-mapping-test.cpp \
$(testcomponents_srcdir)/proc/mobject/placement-basic-test.cpp \
$(testcomponents_srcdir)/proc/mobject/placement-hierarchy-test.cpp \
$(testcomponents_srcdir)/proc/mobject/placement-object-identity-test.cpp \

View file

@ -0,0 +1,160 @@
/*
OutputMapping(Test) - verify generic output designation mapping
Copyright (C) Lumiera.org
2010, 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 02139, USA.
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
//#include "proc/asset/media.hpp"
//#include "proc/mobject/session.hpp"
//#include "proc/mobject/session/testclip.hpp"
#include "proc/asset/pipe.hpp"
//#include "proc/mobject/placement.hpp"
#include "proc/mobject/output-mapping.hpp"
#include "lib/util.hpp"
//#include "proc/mobject/session/mobjectfactory.hpp" ////TODO: avoidable?
//#include <boost/format.hpp>
//#include <iostream>
//using boost::format;
//using lumiera::Time;
//using util::contains;
using util::isnil;
//using std::string;
//using std::cout;
namespace mobject {
namespace test {
//using asset::VIDEO;
using asset::Pipe;
using asset::PPipe;
namespace {
}
/*******************************************************************
* @test create a synthetic / example mapping to verify
* generic mapping behaviour
*
* @see mobject::OutputDesignation
* @see mobject::session::Binding
*/
class OutputMapping_test : public Test
{
struct DummyDef
{
};
typedef OutputMapping<DummyDef> Mapping;
virtual void
run (Arg)
{
map_and_retrieve();
instance_copy();
default_mapping();
}
void
map_and_retrieve()
{
Mapping map;
CHECK (isnil (map));
PPipe p1 = Pipe::query("id(hairy)");
PPipe p2 = Pipe::query("id(furry)");
PPipe pX = Pipe::query("");
map[p1] = p2;
CHECK (!isnil (map));
CHECK (1 == map.size());
CHECK (map[p1] == "furry");
CHECK (map[p1].isDefined());
CHECK (!map[pX].isDefined());
CHECK (!map[p2].isDefined());
VERIFY_ERROR (UNKNOWN_MAPPING, map[pX] );
}
void
instance_copy()
{
Mapping m1;
PPipe p1 = Pipe::query("id(hairy)");
PPipe p2 = Pipe::query("id(furry)");
PPipe pX = Pipe::query("");
m1[pX] = p1;
Mapping m2(m1);
CHECK (!isnil (m2));
CHECK (1 == m2.size());
CHECK (m1[p1] == "hairy");
CHECK (m2[p1] == "hairy");
m1[pX] = p2;
CHECK (m1[p1] == "furry");
CHECK (m2[p1] == "hairy");
m2 = m1;
CHECK (m1[p1] == "furry");
CHECK (m2[p1] == "furry");
m1.clear();
CHECK (isnil(m1));
CHECK (!isnil(m2));
CHECK (m2[p1] == "furry");
CHECK (!m1[p1].isDefined());
}
void
default_mapping()
{
Mapping map;
CHECK (isnil (map));
PPipe p1 = Pipe::query("stream(hairy)");
PPipe p2 = Pipe::query("stream(furry)");
CHECK (map[p1] == "master(hairy)");
CHECK (map[p2] == "master(furry)");
Query<Pipe> special_bus ("stream(furry), ord(2)");
CHECK (map[special_bus] == "master.2(furry)");
}
};
/** Register this test class... */
LAUNCHER (OutputMapping_test, "unit session");
}} // namespace mobject::test

View file

@ -3012,7 +3012,7 @@ Any external output sink is managed as a [[slot|DisplayerSlot]] in the ~OutputMa
&amp;rarr; see also the PlayerDummy
</pre>
</div>
<div title="OutputMapping" modifier="Ichthyostega" modified="201011220305" created="201011080238" tags="Model spec draft" changecount="21">
<div title="OutputMapping" modifier="Ichthyostega" modified="201011230136" created="201011080238" tags="Model spec draft" changecount="22">
<pre>An output mapping serves to //resolve//&amp;nbsp; [[output designations|OutputDesignation]].
!Mapping situations
@ -3039,7 +3039,7 @@ All these mapping steps are listed here, because they exhibit a common pattern.
* there is an //unconnected//&amp;nbsp; state.
!Implementation notes
Thus the mapping is a copyable value object, based on a associative array. It may be attached to a model object and persisted alongside. The mapping is assumed to run a defaults query when necessary. To allow for that, it should be configured with a query template (string). Frequently, special //default pipe// markers will be used at places, where no distinct pipe-~ID is explicitly specified. Besides that, invocations might supply additional predicates (e.g. {{{ord(2)}}} to denote &quot;the second stream of this kind&quot;) to hint the defaults resolution. Moreover, the mapping needs a way to retrieve the set of possible results, allowing to filter the results of the rules based default. Mappings might be defined explicitly. Instead of storing a //bottom value,// an {{{isDefined()}}} predicate might be preferable.
Thus the mapping is a copyable value object, based on a associative array. It may be attached to a model object and persisted alongside. The mapping is assumed to run a defaults query when necessary. To allow for that, it should be configured with a query template (string). Frequently, special //default pipe// markers will be used at places, where no distinct pipe-ID is explicitly specified. Besides that, invocations might supply additional predicates (e.g. {{{ord(2)}}} to denote &quot;the second stream of this kind&quot;) to hint the defaults resolution. Moreover, the mapping needs a way to retrieve the set of possible results, allowing to filter the results of the rules based default. Mappings might be defined explicitly. Instead of storing a //bottom value,// an {{{isDefined()}}} predicate might be preferable.
First and foremost, mapping can be seen as a //functional abstraction.// As it's used at implementation level, encapsulation of detail types in't the primary concern, so it's a candidate for generic programming. But there //is// a concern better to be concealed at the usage site, namely accessing the rules system. Thus mapping leads itself to the frequently used implementation pattern where there is a generic frontend as header, calling into opaque functions embedded within a separate compilation unit.
</pre>