event_test.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   tag: Peter Soetens  Mon Jan 10 15:59:51 CET 2005  event_test.cpp
00003 
00004                         event_test.cpp -  description
00005                            -------------------
00006     begin                : Mon January 10 2005
00007     copyright            : (C) 2005 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.be
00009 
00010  ***************************************************************************
00011  *                                                                         *
00012  *   This program is free software; you can redistribute it and/or modify  *
00013  *   it under the terms of the GNU General Public License as published by  *
00014  *   the Free Software Foundation; either version 2 of the License, or     *
00015  *   (at your option) any later version.                                   *
00016  *                                                                         *
00017  ***************************************************************************/
00018 
00019 #include "unit.hpp"
00020 
00021 #include <internal/Signal.hpp>
00022 #include <extras/SlaveActivity.hpp>
00023 #include <string>
00024 #include <rtt-detail-fwd.hpp>
00025 #include <Logger.hpp>
00026 #include <base/RunnableInterface.hpp>
00027 #include <extras/SimulationActivity.hpp>
00028 #include <extras/SimulationThread.hpp>
00029 #include <Activity.hpp>
00030 #include <os/Atomic.hpp>
00031 
00032 #include <boost/bind.hpp>
00033 #include <boost/scoped_ptr.hpp>
00034 
00035 using namespace RTT;
00036 using namespace boost;
00037 using namespace RTT::detail;
00038 
00039 
00040 
00041 struct Runner : public RunnableInterface
00042 {
00043     bool result;
00044     int data;
00045     Signal<void(int)>& e;
00046     Handle h1;
00047     Runner( Signal<void(int)>& e_ ) : e(e_) {
00048     }
00049 
00050     bool initialize() {
00051         result = false;
00052         // connect sync and async handler with event
00053         // and run async handler in thread of this task.
00054         h1 = e.connect( boost::bind(&Runner::handle,this, _1) );
00055         return true;
00056     }
00057     void step() {
00058         e( 123456 );
00059     }
00060 
00061     // blocking implementation
00062     void loop() {
00063         e( 123456 );
00064     }
00065 
00066     bool breakLoop() {
00067         return true;
00068     }
00069 
00070     void finalize() {
00071         h1.disconnect();
00072     }
00073 
00074     void handle(int i) {
00075         data = i;
00076         if (data == 123456)
00077             result = true;
00078         else
00079             result = false;
00080     }
00081 };
00082 
00083 struct SelfRemover : public RunnableInterface
00084 {
00085     Signal<void(void)>& e;
00086     Handle h1;
00087     SelfRemover( Signal<void(void)>& e_ ) : e(e_) {
00088     }
00089 
00090     bool initialize() {
00091         // connect sync and async handler with event
00092         // and run async handler in thread of this task.
00093         h1 = e.setup( boost::bind(&SelfRemover::handle,this));
00094         return true;
00095     }
00096     void step() {
00097         h1.connect();
00098         e();
00099     }
00100 
00101     void finalize() {
00102     }
00103 
00104     void handle(void) {
00105         // do not emit within handle!
00106         // first disconnect self, then reconnect
00107         h1.disconnect();
00108         h1.connect();
00109         h1.disconnect();
00110     }
00111 };
00112 
00113 struct CrossRemover : public RunnableInterface
00114 {
00115     Signal<void(void)>& e;
00116     Handle h1;
00117     CrossRemover( Signal<void(void)>& e_ ) : e(e_), count(0) {
00118     }
00119     int count;
00120 
00121     bool initialize() {
00122         // connect sync handler with event
00123         e.connect( boost::bind(&CrossRemover::handle,this));
00124         h1 = e.connect( boost::bind(&CrossRemover::handle,this));
00125         e.connect( boost::bind(&CrossRemover::handle,this));
00126         return true;
00127     }
00128     void step() {
00129         // for syn :
00130         count = 0;
00131         e();
00132         h1.disconnect(); // disconnect !
00133     }
00134 
00135     void finalize() {
00136     }
00137 
00138     void handle(void) {
00139         if ( count == 0 ) {
00140             h1.disconnect(); // remove next handler
00141         }
00142         if ( count == 1 ){
00143             h1.connect();  // insert again
00144         }
00145     }
00146 };
00147 
00148 class EventTest
00149 {
00150 public:
00151 
00152     Signal<void( void )> t_event;
00153     Signal<void( std::string )> t_event_string;
00154     Signal<int( float, float )> t_event_float;
00155     bool t_listener_value;
00156     std::string t_listener_what;
00157     float float_sum;
00158 public:
00159 
00160     EventTest(): t_listener_value(false), float_sum(0.0) {
00161         reset();
00162     }
00163 
00164     ~EventTest(){
00165     }
00166 
00167 
00168     void listener(void)
00169     {
00170         t_listener_value = true;
00171     }
00172 
00173     void listenerString(const std::string& what)
00174     {
00175         t_listener_what = what;
00176     }
00177 
00178     int float_listener(float a, float b)
00179     {
00180         Logger::log() << Logger::Debug << "float_listener "<< a<<", "<<b<<Logger::endl;
00181         float_sum += a + b;
00182         return 1;
00183     }
00184 
00185     void reset()
00186     {
00187         t_listener_value = false;
00188         t_listener_what = "";
00189     }
00190 
00191     void float_reference(float& f) {
00192         log(Debug) << "Received f:"<<f<<endlog();
00193         f = 10.0;
00194         float_sum +=f ;
00195     }
00196 };
00197 
00198 static AtomicInt testConcurrentEmitHandlerCount;
00199 
00200 void testConcurrentEmitHandler(void)
00201 {
00202     testConcurrentEmitHandlerCount.inc();
00203 }
00204 
00205 class EmitAndcount
00206     :public RunnableInterface
00207 {
00208 public:
00209     EmitAndcount(Signal<void(void)> &ev)
00210         : mev(ev), count(0) {}
00211     Signal<void(void)> &mev;
00212     int count;
00213     bool initialize() { return true;}
00214     void step() {}
00215     void finalize() {}
00216     bool breakLoop() { return true; }
00217     void loop()
00218     {
00219         mev();
00220         ++count;
00221         this->getActivity()->trigger();
00222     }
00223 
00224 };
00225 
00226 BOOST_FIXTURE_TEST_SUITE( EventTestSuite, EventTest )
00227 
00228 BOOST_AUTO_TEST_CASE( testEmpty )
00229 {
00230     t_event();
00231 }
00232 
00233 BOOST_AUTO_TEST_CASE( testTask )
00234 {
00235     Signal<void(int)> event;
00236     Runner runobj(event);
00237     SimulationActivity task(0.01, &runobj);
00238     BOOST_CHECK(task.start());
00239     BOOST_CHECK( SimulationThread::Instance()->run(100) );
00240     BOOST_CHECK( runobj.result );
00241 }
00242 
00243 BOOST_AUTO_TEST_CASE( testSelfRemoval )
00244 {
00245     SelfRemover runobj(t_event);
00246     SimulationActivity task(0.01, &runobj);
00247     BOOST_CHECK( task.start() );
00248     BOOST_CHECK( SimulationThread::Instance()->run(100) );
00249     BOOST_CHECK( task.stop() );
00250 }
00251 
00255 BOOST_AUTO_TEST_CASE( testReference )
00256 {
00257     Signal<void(float&)> event;
00258 
00259     Handle h = event.connect( boost::bind(&testReference::float_reference, this, _1) );
00260 
00261     float f = 5.0;
00262     event.emit( f );
00263 
00264     // Note: we actually don't guarantee that this will succeed.
00265     // The current implementation allows it though. This check may
00266     // be removed in the future.
00267     BOOST_CHECK( f == 10.0 );
00268     BOOST_CHECK(float_sum == 10.0 );
00269 }
00270 
00271 BOOST_AUTO_TEST_CASE( testCrossRemoval )
00272 {
00273     CrossRemover runobj(t_event);
00274     SimulationActivity task(0.01, &runobj);
00275     BOOST_CHECK( task.start() );
00276     BOOST_CHECK( SimulationThread::Instance()->run(100) );
00277     BOOST_CHECK( task.stop() );
00278 }
00279 
00280 #ifdef OROCOS_TARGET_GNULINUX
00281 BOOST_AUTO_TEST_CASE( testConcurrentEmit )
00282 {
00283     testConcurrentEmitHandlerCount.set(0);
00284     Signal<void(void)> event;
00285     EmitAndcount arunobj(event);
00286     EmitAndcount brunobj(event);
00287     EmitAndcount crunobj(event);
00288     EmitAndcount drunobj(event);
00289     Activity atask(ORO_SCHED_OTHER, 0, 0, &arunobj);
00290     Activity btask(ORO_SCHED_OTHER, 0, 0, &brunobj);
00291     Activity ctask(ORO_SCHED_OTHER, 0, 0, &crunobj);
00292     Activity dtask(ORO_SCHED_OTHER, 0, 0, &drunobj);
00293     Handle h = event.connect( &testConcurrentEmitHandler );
00294     BOOST_CHECK( h.connected() );
00295     BOOST_CHECK( atask.start() );
00296     BOOST_CHECK( btask.start() );
00297     BOOST_CHECK( ctask.start() );
00298     BOOST_CHECK( dtask.start() );
00299     sleep(1);
00300     BOOST_CHECK( atask.stop() );
00301     BOOST_CHECK( btask.stop() );
00302     BOOST_CHECK( ctask.stop() );
00303     BOOST_CHECK( dtask.stop() );
00304     // Verify that all emits also caused the handler to be called.
00305     BOOST_CHECK_EQUAL( arunobj.count + brunobj.count + crunobj.count + drunobj.count, testConcurrentEmitHandlerCount.read() );
00306 }
00307 #endif
00308 
00309 BOOST_AUTO_TEST_CASE( testBlockingTask )
00310 {
00311     Signal<void(int)> event;
00312     Runner runobj(event);
00313     Activity task(15, &runobj);
00314     BOOST_CHECK(task.start());
00315     usleep(100000);
00316     BOOST_CHECK(task.stop());
00317 
00318     BOOST_CHECK( runobj.result );
00319 }
00320 
00321 BOOST_AUTO_TEST_CASE( testEventArgs )
00322 {
00323     float_sum = 0;
00324     Handle h1 = t_event_float.connect( boost::bind(&EventTest::float_listener, this,_1,_2) );
00325 
00326     t_event_float(1.0, 4.0);
00327     BOOST_CHECK_EQUAL( float(5.0), float_sum );
00328 
00329     float a = 10.0, b = 5.0;
00330     t_event_float(a, b);
00331     BOOST_CHECK_EQUAL( float(20.0), float_sum );
00332 
00333     h1.disconnect();
00334 }
00335 
00336 BOOST_AUTO_TEST_CASE( testSyncListener )
00337 {
00338     // No completer:
00339     reset();
00340     Handle h = t_event.connect( boost::bind(&EventTest::listener, this) );
00341     BOOST_CHECK( h.connected() );
00342     t_event();
00343     h.disconnect();
00344     BOOST_CHECK( !h.connected() );
00345 
00346     BOOST_CHECK( t_listener_value );
00347 }
00348 
00349 BOOST_AUTO_TEST_CASE( testSyncListenerString )
00350 {
00351     reset();
00352     Handle h = t_event_string.connect( boost::bind(&EventTest::listenerString,this,_1) );
00353     BOOST_CHECK( h.connected() );
00354     t_event_string( std::string("What") );
00355     h.disconnect();
00356     BOOST_CHECK( !h.connected() );
00357 
00358     BOOST_CHECK_EQUAL( t_listener_what, std::string("What") );
00359     BOOST_CHECK( !t_listener_value );
00360 }
00361 
00362 BOOST_AUTO_TEST_CASE( testRTEvent )
00363 {
00364     reset();
00365 
00366     Handle hl( t_event.setup( boost::bind(&EventTest::listener,this) ) );
00367 
00368     BOOST_CHECK( !hl.connected() );
00369 
00370     hl.connect();
00371     BOOST_CHECK( hl.connected() );
00372 
00373     t_event();
00374 
00375 
00376     hl.disconnect();
00377     BOOST_CHECK( !hl.connected() );
00378     BOOST_CHECK( t_listener_value );
00379 
00380     reset();
00381     t_event();
00382     BOOST_CHECK( t_listener_value == false );
00383 
00384     hl.connect();
00385     t_event();
00386 
00387     hl.disconnect();
00388     BOOST_CHECK( !hl.connected() );
00389     BOOST_CHECK( t_listener_value == true );
00390 }
00391 
00392 BOOST_AUTO_TEST_SUITE_END()
00393 


rtt
Author(s): RTT Developers
autogenerated on Thu Jan 2 2014 11:35:21