$search
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