00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00053
00054 h1 = e.connect( boost::bind(&Runner::handle,this, _1) );
00055 return true;
00056 }
00057 void step() {
00058 e( 123456 );
00059 }
00060
00061
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
00092
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
00106
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
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
00130 count = 0;
00131 e();
00132 h1.disconnect();
00133 }
00134
00135 void finalize() {
00136 }
00137
00138 void handle(void) {
00139 if ( count == 0 ) {
00140 h1.disconnect();
00141 }
00142 if ( count == 1 ){
00143 h1.connect();
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
00265
00266
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
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
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