switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / PPI / MultiConnectorMixin.test.cc
1 // $Id$
2 //
3 // Copyright (C) 2009
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief MultiConnectorMixin.test unit tests */
30
31 //#include "MultiConnectorMixin.test.hh"
32 //#include "MultiConnectorMixin.test.ih"
33
34 // Custom includes
35 #include "MultiConnectorMixin.hh"
36 #include "DebugModules.hh"
37 #include "Joins.hh"
38 #include "AnnotationRouter.hh"
39
40 #include <senf/Utils/auto_unit_test.hh>
41 #include <boost/test/test_tools.hpp>
42
43 #define prefix_
44 //-/////////////////////////////////////////////////////////////////////////////////////////////////
45 namespace ppi = senf::ppi;
46 namespace connector = ppi::connector;
47 namespace module = ppi::module;
48 namespace debug = module::debug;
49
50 namespace {
51
52     // Primitive join
53     class SequenceContainerModule
54         : public module::Module,
55           public module::MultiConnectorMixin<SequenceContainerModule, connector::PassiveInput<> >
56     {
57         SENF_PPI_MODULE(SequenceContainerModule);
58         typedef module::MultiConnectorMixin<SequenceContainerModule, connector::PassiveInput<> > base;
59
60     public:
61         connector::ActiveOutput<> output;
62
63         using base::connectors;
64
65         SequenceContainerModule() : count (0u)
66         {
67             noroute(output);
68         }
69
70         unsigned count;
71
72     private:
73         void connectorSetup(connector::PassiveInput<> & c)
74         {
75             route(c, output);
76             c.onRequest(boost::bind(&SequenceContainerModule::request, this, boost::ref(c)));
77             ++ count;
78         }
79
80         void connectorDestroy(connector::PassiveInput<> const & c)
81         {
82             -- count;
83         }
84
85         void request(connector::PassiveInput<> & c)
86         {
87             output(c());
88         }
89
90         friend class module::MultiConnectorMixin<SequenceContainerModule, connector::PassiveInput<> >;
91     };
92
93     // Primitive duplicator
94     class UserContainerModule
95         : public module::Module,
96           public module::MultiConnectorMixin<UserContainerModule, connector::ActiveOutput<>, void, void>
97     {
98         SENF_PPI_MODULE(UserContainerModule);
99         typedef std::vector< boost::shared_ptr<UserContainerModule::ConnectorType> > Connectors;
100     public:
101         connector::PassiveInput<> input;
102
103         UserContainerModule()
104         {
105             noroute(input);
106             input.onRequest(&UserContainerModule::request);
107         }
108
109         Connectors const & connectors() const
110         { return connectors_; }
111
112     private:
113         void connectorSetup(std::auto_ptr<ConnectorType> c)
114         {
115             route(input, *c);
116             connectors_.push_back(boost::shared_ptr<ConnectorType>(c));
117         }
118
119         void connectorDestroy(ConnectorType const * c)
120         {
121             Connectors::iterator i (
122                 std::find_if(connectors_.begin(), connectors_.end(),
123                              boost::bind(&Connectors::value_type::get,_1) == c));
124             if (i != connectors_.end())
125                 connectors_.erase(i);
126         }
127
128         void request()
129         {
130             senf::Packet p (input());
131             for (Connectors::iterator i (connectors_.begin()), i_end (connectors_.end());
132                     i != i_end; ++i)
133                 (**i)(p);
134         }
135
136         Connectors connectors_;
137
138         friend class module::MultiConnectorMixin<UserContainerModule, connector::ActiveOutput<>, void, void>;
139     };
140
141     struct IntAnnotation {
142         int value;
143         bool operator<(IntAnnotation const & other) const { return value < other.value; }
144         IntAnnotation() {}
145         IntAnnotation(int v) : value(v) {}
146     };
147
148     std::ostream & operator<<(std::ostream & os, IntAnnotation const & value)
149     { os << value.value; return os; }
150 }
151
152 SENF_AUTO_UNIT_TEST(multiConnectorMixin_sequenceContainer)
153 {
154     debug::ActiveSource source1;
155     debug::ActiveSource source2;
156     SequenceContainerModule module;
157     debug::PassiveSink sink;
158
159     ppi::connect(source1, module);
160     ppi::connect(source2, module);
161     ppi::connect(module, sink);
162     ppi::init();
163
164     senf::Packet p (senf::DataPacket::create());
165
166     source1.submit(p);
167     BOOST_CHECK_EQUAL( sink.size(), 1u );
168     BOOST_CHECK( sink.pop_front() == p );
169     source2.submit(p);
170     BOOST_CHECK_EQUAL( sink.size(), 1u );
171     BOOST_CHECK( sink.pop_front() == p );
172
173     BOOST_CHECK_EQUAL( module.connectors().size(), 2u );
174     BOOST_CHECK_EQUAL( module.count, 2u );
175     source1.output.disconnect();
176     BOOST_CHECK_EQUAL( module.connectors().size(), 1u );
177     BOOST_CHECK_EQUAL( module.count, 1u );
178 }
179
180 SENF_AUTO_UNIT_TEST(multiConnectorMixin_userContainer)
181 {
182     debug::ActiveSource source;
183     UserContainerModule module;
184     debug::PassiveSink sink1;
185     debug::PassiveSink sink2;
186
187     ppi::connect(source, module);
188     ppi::connect(module, sink1);
189     ppi::connect(module, sink2);
190     ppi::init();
191
192     senf::Packet p (senf::DataPacket::create());
193
194     source.submit(p);
195     BOOST_CHECK_EQUAL( sink1.size(), 1u );
196     BOOST_CHECK_EQUAL( sink2.size(), 1u );
197     BOOST_CHECK( sink1.pop_front() == p );
198     BOOST_CHECK( sink2.pop_front() == p );
199
200     BOOST_CHECK_EQUAL( module.connectors().size(), 2u );
201     sink1.input.disconnect();
202     BOOST_CHECK_EQUAL( module.connectors().size(), 1u );
203 }
204
205 SENF_AUTO_UNIT_TEST(multiConnectorMixin_multipleModules)
206 {
207     debug::ActiveSource source;
208     debug::PassiveSink sink;
209     module::PassiveJoin join1;
210     module::PassiveJoin join2;
211     module::AnnotationRouter<IntAnnotation> router;
212     UserContainerModule module;
213
214     ppi::connect(source, join1);
215     ppi::connect(join1, router);
216     ppi::connect(router, 1, join2);
217     ppi::connect(join2, module);
218     ppi::connect(module, sink);
219
220     senf::Packet p (senf::DataPacket::create());
221     p.annotation<IntAnnotation>().value = 1;
222
223     source.submit(p);
224     BOOST_CHECK_EQUAL( sink.size(), 1u );
225     BOOST_CHECK( sink.pop_front() == p );
226 }
227
228 //-/////////////////////////////////////////////////////////////////////////////////////////////////
229 #undef prefix_
230
231 \f
232 // Local Variables:
233 // mode: c++
234 // fill-column: 100
235 // comment-column: 40
236 // c-file-style: "senf"
237 // indent-tabs-mode: nil
238 // ispell-local-dictionary: "american"
239 // compile-command: "scons -u test"
240 // End: