$search
00001 /*************************************************************************** 00002 tag: Peter Soetens Mon Jan 10 15:59:51 CET 2005 dispatch_test.cpp 00003 00004 dispatch_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 "dispatch_test.hpp" 00022 00023 #include <iostream> 00024 #include <sstream> 00025 #include <scripting/FunctionGraph.hpp> 00026 #include <extras/SimulationThread.hpp> 00027 #include <OperationCaller.hpp> 00028 #include <OperationCaller.hpp> 00029 #include <Service.hpp> 00030 00031 using namespace std; 00032 00033 DispatchTest::DispatchTest() 00034 : gtc("root"), 00035 mtc("space"), 00036 ltc("subspace") 00037 { 00038 setUp(); 00039 } 00040 00041 00042 void 00043 DispatchTest::setUp() 00044 { 00045 ltc.clear(); 00046 mtc.clear(); 00047 gtc.clear(); 00048 // ltc has a test object 00049 ltc.addService( this->createObject("test", ltc.engine()) ); 00050 // mtc has two methods. 00051 mtc.addService( this->createObject("test", mtc.engine()) ); 00052 00053 gtc.addPeer( &mtc ); 00054 mtc.connectPeers( <c ); 00055 00056 gtc.setActivity( new SimulationActivity(0.1) ); 00057 mtc.setActivity( new SimulationActivity(0.05) ); 00058 ltc.setActivity( new SimulationActivity(0.01) ); 00059 } 00060 00061 00062 void 00063 DispatchTest::tearDown() 00064 { 00065 gtc.removePeer( "space" ); 00066 ltc.disconnectPeers( "subspace" ); 00067 } 00068 00069 00070 bool DispatchTest::assertBool( bool b) { 00071 return b; 00072 } 00073 bool DispatchTest::assertMsg( bool b, const std::string& msg) { 00074 if ( b == false ) 00075 cout << "Asserted :" << b << " with :" << msg << endl; 00076 return b; 00077 } 00078 00079 00080 Service* DispatchTest::createObject(string a, CommandProcessor* cp) 00081 { 00082 Service* dat = new Service(a); 00083 dat->addOperation("assert", &DispatchTest::assertBool, this).doc("Assert").arg("bool", ""); 00084 dat->addOperation("assertMsg", &DispatchTest::assertMsg, this).doc("Assert message").arg("bool", "").arg("text", "text"); 00085 dat->addOperation("isTrue", &DispatchTest::assertBool, this).doc("Identity function").arg("bool", ""); 00086 dat->addOperation("instantDone", &DispatchTest::true_genCom, this).doc("returns immediately"); 00087 addOperation("instantDoneDone", &DispatchTest::true_gen, this).doc("Returns true when instantDone is done."); 00088 dat->addOperation("neverDone", &DispatchTest::true_genCom, this).doc("returns never"); 00089 addOperation("neverDoneDone", &DispatchTest::false_gen, this).doc("Returns true when neverDone is done."); 00090 dat->addCommand( command( "instantNotDone", &DispatchTest::true_genCom, 00091 &DispatchTest::true_gen, this, cp, false), 00092 "returns never"); 00093 dat->addOperation("instantFail", &DispatchTest::false_genCom, this).doc("fails immediately"); 00094 addOperation("instantFailDone", &DispatchTest::true_gen, this).doc("Returns true when instantFail is done."); 00095 dat->addOperation("totalFail", &DispatchTest::false_genCom, this).doc("fails in command and condition"); 00096 addOperation("totalFailDone", &DispatchTest::false_gen, this).doc("Returns true when totalFail is done."); 00097 return dat; 00098 } 00099 00100 // Registers the fixture into the 'registry' 00101 BOOST_FIXTURE_TEST_SUITE( DispatchTestSuite, DispatchTest ) 00102 00103 BOOST_AUTO_TEST_CASE( testParseDispatch) 00104 { 00105 // this is a global program requesting a method on a local 00106 // task/processor (ie assert) and a command (instantDone) 00107 string prog = string("program x { do space.subspace.test.assertMsg(true,\"tpdtrue\") \n") 00108 + " if space.subspace.test.assert(true) then \n" 00109 + " do nothing\n" 00110 + " do space.subspace.test.instantDone() \n" 00111 // + " do space.assertMsg(true,\"tpdfail\")\n" 00112 // + " do this.space.assertMsg(true,\"donotreach\")\n" 00113 + "}"; 00114 00115 this->doDispatch( prog, >c ); 00116 00117 BOOST_CHECK( gtc.engine()->programs()->getProgramStatus("x") != ProgramInterface::Status::error ); 00118 BOOST_CHECK( gtc.engine()->programs()->getProgramStatus("x") != ProgramInterface::Status::running ); 00119 BOOST_CHECK( gtc.engine()->programs()->getProgramStatus("x") == ProgramInterface::Status::stopped ); 00120 00121 this->finishDispatch( >c, "x"); 00122 } 00123 00124 BOOST_AUTO_TEST_CASE( testDispatchFailure) 00125 { 00126 // this is a global program requesting a command on a local 00127 // task/processor (ie instantFail). 00128 string prog = string("program x { do space.subspace.test.instantFail() \n") 00129 + "}"; 00130 00131 this->doDispatch( prog, >c ); 00132 00133 BOOST_CHECK( gtc.engine()->programs()->getProgramStatus("x") == ProgramInterface::Status::error ); 00134 00135 this->finishDispatch( >c, "x"); 00136 } 00137 BOOST_AUTO_TEST_CASE( testDispatchCondition) 00138 { 00139 // see if checking a remote condition works 00140 // also tests peerparser in expressions 00141 string prog = string("program x { if ( space.subspace.test.assert(true) ) then \n") 00142 + "do space.subspace.test.instantDone() \n" 00143 + "else \n" 00144 + "do space.subspace.test.instantFail() \n" 00145 + "if ( space.subspace.test.assert(false) ) then \n" 00146 + "do space.subspace.test.instantFail() \n" 00147 + "else \n" 00148 + "do space.subspace.test.instantDone() \n" 00149 + " }"; 00150 this->doDispatch( prog, >c ); 00151 00152 stringstream msg; 00153 msg << "Status was not 'stopped', but "+gtc.engine()->programs()->getProgramStatusStr("x"); 00154 msg << " on line " << gtc.engine()->programs()->getProgram("x")->getLineNumber(); 00155 BOOST_CHECK_MESSAGE(gtc.engine()->programs()->getProgramStatus("x") == ProgramInterface::Status::stopped, 00156 msg.str()); 00157 00158 this->finishDispatch( >c, "x"); 00159 } 00160 00161 BOOST_AUTO_TEST_CASE( testDispatchAnd) 00162 { 00163 // see if checking a remote condition works 00164 string prog = string("program x { do space.subspace.test.assert(true)\n") 00165 + "and space.subspace.test.assert(true) \n" 00166 + "and space.subspace.test.assert(true) \n" 00167 + "do space.subspace.test.instantDone() \n" 00168 + "and space.subspace.test.instantDone() \n" 00169 + "and space.subspace.test.instantDone() \n" 00170 + " }"; 00171 this->doDispatch( prog, >c ); 00172 00173 stringstream msg; 00174 msg << "Status was not 'stopped', but "+gtc.engine()->programs()->getProgramStatusStr("x"); 00175 msg << " on line " << gtc.engine()->programs()->getProgram("x")->getLineNumber(); 00176 BOOST_CHECK_MESSAGE(gtc.engine()->programs()->getProgramStatus("x") == ProgramInterface::Status::stopped 00177 , msg.str()); 00178 00179 this->finishDispatch( >c, "x"); 00180 } 00181 00182 BOOST_AUTO_TEST_CASE( testDispatchTry) 00183 { 00184 // see if checking a remote condition works 00185 string prog = string("program x { try space.subspace.test.assert(false)\n") 00186 + "try space.subspace.test.assert(true) \n" 00187 + "and space.subspace.test.assert(false) \n" 00188 + "and space.subspace.test.assert(true) \n" 00189 + "try space.subspace.test.instantFail()\n" 00190 + "try space.subspace.test.instantDone() \n" 00191 + "and space.subspace.test.instantFail() \n" 00192 + "and space.subspace.test.instantDone() \n" 00193 + " }"; 00194 this->doDispatch( prog, >c ); 00195 00196 BOOST_CHECK( gtc.engine()->programs()->getProgramStatus("x") != ProgramInterface::Status::error ); 00197 stringstream msg; 00198 msg << "Status was not 'stopped', but "+gtc.engine()->programs()->getProgramStatusStr("x"); 00199 msg << " on line " << gtc.engine()->programs()->getProgram("x")->getLineNumber(); 00200 BOOST_CHECK_MESSAGE(gtc.engine()->programs()->getProgramStatus("x") == ProgramInterface::Status::stopped 00201 , msg.str()); 00202 00203 this->finishDispatch( >c, "x"); 00204 } 00205 00206 BOOST_AUTO_TEST_CASE( testDispatchUntil) 00207 { 00208 // see if checking a remote condition works 00209 string prog = string("program x { do space.subspace.test.instantDone()\n") 00210 + "until { \n" 00211 + " if time > 10 ms then continue \n" // test in simulation takes far less than 1 second 00212 + "} \n" 00213 + "do space.subspace.test.instantDone()\n" 00214 + "until { \n" 00215 + " if done then continue \n" 00216 + "} \n" 00217 + " }"; 00218 this->doDispatch( prog, >c ); 00219 00220 stringstream msg; 00221 msg << "Status was not 'stopped', but "+gtc.engine()->programs()->getProgramStatusStr("x"); 00222 msg << " on line " << gtc.engine()->programs()->getProgram("x")->getLineNumber(); 00223 BOOST_CHECK_MESSAGE(gtc.engine()->programs()->getProgramStatus("x") == ProgramInterface::Status::stopped, 00224 msg.str()); 00225 00226 this->finishDispatch( >c, "x"); 00227 } 00228 00229 BOOST_AUTO_TEST_CASE( testDispatchUntilFail) 00230 { 00231 // see if checking a remote condition works 00232 string prog = string("program x { do space.subspace.test.instantFail()\n") 00233 + "until { \n" 00234 + " if done then continue \n" // program should go into error 00235 + "} \n" 00236 + " }"; 00237 this->doDispatch( prog, >c ); 00238 00239 BOOST_CHECK( gtc.engine()->programs()->getProgramStatus("x") == ProgramInterface::Status::error ); 00240 00241 this->finishDispatch( >c, "x"); 00242 } 00243 00244 BOOST_AUTO_TEST_CASE( testDispatchMany) 00245 { 00246 // XXX not a valid test. send not present in Orocos, this looks like 'try' 00247 // a program which must not fail, even if the command failes. 00248 string prog = string("program x { ") 00249 +" do space.subspace.test.instantDone()\n" 00250 +" do space.subspace.test.instantDone()\n" 00251 +" do space.subspace.test.instantDone()\n" 00252 +" do space.subspace.test.instantDone()\n" 00253 +" }"; 00254 this->doDispatch( prog, >c ); 00255 00256 BOOST_CHECK( gtc.engine()->programs()->getProgramStatus("x") != ProgramInterface::Status::error ); 00257 BOOST_CHECK( gtc.engine()->programs()->getProgramStatus("x") == ProgramInterface::Status::stopped ); 00258 00259 this->finishDispatch( >c, "x" ); 00260 } 00261 00262 BOOST_AUTO_TEST_SUITE_END() 00263 00264 void DispatchTest::doDispatch( const std::string& prog, TaskContext* tc ) 00265 { 00266 Parser::ParsedPrograms pg_list; 00267 try { 00268 pg_list = parser.parseProgram( prog, tc ); 00269 } 00270 catch( const file_parse_exception& exc ) 00271 { 00272 BOOST_REQUIRE_MESSAGE( false , exc.what()); 00273 } 00274 if ( pg_list.empty() ) 00275 { 00276 BOOST_REQUIRE( false ); 00277 } 00278 BOOST_REQUIRE( tc->engine()->programs()->loadProgram( *pg_list.begin() ) ); 00279 BOOST_CHECK(ltc.start()); 00280 BOOST_CHECK(mtc.start()); 00281 BOOST_CHECK(gtc.start()); 00282 BOOST_REQUIRE( tc->engine()->programs()->getProgram( (*pg_list.begin())->getName() )->start() ); 00283 00284 SimulationThread::Instance()->stop(); 00285 SimulationThread::Instance()->run(1000); 00286 } 00287 00288 void DispatchTest::finishDispatch(TaskContext* tc, std::string prog_name) 00289 { 00290 BOOST_CHECK(gtc.stop()); 00291 BOOST_CHECK(mtc.stop()); 00292 BOOST_CHECK(ltc.stop()); 00293 tc->engine()->programs()->getProgram( prog_name )->stop(); 00294 BOOST_CHECK( tc->engine()->programs()->unloadProgram( prog_name ) ); 00295 00296 } 00297