PPI: Add support for multiple notify sources per notify target
[senf.git] / PPI / Route.test.cc
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief Route.test unit tests */
25
26 //#include "Route.test.hh"
27 //#include "Route.test.ih"
28
29 // Custom includes
30 #include "Route.hh"
31 #include "DebugEvent.hh"
32 #include "DebugModules.hh"
33 #include "Module.hh"
34 #include "Setup.hh"
35
36 #include <boost/test/auto_unit_test.hpp>
37 #include <boost/test/test_tools.hpp>
38
39 #define prefix_
40 ///////////////////////////////cc.p////////////////////////////////////////
41
42 namespace ppi = senf::ppi;
43 namespace connector = ppi::connector;
44 namespace module = ppi::module;
45 namespace debug = module::debug;
46
47 namespace {
48     class RouteTester : public module::Module
49     {
50     public:
51         connector::ActiveInput activeIn;
52         connector::PassiveInput passiveIn;
53
54         connector::ActiveOutput activeOut;
55         connector::PassiveOutput passiveOut;
56
57         ppi::DebugEvent event;
58
59         ppi::ForwardingRoute * rt;
60         
61         RouteTester() : events(0), throttles(0) {
62                    route( activeIn,  activeOut  );  // non-forwarding
63             rt = & route( activeIn,  passiveOut );  // forward throttling
64                    route( passiveIn, activeOut  );  // backward throttling
65                    route( passiveIn, passiveOut );  // non-forwarding
66                    route( event,     activeOut  );  // forward event throttling
67                    route( activeIn,  event      );  // backward event throttling
68
69             passiveIn.onRequest(&RouteTester::inputRequest);
70             passiveOut.onRequest(&RouteTester::outputRequest);
71             registerEvent(&RouteTester::onEvent, event);
72
73             activeIn.onThrottle(&RouteTester::throttleRequest);
74             activeIn.onUnthrottle(&RouteTester::unthrottleRequest);
75             activeOut.onThrottle(&RouteTester::throttleRequest);
76             activeOut.onUnthrottle(&RouteTester::unthrottleRequest);
77         }
78
79         void inputRequest() {
80             activeOut(passiveIn());
81         }
82
83         void outputRequest() {
84             passiveOut(activeIn());
85         }
86
87         void onEvent() {
88             ++ events;
89         }
90
91         void throttleRequest() {
92             ++ throttles;
93         }
94         
95         void unthrottleRequest() {
96             -- throttles;
97         }
98
99         unsigned events;
100         int throttles;
101     };
102 }
103
104 BOOST_AUTO_UNIT_TEST(route)
105 {
106     debug::PassivePacketSource passiveSource;
107     debug::ActivePacketSource activeSource;
108     debug::PassivePacketSink passiveSink;
109     debug::ActivePacketSink activeSink;
110     RouteTester tester;
111
112     ppi::connect(passiveSource.output, tester.activeIn);
113     ppi::connect(activeSource.output, tester.passiveIn);
114     ppi::connect(tester.activeOut, passiveSink.input);
115     ppi::connect(tester.passiveOut, activeSink.input);
116
117     ppi::init();
118
119     senf::Packet p1 (senf::DataPacket::create());
120     senf::Packet p2 (senf::DataPacket::create());
121
122     passiveSource.submit(p1);
123     activeSource.submit(p2);
124
125     BOOST_CHECK( p2 == passiveSink.front() );
126
127     // The passive source is not throttled at this point since it has packets in queue
128
129     passiveSink.input.throttle();
130     BOOST_CHECK( passiveSink.input.throttled() );
131     BOOST_CHECK( ! tester.activeOut );
132     BOOST_CHECK_EQUAL( tester.throttles, 1 );
133     BOOST_CHECK( tester.passiveIn.throttled() );
134     BOOST_CHECK( ! activeSource );
135     BOOST_CHECK( ! tester.event.enabled() );
136
137     passiveSink.input.unthrottle();
138     BOOST_CHECK( activeSource );
139     BOOST_CHECK( tester.event.enabled() );
140     
141     // Now throttle the passive source by exhausting the queue
142     
143     BOOST_CHECK( p1 == activeSink.request() );
144     BOOST_CHECK( passiveSource.output.throttled() );
145     BOOST_CHECK( ! tester.activeIn );
146     BOOST_CHECK_EQUAL( tester.throttles, 1 );
147     BOOST_CHECK( tester.passiveOut.throttled() );
148     BOOST_CHECK( ! activeSink );
149     BOOST_CHECK( ! tester.event.enabled() );
150     
151     passiveSource.submit(p1);
152     BOOST_CHECK( activeSink );
153     BOOST_CHECK( tester.event.enabled() );
154
155     // Check correct combination of multiple throttling events
156
157     activeSink.request();
158     BOOST_CHECK( ! tester.event.enabled() );
159     passiveSink.input.throttle();
160     BOOST_CHECK( ! tester.event.enabled() );
161     passiveSource.submit(p1);
162     BOOST_CHECK( ! tester.event.enabled() );
163     passiveSink.input.unthrottle();
164     BOOST_CHECK( tester.event.enabled() );
165
166     tester.rt->autoThrottling(false);
167
168     BOOST_CHECK( p1 == activeSink.request() );
169     BOOST_CHECK( passiveSource.output.throttled() );
170     BOOST_CHECK( activeSink );
171 }
172
173 ///////////////////////////////cc.e////////////////////////////////////////
174 #undef prefix_
175
176 \f
177 // Local Variables:
178 // mode: c++
179 // fill-column: 100
180 // comment-column: 40
181 // c-file-style: "senf"
182 // indent-tabs-mode: nil
183 // ispell-local-dictionary: "american"
184 // compile-command: "scons -u test"
185 // End: