1e82306acd9b7b67b116a327a2a9fe3108856546
[senf.git] / senf / PPI / Connectors.test.cc
1 // $Id$
2 //
3 // Copyright (C) 2007
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 Connectors unit tests */
30
31 //#include "Connectors.test.hh"
32 //#include "Connectors.test.ih"
33
34 // Custom includes
35 #include "Connectors.hh"
36 #include "DebugModules.hh"
37 #include "Setup.hh"
38
39 #include <senf/Utils/auto_unit_test.hh>
40 #include <boost/test/test_tools.hpp>
41
42 #define prefix_
43 //-/////////////////////////////////////////////////////////////////////////////////////////////////
44
45 namespace ppi = senf::ppi;
46 namespace debug = ppi::module::debug;
47
48 // For each type of connector we use the corresponding debug module. Additionally, we always need
49 // the corresponding connected module since otherwise the connectors cannot be connected anywhere
50 // and will be unusable.
51
52 SENF_AUTO_UNIT_TEST(connector)
53 {
54     // It doesn't matter, which type of connectors we use here since they are all based on
55     // Connector.
56
57     debug::ActiveSource source;
58     debug::PassiveSink target;
59
60     ppi::connect(source.output,target.input);
61     ppi::init();
62
63     BOOST_CHECK_EQUAL( & source.output.module(), & source );
64     BOOST_CHECK_EQUAL( & target.input.module(), & target );
65     BOOST_CHECK_EQUAL( & source.output.peer(), & target.input );
66     BOOST_CHECK_EQUAL( & target.input.peer(), & source.output );
67 }
68
69 SENF_AUTO_UNIT_TEST(passiveConnector)
70 {
71     debug::ActiveSource source;
72     debug::PassiveSink target;
73
74     ppi::connect(source.output,target.input);
75     ppi::init();
76
77     // onRequest is implicitly tested within the PassiveSink implementation which is tested
78     // in DebugModules.test.cc
79
80     target.input.throttle();
81     BOOST_CHECK( target.input.throttled() );
82     BOOST_CHECK( target.input.nativeThrottled() );
83
84     target.input.unthrottle();
85     BOOST_CHECK( ! target.input.throttled() );
86     BOOST_CHECK( ! target.input.nativeThrottled() );
87
88     BOOST_CHECK_EQUAL( & target.input.peer(), & source.output );
89 }
90
91 namespace {
92
93     bool called = false;
94
95     void handler() { called = true; }
96 }
97
98 SENF_AUTO_UNIT_TEST(activeConnector)
99 {
100     debug::ActiveSource source;
101     debug::PassiveSink target;
102
103     ppi::connect(source.output,target.input);
104     ppi::init();
105
106     source.output.onThrottle(handler);
107     BOOST_CHECK( ! called );
108     target.input.throttle();
109     BOOST_CHECK( called );
110     called = false;
111     target.input.unthrottle();
112     BOOST_CHECK( ! called );
113     source.output.onThrottle();
114     source.output.onUnthrottle(handler);
115     BOOST_CHECK( ! called );
116     target.input.throttle();
117     BOOST_CHECK( ! called );
118     target.input.unthrottle();
119     BOOST_CHECK( called );
120     source.output.onUnthrottle();
121     called = false;
122     BOOST_CHECK( ! called );
123     target.input.throttle();
124     target.input.unthrottle();
125     BOOST_CHECK( ! called );
126
127     BOOST_CHECK_EQUAL( & source.output.peer(), & target.input );
128 }
129
130 SENF_AUTO_UNIT_TEST(inputConnector)
131 {
132     debug::ActiveSource source;
133     debug::PassiveSink target;
134
135     ppi::connect(source.output,target.input);
136     ppi::init();
137
138     // operator() is implicitly tested within the Active/PassiveSink implementation which is
139     // tested in DebugModules.test.cc
140
141     // peek() is implicitly tested within the Active/PassiveSink implementation
142
143     BOOST_CHECK_EQUAL ( & target.input.peer(), & source.output );
144
145     BOOST_CHECK( target.input.begin() == target.input.end() );
146     BOOST_CHECK_EQUAL( target.input.queueSize(), 0u );
147     BOOST_CHECK( target.input.empty() );
148 }
149
150 SENF_AUTO_UNIT_TEST(outputConnector)
151 {
152     debug::ActiveSource source;
153     debug::PassiveSink target;
154
155     ppi::connect(source.output,target.input);
156     ppi::init();
157
158     // operator() is implicitly tested within the Active/PassiveSource implementation which is
159     // tested in DebugModules.test.cc
160
161     BOOST_CHECK_EQUAL( & source.output.peer(), & target.input );
162 }
163
164 namespace {
165
166     class PassiveInputTest
167         : public ppi::module::Module
168     {
169         SENF_PPI_MODULE(PassiveInputTest);
170
171     public:
172         ppi::connector::PassiveInput<> input;
173
174         PassiveInputTest() : counter() {
175             noroute(input);
176             input.onRequest(&PassiveInputTest::request);
177         }
178
179         void request() {
180             ++ counter;
181         }
182
183         unsigned counter;
184     };
185 }
186
187 SENF_AUTO_UNIT_TEST(passiveInput)
188 {
189     debug::ActiveSource source;
190     PassiveInputTest target;
191
192     ppi::connect(source,target);
193     ppi::init();
194
195     BOOST_CHECK_EQUAL( & target.input.peer(), & source.output );
196
197     target.input.throttle();
198     senf::Packet p (senf::DataPacket::create());
199     source.submit(p);
200
201     BOOST_CHECK_EQUAL( target.counter, 0u );
202     BOOST_CHECK( target.input );
203     BOOST_CHECK_EQUAL( target.input.queueSize(), 1u );
204     target.input.unthrottle();
205     BOOST_CHECK( target.input );
206     BOOST_CHECK_EQUAL( target.counter, 1u );
207
208     BOOST_CHECK( target.input() == p );
209     BOOST_CHECK( ! target.input );
210
211     source.submit(p);
212
213     BOOST_CHECK_EQUAL( target.counter, 2u );
214     BOOST_CHECK( target.input.throttled() );
215     BOOST_CHECK( target.input() == p );
216     BOOST_CHECK( ! target.input.throttled() );
217
218     target.input.qdisc(ppi::ThresholdQueueing(2,0));
219
220     source.submit(p);
221     BOOST_CHECK ( ! target.input.throttled() );
222     source.submit(p);
223     BOOST_CHECK( target.input.throttled() );
224     target.input();
225     BOOST_CHECK( target.input.throttled() );
226     target.input();
227     BOOST_CHECK( ! target.input.throttled() );
228 }
229
230 SENF_AUTO_UNIT_TEST(passiveOutput)
231 {
232     debug::PassiveSource source;
233     debug::ActiveSink target;
234
235     ppi::connect(source,target);
236     ppi::init();
237
238     senf::Packet p (senf::DataPacket::create());
239     source.submit(p);
240
241     BOOST_CHECK_EQUAL( & source.output.peer(), & target.input );
242
243     BOOST_CHECK( source.output );
244
245     source.submit(p);
246     BOOST_CHECK( target.request() == p );
247
248     // connect() is tested indirectly via ppi::connect
249 }
250
251 SENF_AUTO_UNIT_TEST(activeInput)
252 {
253     debug::PassiveSource source;
254     debug::ActiveSink target;
255
256     ppi::connect(source,target);
257     ppi::init();
258
259     BOOST_CHECK_EQUAL( & target.input.peer(), & source.output );
260
261     BOOST_CHECK ( ! target.input );
262
263     senf::Packet p (senf::DataPacket::create());
264     source.submit(p);
265
266     BOOST_CHECK( target.input );
267     BOOST_CHECK( target.request() == p );
268
269     source.submit(p);
270     target.input.request();
271     BOOST_CHECK_EQUAL( target.input.queueSize(), 1u );
272     BOOST_CHECK( target.input );
273     BOOST_CHECK( target.request() == p );
274 }
275
276 SENF_AUTO_UNIT_TEST(activeOutput)
277 {
278     debug::ActiveSource source;
279     debug::PassiveSink target;
280
281     ppi::connect(source,target);
282     ppi::init();
283
284     BOOST_CHECK_EQUAL( & source.output.peer(), & target.input );
285     BOOST_CHECK( source.output );
286     target.input.throttle();
287     BOOST_CHECK( ! source.output );
288
289     // connect() is tested indirectly via ppi::connect
290 }
291
292 namespace {
293
294     template <class PacketType = senf::DataPacket>
295     class TypedPassiveInput
296         : public ppi::module::Module
297     {
298         SENF_PPI_MODULE(TypedPassiveInput);
299
300     public:
301         ppi::connector::PassiveInput<PacketType> input;
302
303         TypedPassiveInput() {
304             noroute(input);
305             input.onRequest(&TypedPassiveInput::request);
306         }
307
308         void request() {
309             senf::IGNORE( input() );
310             senf::IGNORE( input.read() );
311         }
312     };
313
314     template <class PacketType = senf::DataPacket>
315     class TypedActiveInput
316         : public ppi::module::Module
317     {
318         SENF_PPI_MODULE(TypedActiveInput);
319
320     public:
321         ppi::connector::ActiveInput<PacketType> input;
322
323         TypedActiveInput() {
324             noroute(input);
325         }
326     };
327
328     template <class PacketType = senf::DataPacket>
329     class TypedPassiveOutput
330         : public ppi::module::Module
331     {
332         SENF_PPI_MODULE(TypedPassiveOutput);
333
334     public:
335         ppi::connector::PassiveOutput<PacketType> output;
336
337         TypedPassiveOutput() {
338             noroute(output);
339             output.onRequest(&TypedPassiveOutput::request);
340         }
341
342         void request() {
343             senf::DataPacket pkg (senf::DataPacket::create());
344             output(pkg);
345             output.write(pkg);
346         }
347     };
348
349     template <class PacketType = senf::DataPacket>
350     class TypedActiveOutput
351         : public ppi::module::Module
352     {
353         SENF_PPI_MODULE(TypedActiveOutput);
354
355     public:
356         ppi::connector::ActiveOutput<PacketType> output;
357
358         TypedActiveOutput() {
359             noroute(output);
360         }
361     };
362
363     struct MyPacketType : public senf::PacketTypeBase
364     {};
365
366     typedef senf::ConcretePacket<MyPacketType> MyPacket;
367
368 }
369
370 SENF_AUTO_UNIT_TEST(typedInput)
371 {
372     debug::ActiveSource source;
373     TypedPassiveInput<> target;
374
375     ppi::connect(source,target);
376     ppi::init();
377
378     senf::Packet p (senf::DataPacket::create());
379     source.submit(p);
380
381     BOOST_CHECK( true );
382 }
383
384 SENF_AUTO_UNIT_TEST(tyepdOutput)
385 {
386     TypedPassiveOutput<> source;
387     debug::ActiveSink target;
388
389     ppi::connect(source,target);
390     ppi::init();
391
392     senf::IGNORE( target.request() );
393
394     BOOST_CHECK( true );
395 }
396
397 SENF_AUTO_UNIT_TEST(connectorTest)
398 {
399     {
400         TypedPassiveInput<> input;
401         TypedActiveOutput<MyPacket> output;
402         BOOST_CHECK_THROW( ppi::connect(output, input),
403                            ppi::connector::IncompatibleConnectorsException );
404     }
405     {
406         TypedPassiveInput<MyPacket> input;
407         TypedActiveOutput<> output;
408         BOOST_CHECK_THROW( ppi::connect(output, input),
409                            ppi::connector::IncompatibleConnectorsException );
410     }
411     {
412         TypedPassiveInput<> input;
413         TypedActiveOutput<> output;
414         SENF_CHECK_NO_THROW( ppi::connect(output, input) );
415     }
416     {
417         TypedPassiveInput<> input;
418         debug::ActiveSource output;
419         SENF_CHECK_NO_THROW( ppi::connect(output, input) );
420     }
421     {
422         debug::ActiveSink input;
423         TypedPassiveOutput<> output;
424         SENF_CHECK_NO_THROW( ppi::connect(output, input) );
425     }
426     {
427         debug::ActiveSink input;
428         debug::PassiveSource output;
429         SENF_CHECK_NO_THROW( ppi::connect(output, input) );
430     }
431 }
432
433 SENF_AUTO_UNIT_TEST(delayedConnect)
434 {
435     {
436         debug::PassiveSource source;
437         debug::ActiveSink target;
438
439         ppi::init();
440
441         BOOST_CHECK( ! target.input );
442         BOOST_CHECK( ! target.request() );
443
444         ppi::connect(source, target);
445         ppi::init();
446
447         BOOST_CHECK( ! target.input );
448
449         senf::Packet p (senf::DataPacket::create());
450         source.submit(p);
451         BOOST_CHECK( target.request() == p );
452     }
453
454     {
455         debug::PassiveSource source;
456         debug::ActiveSink target;
457
458         ppi::init();
459
460         senf::Packet p (senf::DataPacket::create());
461         source.submit(p);
462
463         BOOST_CHECK( ! target.input );
464         BOOST_CHECK( ! target.request() );
465
466         ppi::connect(source, target);
467         ppi::init();
468
469         BOOST_CHECK( target.input );
470         BOOST_CHECK( target.request() == p );
471     }
472
473     {
474         debug::ActiveSource source;
475         debug::PassiveSink target;
476
477         ppi::init();
478
479         BOOST_CHECK( ! source.output );
480         SENF_CHECK_NO_THROW( source.output(senf::DataPacket::create()) );
481
482         ppi::connect(source, target);
483         ppi::init();
484
485         BOOST_CHECK( source.output );
486
487         senf::Packet p (senf::DataPacket::create());
488         source.submit(p);
489
490         BOOST_CHECK( target.front() == p );
491         BOOST_CHECK_EQUAL( target.size(), 1u );
492     }
493
494     {
495         debug::ActiveSource source;
496         debug::PassiveSink target;
497
498         ppi::init();
499
500         BOOST_CHECK( ! source.output );
501         SENF_CHECK_NO_THROW( source.output(senf::DataPacket::create()) );
502         target.throttle();
503
504         ppi::connect(source, target);
505         ppi::init();
506
507         BOOST_CHECK( ! source.output );
508         target.unthrottle();
509         BOOST_CHECK( source.output );
510     }
511 }
512
513 SENF_AUTO_UNIT_TEST(disconnect)
514 {
515     {
516         debug::PassiveSource source;
517         debug::ActiveSink target;
518
519         ppi::connect(source, target);
520         ppi::init();
521
522         BOOST_CHECK( ! target.input );
523
524         senf::Packet p (senf::DataPacket::create());
525         source.submit(p);
526
527         BOOST_CHECK( target.input );
528
529         target.input.disconnect();
530         ppi::init();
531
532         BOOST_CHECK( ! target.input );
533     }
534     {
535         debug::ActiveSource source;
536         debug::PassiveSink target;
537
538         ppi::connect(source, target);
539         ppi::init();
540
541         BOOST_CHECK( source.output );
542
543         source.output.disconnect();
544         ppi::init();
545
546         BOOST_CHECK( ! source.output );
547     }
548 }
549
550 //-/////////////////////////////////////////////////////////////////////////////////////////////////
551 #undef prefix_
552
553 \f
554 // Local Variables:
555 // mode: c++
556 // fill-column: 100
557 // comment-column: 40
558 // c-file-style: "senf"
559 // indent-tabs-mode: nil
560 // ispell-local-dictionary: "american"
561 // compile-command: "scons -u test"
562 // End: