X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=PPI%2FRoute.test.cc;h=68e7ffdafc6d1c62bb92f1a8902211608a6d8d03;hb=bd9f9d3fd6fbcff0112a7bf48ab9284da9576b11;hp=2337e9ee5c52b8c6ada744c21f27208e71983758;hpb=81ffa1c459b96dd44472bcef37e1e373934ee138;p=senf.git diff --git a/PPI/Route.test.cc b/PPI/Route.test.cc index 2337e9e..68e7ffd 100644 --- a/PPI/Route.test.cc +++ b/PPI/Route.test.cc @@ -1,8 +1,8 @@ // $Id$ // -// Copyright (C) 2007 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify @@ -21,22 +21,222 @@ // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /** \file - \brief Route.test unit tests */ + \brief Route unit tests */ //#include "Route.test.hh" //#include "Route.test.ih" // Custom includes +#include #include "Route.hh" +#include "DebugEvent.hh" +#include "DebugModules.hh" +#include "Module.hh" +#include "Setup.hh" +#include "CloneSource.hh" +#include "Joins.hh" +#include "PassiveQueue.hh" +#include "../Utils/membind.hh" +#include "../Utils/senfassert.hh" -#include +#include "../Utils/auto_unit_test.hh" #include #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// +namespace ppi = senf::ppi; +namespace connector = ppi::connector; +namespace module = ppi::module; +namespace debug = module::debug; + +namespace { + class RouteTester : public module::Module + { + SENF_PPI_MODULE(RouteTester); + + public: + connector::ActiveInput<> activeIn; + connector::PassiveInput<> passiveIn; + + connector::ActiveOutput<> activeOut; + connector::PassiveOutput<> passiveOut; + + ppi::DebugEvent event; + + ppi::ForwardingRoute * rt; + + RouteTester() : events(0), throttles(0) { + route( activeIn, activeOut ); // non-forwarding + rt = & route( activeIn, passiveOut ); // forward throttling + route( passiveIn, activeOut ); // backward throttling + route( passiveIn, passiveOut ); // non-forwarding + route( event, activeOut ); // forward event throttling + route( activeIn, event ); // backward event throttling + + passiveIn.onRequest(&RouteTester::inputRequest); + passiveOut.onRequest(&RouteTester::outputRequest); + registerEvent(event, &RouteTester::onEvent); + + activeIn.onThrottle(&RouteTester::throttleRequest); + activeIn.onUnthrottle(&RouteTester::unthrottleRequest); + activeOut.onThrottle(&RouteTester::throttleRequest); + activeOut.onUnthrottle(&RouteTester::unthrottleRequest); + } + + void inputRequest() { + activeOut(passiveIn()); + } + + void outputRequest() { + passiveOut(activeIn()); + } + + void onEvent() { + ++ events; + } + + void throttleRequest() { + ++ throttles; + } + + void unthrottleRequest() { + -- throttles; + } + + unsigned events; + int throttles; + }; +} + BOOST_AUTO_UNIT_TEST(route) -{} +{ + debug::PassiveSource passiveSource; + debug::ActiveSource activeSource; + debug::PassiveSink passiveSink; + debug::ActiveSink activeSink; + RouteTester tester; + + ppi::connect(passiveSource, tester.activeIn); + ppi::connect(activeSource, tester.passiveIn); + ppi::connect(tester.activeOut, passiveSink); + ppi::connect(tester.passiveOut, activeSink); + + ppi::init(); + + senf::Packet p1 (senf::DataPacket::create()); + senf::Packet p2 (senf::DataPacket::create()); + + passiveSource.submit(p1); + activeSource.submit(p2); + + BOOST_CHECK( p2 == passiveSink.front() ); + + // The passive source is not throttled at this point since it has packets in queue + + passiveSink.input.throttle(); + BOOST_CHECK( passiveSink.input.throttled() ); + BOOST_CHECK( ! tester.activeOut ); + BOOST_CHECK_EQUAL( tester.throttles, 1 ); + BOOST_CHECK( tester.passiveIn.throttled() ); + BOOST_CHECK( ! activeSource ); + BOOST_CHECK( ! tester.event.enabled() ); + + passiveSink.input.unthrottle(); + BOOST_CHECK( activeSource ); + BOOST_CHECK( tester.event.enabled() ); + + // Now throttle the passive source by exhausting the queue + + BOOST_CHECK( p1 == activeSink.request() ); + BOOST_CHECK( passiveSource.output.throttled() ); + BOOST_CHECK( ! tester.activeIn ); + BOOST_CHECK_EQUAL( tester.throttles, 1 ); + BOOST_CHECK( tester.passiveOut.throttled() ); + BOOST_CHECK( ! activeSink ); + BOOST_CHECK( ! tester.event.enabled() ); + + passiveSource.submit(p1); + BOOST_CHECK( activeSink ); + BOOST_CHECK( tester.event.enabled() ); + + // Check correct combination of multiple throttling events + + activeSink.request(); + BOOST_CHECK( ! tester.event.enabled() ); + passiveSink.input.throttle(); + BOOST_CHECK( ! tester.event.enabled() ); + passiveSource.submit(p1); + BOOST_CHECK( ! tester.event.enabled() ); + passiveSink.input.unthrottle(); + BOOST_CHECK( tester.event.enabled() ); + + tester.rt->autoThrottling(false); + + BOOST_CHECK( p1 == activeSink.request() ); + BOOST_CHECK( passiveSource.output.throttled() ); + BOOST_CHECK( activeSink ); +} + +/////////////////////////////////////////////////// +// test connection new modules on runtime + +namespace { + void timeout() { + senf::scheduler::terminate(); + } + + // just a helper class for the test + struct ModuleConnector { + module::PriorityJoin & join_; + ModuleConnector( module::PriorityJoin & join) + : join_( join) {}; + void connect() { + queue.reset(new module::PassiveQueue); + ppi::connect( *queue, join_, 0); + } + boost::scoped_ptr queue; + }; + + class TestSink : public module::Module + { + SENF_PPI_MODULE(TestSink); + public: + connector::PassiveInput<> input; + TestSink() { + noroute(input); + input.onRequest(&TestSink::request); + } + private: + void request() { + SENF_ASSERT(input()); + } + }; +} + +BOOST_AUTO_UNIT_TEST(connect_runtime) +{ + TestSink sink; + module::ActiveFeeder feeder; + module::PriorityJoin join; + module::CloneSource source1 (senf::DataPacket::create()); + + ppi::connect( source1, join); + ppi::connect( join, feeder); + ppi::connect( feeder, sink); + + ModuleConnector moduleConnector ( join); + senf::scheduler::TimerEvent timer ( + "connect_runtime timer", + senf::membind(&ModuleConnector::connect, &moduleConnector), + senf::ClockService::now() + senf::ClockService::milliseconds(250)); + + senf::scheduler::TimerEvent timeoutTimer ( + "connect_runtime test timeoutTimer", &timeout, + senf::ClockService::now() + senf::ClockService::milliseconds(500)); + + senf::ppi::run(); +} ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_