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