00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "unit.hpp"
00021
00022 #include "tasks_test.hpp"
00023
00024 #include <iostream>
00025
00026 #include <extras/PeriodicActivity.hpp>
00027 #include <os/TimeService.hpp>
00028 #include <Logger.hpp>
00029
00030 #include <boost/scoped_ptr.hpp>
00031
00032 using namespace std;
00033 using namespace boost;
00034 using namespace RTT;
00035 using namespace RTT::detail;
00036
00037 #define BOOST_CHECK_EQUAL_MESSAGE(M, v1, v2) BOOST_CHECK_MESSAGE( v1==v2, M)
00038
00039 struct TestOverrun
00040 : public RunnableInterface
00041 {
00042 bool fini;
00043 bool initialize() { fini = false; return true; }
00044
00045 void step() {
00046
00047 usleep(200*1000);
00048
00049
00050
00051 #if 0
00052 TIME_SPEC timevl;
00053 timevl = ticks2timespec( nano2ticks(200*1000*1000) );
00054 rtos_nanosleep( &timevl, 0);
00055 #endif
00056 }
00057
00058 void finalize() {
00059 fini = true;
00060 }
00061 };
00062
00063 struct TestPeriodic
00064 : public RunnableInterface
00065 {
00066 int overfail, underfail, succ;
00067 bool stepped;
00068
00069 TimeService::ticks ts;
00070
00071
00072 int cpu;
00073
00074 TestPeriodic()
00075 : overfail(0), underfail(0), succ(0), stepped(false), cpu(0)
00076 {
00077 }
00078
00079 bool initialize() {
00080 this->reset();
00081 return true;
00082 }
00083 void step() {
00084 if (stepped == false ) {
00085 ts = TimeService::Instance()->getTicks();
00086 stepped = true;
00087 } else {
00088 TimeService::Seconds s = TimeService::Instance()->secondsSince( ts );
00089 if ( s < this->getThread()->getPeriod() *0.9 ) {
00090 ++underfail;
00091
00092 }
00093 else if ( s > this->getThread()->getPeriod() *1.1 ) {
00094 ++overfail;
00095
00096 }
00097 else {
00098 ++succ;
00099
00100 }
00101 ts = TimeService::Instance()->getTicks();
00102 }
00103 #if defined( OROCOS_TARGET_GNULINUX )
00104 cpu = sched_getcpu();
00105 BOOST_REQUIRE_NE(ENOSYS, cpu);
00106 #endif
00107 }
00108 void finalize() {
00109 if (overfail || underfail)
00110 cerr <<"overfail is:"<<overfail<<", underfail is:"<<underfail<< " success is: "<<succ<<endl;
00111 }
00112
00113 void reset() {
00114 overfail = 0;
00115 underfail = 0;
00116 succ = 0;
00117 cpu = 0;
00118 stepped = false;
00119 }
00120 };
00121
00122 struct TestRunnableInterface
00123 : public RunnableInterface
00124 {
00125 bool result, breakl;
00126 bool init, stepped, looped, fini;
00127
00128 TestRunnableInterface(bool res)
00129 {
00130 this->reset(res);
00131 }
00132
00133 bool initialize() {
00134 init = true;
00135 return result;
00136 }
00137 void step() {
00138 stepped = true;
00139 }
00140 void finalize() {
00141 fini = true;
00142 }
00143
00144 void loop() {
00145 looped = true;
00146 while (breakl == false) {
00147 usleep(500*1000);
00148 }
00149 }
00150
00151 bool breakLoop() {
00152 return breakl;
00153 }
00154
00155 void reset(bool res) {
00156 result = res;
00157 init = false;
00158 stepped = false;
00159 fini = false;
00160 looped = false;
00161 breakl = true;
00162 }
00163 };
00164
00165 struct TestAllocate
00166 : public RunnableInterface
00167 {
00168 std::vector<std::string> v;
00169 char* c;
00170 std::string s;
00171
00172 bool initialize() {
00173 c = 0;
00174 return true;
00175 }
00176 void step() {
00177 v.resize( 0 );
00178 v.resize( 1025, std::string("Goodbye Memory") );
00179 delete[] c;
00180 c = new char[1025];
00181 s = "Hello World ";
00182 s += s;
00183 s += s;
00184 }
00185 void finalize() {
00186 delete[] c;
00187 v.resize(0);
00188 }
00189 };
00190
00194 struct TestSelfRemove
00195 : public RunnableInterface
00196 {
00197 int c;
00198 bool fini;
00199 bool breakl;
00200 bool initialize() {
00201 c = 0;
00202 fini = false;
00203 breakl = true;
00204 return true;
00205 }
00206 bool breakLoop() {
00207 return breakl;
00208 }
00209 void loop() {
00210 this->getActivity()->stop();
00211 }
00212 void step() {
00213 ++c;
00214 if (c == 5)
00215 this->getActivity()->stop();
00216 }
00217 void finalize() {
00218 fini = true;
00219 }
00220 };
00221
00222 void
00223 ActivitiesTest::setUp()
00224 {
00225 periodic_act = new PeriodicActivity( 15, 0.01 );
00226 t_act = new Activity(15, 0.01);
00227
00228 t_run_int_prio = new TestRunnableInterface(true);
00229 t_run_int_act = new TestRunnableInterface(true);
00230 t_run_int_fail = new TestRunnableInterface(false);
00231
00232 t_run_allocate = new TestAllocate();
00233 t_self_remove = new TestSelfRemove();
00234
00235 t_run_allocate_act = new TestAllocate();
00236 }
00237
00238
00239 void
00240 ActivitiesTest::tearDown()
00241 {
00242 delete periodic_act;
00243 delete t_act;
00244
00245 delete t_run_int_prio;
00246 delete t_run_int_act;
00247 delete t_run_int_fail;
00248
00249 delete t_run_allocate;
00250 delete t_run_allocate_act;
00251
00252 delete t_self_remove;
00253 }
00254
00255 BOOST_FIXTURE_TEST_SUITE( ActivitiesTestSuite, ActivitiesTest )
00256
00257 BOOST_AUTO_TEST_CASE( testFailInit )
00258 {
00259 periodic_act->run( t_run_int_fail );
00260
00261 BOOST_CHECK( !periodic_act->start() );
00262 BOOST_CHECK( !periodic_act->stop() );
00263
00264 BOOST_CHECK( t_act->run( t_run_int_fail ) );
00265 t_run_int_fail->reset(false);
00266
00267 BOOST_CHECK( !t_act->start() );
00268 BOOST_CHECK( !t_act->stop() );
00269
00270 }
00271
00272 #if !defined( OROCOS_TARGET_WIN32 ) && !defined(OROCOS_TARGET_LXRT)
00273 BOOST_AUTO_TEST_CASE( testOverrun )
00274 {
00275 bool r = false;
00276
00277 boost::scoped_ptr<TestOverrun> run( new TestOverrun() );
00278 boost::scoped_ptr<Activity> t( new Activity(25, 0.1, 0,"ORThread") );
00279
00280 BOOST_CHECK_EQUAL(0.1,t->getPeriod() );
00281 t->thread()->setMaxOverrun(1);
00282
00283 t->run( run.get() );
00284
00285
00286 Logger::LogLevel ll = Logger::log().getLogLevel();
00287 Logger::log().setLogLevel(Logger::Never);
00288
00289 t->start();
00290
00291
00292 usleep(100*1000);
00293 usleep(400*1000);
00294 Logger::log().setLogLevel(ll);
00295
00296 r = !t->isRunning();
00297
00298 t->run(0);
00299
00300 BOOST_REQUIRE_MESSAGE( r, "Failed to detect step overrun in Thread");
00301
00302 BOOST_CHECK_MESSAGE( run->fini, "Failed to execute finalize in emergencyStop" );
00303
00304 }
00305 #endif
00306
00307 BOOST_AUTO_TEST_CASE( testThread )
00308 {
00309 bool r = false;
00310
00311 boost::scoped_ptr<TestPeriodic> run( new TestPeriodic() );
00312
00313 boost::scoped_ptr<ActivityInterface> t( new Activity(ORO_SCHED_RT, os::HighestPriority, 0.1, 0, "PThread") );
00314 t->run( run.get() );
00315
00316 r = t->start();
00317 BOOST_CHECK_MESSAGE( r, "Failed to start Thread");
00318 usleep(1000*100);
00319 r = t->stop();
00320 BOOST_CHECK_MESSAGE( r, "Failed to stop Thread" );
00321 BOOST_CHECK_MESSAGE( run->stepped == true, "Step not executed" );
00322 BOOST_CHECK_EQUAL_MESSAGE("Periodic Failure: period of step() too long !", run->overfail, 0);
00323 BOOST_CHECK_EQUAL_MESSAGE("Periodic Failure: period of step() too short!", run->underfail, 0);
00324 t->run(0);
00325 }
00326
00327 #if defined( OROCOS_TARGET_GNULINUX )
00328
00329 void testAffinity2(boost::scoped_ptr<TestPeriodic>& run,
00330 boost::scoped_ptr<Activity>& t,
00331 int targetCPU)
00332 {
00333 bool r = false;
00334
00335 t->run( run.get() );
00336
00337 BOOST_CHECK(t->setCpuAffinity(1 << targetCPU));
00338 BOOST_CHECK_EQUAL((1 << targetCPU), t->getCpuAffinity());
00339
00340 if ( t->getScheduler() == os::HighestPriority) {
00341 r = t->start();
00342 BOOST_CHECK_MESSAGE( r, "Failed to start Thread");
00343 r = t->stop();
00344 BOOST_CHECK_MESSAGE( r, "Failed to stop Thread");
00345 BOOST_CHECK_MESSAGE( run->stepped == true, "Step not executed" );
00346 BOOST_CHECK_EQUAL(targetCPU, run->cpu);
00347 BOOST_CHECK_LT(0, run->succ);
00348 run->reset();
00349 }
00350 BOOST_CHECK_EQUAL(0, run->cpu);
00351 r = t->start();
00352 BOOST_CHECK_MESSAGE( r, "Failed to start Thread");
00353 sleep(1);
00354 r = t->stop();
00355 BOOST_CHECK_MESSAGE( r, "Failed to stop Thread" );
00356 BOOST_CHECK_MESSAGE( run->stepped == true, "Step not executed" );
00357 BOOST_CHECK_EQUAL(targetCPU, run->cpu);
00358 BOOST_CHECK_LT(0, run->succ);
00359
00360 t->run(0);
00361 }
00362
00363 BOOST_AUTO_TEST_CASE( testAffinity )
00364 {
00365
00366 int numCPU = sysconf( _SC_NPROCESSORS_ONLN );
00367 if (1 < numCPU)
00368 {
00369 boost::scoped_ptr<TestPeriodic> run( new TestPeriodic() );
00370 boost::scoped_ptr<Activity> t( new Activity(ORO_SCHED_RT, os::HighestPriority, 0.1, ~0, 0, "PThread") );
00371
00372 unsigned mask=0;
00373 for (int i=0; i<numCPU; ++i)
00374 {
00375 mask |= (1 << i);
00376 }
00377 BOOST_CHECK_EQUAL(mask, t->getCpuAffinity());
00378
00379
00380 testAffinity2(run, t, 0);
00381 testAffinity2(run, t, numCPU-1);
00382 }
00383
00384 }
00385
00386 #endif
00387
00388 BOOST_AUTO_TEST_CASE( testNonPeriodic )
00389 {
00390 scoped_ptr<TestRunnableInterface> t_run_int_nonper
00391 ( new TestRunnableInterface(true) );
00392
00393 {
00394 scoped_ptr<Activity> t_task_nonper
00395 ( new Activity( 14 ) );
00396
00397 BOOST_CHECK( t_task_nonper->run( t_run_int_nonper.get() ) );
00398 BOOST_CHECK( t_task_nonper->start() );
00399 testPause();
00400 BOOST_CHECK( t_run_int_nonper->looped );
00401 BOOST_CHECK( !t_run_int_nonper->stepped );
00402 BOOST_CHECK( t_run_int_nonper->init );
00403 BOOST_CHECK( t_task_nonper->stop() );
00404 BOOST_CHECK( t_run_int_nonper->fini );
00405 BOOST_CHECK( !t_task_nonper->isRunning() );
00406 BOOST_CHECK( t_task_nonper->run( 0 ) );
00407 BOOST_CHECK( t_task_nonper->start() );
00408 BOOST_CHECK( t_task_nonper->stop() );
00409
00410 BOOST_CHECK( !t_task_nonper->isRunning() );
00411 }
00412 }
00413
00414 BOOST_AUTO_TEST_CASE( testActivityNP )
00415 {
00416 scoped_ptr<TestRunnableInterface> t_run_int_nonper
00417 ( new TestRunnableInterface(true) );
00418
00419 {
00420 scoped_ptr<Activity> t_task_nonper
00421 ( new Activity(15) );
00422
00423 BOOST_CHECK( t_task_nonper->run( t_run_int_nonper.get() ) );
00424 BOOST_CHECK( t_task_nonper->start() );
00425 testPause();
00426 sleep(1);
00427 BOOST_CHECK( t_run_int_nonper->looped );
00428 BOOST_CHECK( t_run_int_nonper->init );
00429 BOOST_CHECK( t_task_nonper->stop() );
00430 BOOST_CHECK( t_run_int_nonper->fini );
00431 BOOST_CHECK( !t_task_nonper->isRunning() );
00432 BOOST_CHECK( t_task_nonper->run( 0 ) );
00433 BOOST_CHECK( t_task_nonper->start() );
00434 BOOST_CHECK( t_task_nonper->stop() );
00435
00436 BOOST_CHECK( !t_task_nonper->isRunning() );
00437 }
00438 }
00439
00440 BOOST_AUTO_TEST_CASE( testActivityBreakLoop )
00441 {
00442 scoped_ptr<TestRunnableInterface> t_run_int_nonper
00443 ( new TestRunnableInterface(true) );
00444
00445 {
00446 scoped_ptr<Activity> t_task_nonper
00447 ( new Activity(15) );
00448
00449 BOOST_CHECK( t_task_nonper->run( t_run_int_nonper.get() ) );
00450 BOOST_CHECK( t_task_nonper->start() );
00451 testPause();
00452
00453 t_run_int_nonper->breakl = false;
00454 BOOST_CHECK( t_task_nonper->start() );
00455 testPause();
00456 BOOST_CHECK( t_task_nonper->stop() == false );
00457
00458 t_run_int_nonper->breakl = true;
00459 BOOST_CHECK( t_task_nonper->stop() );
00460 BOOST_CHECK( t_run_int_nonper->fini );
00461 BOOST_CHECK( !t_task_nonper->isRunning() );
00462 }
00463 }
00464
00465 BOOST_AUTO_TEST_CASE( testSelfRemove )
00466 {
00467 scoped_ptr<TestSelfRemove> t_run_int_nonper
00468 ( new TestSelfRemove() );
00469 scoped_ptr<Activity> t_task_nonper
00470 ( new Activity( 14 ) );
00471 BOOST_CHECK( t_task_nonper->run( t_run_int_nonper.get() ) );
00472 BOOST_CHECK( t_task_nonper->start() );
00473 BOOST_CHECK( periodic_act->run(t_self_remove) );
00474 BOOST_CHECK( periodic_act->start() );
00475 testPause();
00476 BOOST_CHECK( !periodic_act->isRunning() );
00477 BOOST_CHECK( t_self_remove->fini );
00478 BOOST_CHECK( !t_task_nonper->isRunning() );
00479 BOOST_CHECK( t_run_int_nonper->fini );
00480 }
00481
00482 BOOST_AUTO_TEST_CASE( testActivityNPSelfRemove )
00483 {
00484 scoped_ptr<TestSelfRemove> t_run_int_nonper
00485 ( new TestSelfRemove() );
00486 scoped_ptr<Activity> t_task_nonper
00487 ( new Activity( 14 ) );
00488 BOOST_CHECK( t_task_nonper->run( t_run_int_nonper.get() ) );
00489 BOOST_CHECK( t_task_nonper->start() );
00490 testPause();
00491 BOOST_CHECK( !t_task_nonper->isRunning() );
00492 BOOST_CHECK( t_run_int_nonper->fini );
00493 }
00494
00495 BOOST_AUTO_TEST_CASE( testActivityPSelfRemove )
00496 {
00497 scoped_ptr<TestSelfRemove> t_run_int_per
00498 ( new TestSelfRemove() );
00499 scoped_ptr<Activity> t_task_per
00500 ( new Activity( 14, 0.01 ) );
00501 BOOST_CHECK( t_task_per->run( t_run_int_per.get() ) );
00502 BOOST_CHECK( t_task_per->start() );
00503 testPause();
00504 BOOST_CHECK( !t_task_per->isRunning() );
00505 BOOST_CHECK( t_run_int_per->fini );
00506 }
00507
00508
00509 BOOST_AUTO_TEST_CASE( testStartStop )
00510 {
00511 testStart();
00512 testPause();
00513 testStop();
00514 }
00515
00516 BOOST_AUTO_TEST_CASE( testRunnableInterface )
00517 {
00518 testAddRunnableInterface();
00519 testStart();
00520 testRunnableInterfaceInit();
00521 testPause();
00522 testRunnableInterfaceExecution();
00523 testStop();
00524 testRemoveRunnableInterface();
00525 }
00526
00527 BOOST_AUTO_TEST_CASE( testAllocation )
00528 {
00529 testAddAllocate();
00530 testStart();
00531 testPause();
00532 testStop();
00533 testRemoveAllocate();
00534 }
00535
00536 BOOST_AUTO_TEST_SUITE_END()
00537
00538 void ActivitiesTest::testAddRunnableInterface()
00539 {
00540 bool adding_prio = periodic_act->run( t_run_int_prio );
00541 BOOST_CHECK( adding_prio );
00542
00543 bool adding_act = t_act->run( t_run_int_act );
00544 BOOST_CHECK( adding_act );
00545 }
00546
00547 void ActivitiesTest::testRemoveRunnableInterface()
00548 {
00549 BOOST_CHECK( t_run_int_prio->fini );
00550 BOOST_CHECK( periodic_act->run( 0 ) );
00551
00552 BOOST_CHECK( t_run_int_act->fini );
00553 BOOST_CHECK( t_act->run( 0 ) );
00554 }
00555
00556 void ActivitiesTest::testStart()
00557 {
00558 BOOST_CHECK( periodic_act->start());
00559 BOOST_CHECK( periodic_act->isRunning() );
00560
00561 BOOST_CHECK( t_act->start());
00562 BOOST_CHECK( t_act->isRunning() );
00563 }
00564
00565 void ActivitiesTest::testPause()
00566 {
00567 #if 0
00568
00569 int rv = 0;
00570 BOOST_CHECK( (rv = usleep(100000)) == 0);
00571 if ( rv != 0)
00572 BOOST_CHECK_EQUAL_MESSAGE(errno, 0, "Sleep failed. Errno is not zero.");
00573 #else
00574 TIME_SPEC t;
00575 t.tv_sec = 1;
00576 t.tv_nsec = 0;
00577 BOOST_CHECK( rtos_nanosleep(&t,0) == 0);
00578 #endif
00579 }
00580
00581 void ActivitiesTest::testRunnableInterfaceInit() {
00582 BOOST_CHECK( t_run_int_prio->init );
00583 BOOST_CHECK( t_run_int_act->init );
00584 }
00585
00586 void ActivitiesTest::testRunnableInterfaceExecution() {
00587
00588 BOOST_CHECK( t_run_int_prio->stepped );
00589 BOOST_CHECK( t_run_int_act->stepped );
00590 }
00591
00592 void ActivitiesTest::testStop()
00593 {
00594 BOOST_CHECK( periodic_act->stop());
00595 BOOST_CHECK( !periodic_act->isRunning() );
00596
00597 BOOST_CHECK( t_act->stop());
00598 BOOST_CHECK( !t_act->isRunning() );
00599 }
00600
00601 void ActivitiesTest::testAddAllocate()
00602 {
00603 BOOST_CHECK( periodic_act->run( t_run_allocate ) );
00604
00605 BOOST_CHECK( t_act->run( t_run_allocate_act ) );
00606 }
00607
00608 void ActivitiesTest::testRemoveAllocate()
00609 {
00610 BOOST_CHECK( periodic_act->run( 0 ) );
00611
00612 BOOST_CHECK( t_act->run( 0 ) );
00613 }
00614