00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "unit.hpp"
00011
00012 #include <rtt-config.h>
00013 #include <extras/SimulationThread.hpp>
00014 #include <extras/SimulationActivity.hpp>
00015 #include <scripting/StateMachine.hpp>
00016 #include <scripting/ParsedStateMachine.hpp>
00017 #include <scripting/DumpObject.hpp>
00018 #include <scripting/Parser.hpp>
00019
00020 #include <Service.hpp>
00021 #include <TaskContext.hpp>
00022 #include <OperationCaller.hpp>
00023 #include <Port.hpp>
00024 #include <scripting/ScriptingService.hpp>
00025 #include "operations_fixture.hpp"
00026
00027 #include <string>
00028 #include <iostream>
00029 #include <sstream>
00030
00031 using namespace RTT;
00032 using namespace RTT::detail;
00033 using namespace std;
00034
00035 class RtStringStateTest
00036 : public OperationsFixture
00037 {
00038 public:
00039 Parser parser;
00040 ScriptingService::shared_ptr sa;
00041
00042 void doState(const std::string& name, const std::string& prog, TaskContext*, bool test=true );
00043 void parseState( const std::string& prog, TaskContext*, bool test=true );
00044 void runState(const std::string& name, TaskContext*, bool test=true );
00045 void checkState( const std::string& name, TaskContext*, bool test=true );
00046 void finishState( std::string const& name, TaskContext*, bool test=true );
00047
00048 std::string sline;
00049 public:
00050 RtStringStateTest()
00051 :
00052 sa( ScriptingService::Create(tc) )
00053 {
00054 tc->stop();
00055 tc->setActivity( new SimulationActivity(0.001) );
00056
00057 tc->start();
00058 i = 0;
00059 SimulationThread::Instance()->stop();
00060 }
00061 ~RtStringStateTest(){
00062 }
00063 };
00064
00065 BOOST_FIXTURE_TEST_SUITE( RtStringTestSuite, RtStringStateTest )
00066
00067 BOOST_AUTO_TEST_CASE( testCreateRtString )
00068 {
00069 string prog = string("StateMachine X {\n")
00070 + " initial state INIT {\n"
00071 + " var rt_string s1\n"
00072 + " transitions { select FINI }\n"
00073 + " }\n"
00074 + " final state FINI {\n"
00075 + " }\n"
00076 + " }\n"
00077 + " RootMachine X x\n"
00078 ;
00079
00080 this->doState("x", prog, tc );
00081 this->finishState( "x", tc );
00082 }
00083
00084 BOOST_AUTO_TEST_CASE( testCreateRtstringOfFixedSize )
00085 {
00086 string prog = string("StateMachine X {\n")
00087 + " initial state INIT {\n"
00088 + " var rt_string s1(22)\n"
00089 + " transitions { select FINI }\n"
00090 + " }\n"
00091 + " final state FINI {\n"
00092 + " }\n"
00093 + " }\n"
00094 + " RootMachine X x\n"
00095 ;
00096
00097 this->doState("x", prog, tc );
00098 this->finishState( "x", tc );
00099 }
00100
00101 #if 0
00102
00103 BOOST_AUTO_TEST_CASE( testCreateRtstringFromCharPtr )
00104 {
00105 string prog = string("StateMachine X {\n")
00106 + " initial state INIT {\n"
00107 + " var rt_string s1(\"hello world\")\n"
00108 + " transitions { select FINI }\n"
00109 + " }\n"
00110 + " final state FINI {\n"
00111 + " }\n"
00112 + " }\n"
00113 + " RootMachine X x\n"
00114 ;
00115 this->doState("x", prog, tc );
00116 this->finishState( "x", tc );
00117 }
00118 #endif
00119
00120 BOOST_AUTO_TEST_CASE( testCreateRtstringFromRtString )
00121 {
00122 string prog = string("StateMachine X {\n")
00123 + " initial state INIT {\n"
00124 + " var rt_string s1 = rt_string(\"hello world\")\n"
00125 + " transitions { select FINI }\n"
00126 + " }\n"
00127 + " final state FINI {\n"
00128 + " }\n"
00129 + " }\n"
00130 + " RootMachine X x\n"
00131 ;
00132
00133 this->doState("x", prog, tc );
00134 this->finishState( "x", tc );
00135 }
00136
00137 BOOST_AUTO_TEST_CASE( testConcatRtstring )
00138 {
00139 string prog = string("StateMachine X {\n")
00140 + " initial state INIT {\n"
00141 + " var rt_string s1\n"
00142 + " entry {\n"
00143 + " s1 = rt_string(\"Multiply \")\n"
00144 + " s1 = s1 + 10\n"
00145 + " s1 = s1 + rt_string(\" times \")\n"
00146 + " s1 = s1 + 33.3\n"
00147 + " s1 = rt_string(\"Now: \") + 1 + rt_string(\"st \") + s1 + '!'\n"
00148 + " }\n"
00149 + " transitions { select FINI }\n"
00150 + " }\n"
00151 + " final state FINI {\n"
00152 + " }\n"
00153 + " }\n"
00154 + " RootMachine X x\n"
00155 ;
00156
00157 this->doState("x", prog, tc );
00158 this->finishState( "x", tc );
00159 }
00160
00161 BOOST_AUTO_TEST_CASE( testRtstringConversion )
00162 {
00163 string prog = string("StateMachine X {\n")
00164 + " initial state INIT {\n"
00165 + " var rt_string rts1\n"
00166 + " var string s1\n"
00167 + " entry {\n"
00168 + " s1 = \"s1\"\n"
00169 + " rts1 = rt_string(\"rts1\")\n"
00170 + " test.assert(s1 == \"s1\")\n"
00171 + " test.assert(rts1 == rt_string(\"rts1\"))\n"
00172 + " s1 = string(rts1)\n"
00173 + " test.assert(s1 == string(rts1))\n"
00174 + " test.assert(s1 == \"rts1\")\n"
00175 + " s1 = \"s1\"\n"
00176 + " rts1 = rt_string(s1)\n"
00177 + " test.assert(rts1 == rt_string(\"s1\"))\n"
00178 + " s1 = string( rt_string(\" s1 \") )\n"
00179 + " rts1 = rt_string( string(\" rts1 \") )\n"
00180 + " test.assert(s1 == \" s1 \")\n"
00181 + " test.assert(rts1 == rt_string(\" rts1 \"))\n"
00182 + " }\n"
00183 + " transitions { select FINI }\n"
00184 + " }\n"
00185 + " final state FINI {\n"
00186 + " }\n"
00187 + " }\n"
00188 + " RootMachine X x\n"
00189 ;
00190
00191 this->doState("x", prog, tc );
00192 this->finishState( "x", tc );
00193 }
00194
00195
00196 BOOST_AUTO_TEST_SUITE_END()
00197
00198 void RtStringStateTest::doState( const std::string& name, const std::string& prog, TaskContext* tc, bool test )
00199 {
00200 BOOST_CHECK( tc->engine() );
00201
00202 parseState( prog, tc, test);
00203 runState(name, tc, test);
00204 checkState(name, tc, test);
00205 }
00206
00207 void RtStringStateTest::parseState(const std::string& prog, TaskContext* tc, bool test )
00208 {
00209
00210 try {
00211 sa->loadStateMachines( prog, std::string("state_test.cpp"), true );
00212 }
00213 catch( const file_parse_exception& exc )
00214 {
00215 BOOST_REQUIRE_MESSAGE( !test, exc.what() );
00216 }
00217 catch( const parse_exception& exc )
00218 {
00219 BOOST_REQUIRE_MESSAGE( !test, exc.what() );
00220 }
00221 catch( const program_load_exception& e)
00222 {
00223 BOOST_REQUIRE_MESSAGE( !test, e.what() );
00224 }
00225 catch( const std::exception& e ) {
00226 BOOST_CHECK_MESSAGE( !test , e.what());
00227 BOOST_REQUIRE_MESSAGE( !test, "Uncaught Processor load exception" );
00228 }
00229 }
00230
00231 void RtStringStateTest::runState(const std::string& name, TaskContext* tc, bool test )
00232 {
00233 StateMachinePtr sm = sa->getStateMachine(name);
00234 BOOST_REQUIRE( sm );
00235 sm->trace(true);
00236 OperationCaller<bool(StateMachine*)> act = tc->provides(name)->getOperation("activate");
00237 OperationCaller<bool(StateMachine*)> autom = tc->provides(name)->getOperation("automatic");
00238 BOOST_CHECK( act(sm.get()) );
00239 BOOST_CHECK( SimulationThread::Instance()->run(1) );
00240 BOOST_CHECK_MESSAGE( sm->isActive(), "Error : Activate Command for '"+sm->getName()+"' did not have effect." );
00241 BOOST_CHECK( autom(sm.get()) || !test );
00242
00243 BOOST_CHECK( SimulationThread::Instance()->run(1000) );
00244 }
00245
00246 void RtStringStateTest::checkState(const std::string& name, TaskContext* tc, bool test )
00247 {
00248 StateMachinePtr sm = sa->getStateMachine(name);
00249 BOOST_REQUIRE( sm );
00250 if ( test ) {
00251
00252 BOOST_CHECK_MESSAGE( sm->isActive(), "Error : State Context '"+sm->getName()+"' did not get activated." );
00253 stringstream errormsg;
00254 int line = sm->getLineNumber();
00255 errormsg <<" in StateMachine "+sm->getName()
00256 <<" in state "<< (sm->currentState() ? sm->currentState()->getName() : "(null)")
00257 <<" on line " << line <<" of that StateMachine:"<<endl;
00258 {
00259 stringstream sctext( sm->getText() );
00260 int cnt = 1;
00261 while ( cnt++ <line && sctext ) {
00262 string garbage;
00263 getline( sctext, garbage, '\n' );
00264 }
00265 getline( sctext, sline, '\n' );
00266 }
00267 errormsg <<"here > " << sline << endl;
00268 if ( sm->inError() ) {
00269 RTT::scripting::DumpObject( tc->provides() );
00270 RTT::scripting::DumpObject( tc->provides(name) );
00271 }
00272 BOOST_CHECK_MESSAGE( sm->inError() == false, "Runtime error (inError() == true) encountered" + errormsg.str() );
00273
00274 StateMachine::ChildList cl = sm->getChildren();
00275 StateMachine::ChildList::iterator clit = cl.begin();
00276 while( clit != cl.end() ) {
00277 line = (*clit)->getLineNumber();
00278 {
00279 stringstream sctext( (*clit)->getText() );
00280 int cnt = 1;
00281 while ( cnt++ <line && sctext ) {
00282 string garbage;
00283 getline( sctext, garbage, '\n' );
00284 }
00285 getline( sctext, sline, '\n' );
00286 }
00287 stringstream cerrormsg;
00288 if ( (*clit)->currentState() )
00289 cerrormsg <<" in child "<< (*clit)->getName() <<" in state "<<(*clit)->currentState()->getName()<< " on line " << (*clit)->getLineNumber() <<" of that StateMachine."<<endl <<"here > " << sline << endl;
00290 else
00291 cerrormsg <<" child "<< (*clit)->getName() << " (deactivated) on line " << (*clit)->getLineNumber() <<" of that StateMachine."<<endl<<"here > " << sline << endl;
00292
00293 BOOST_CHECK_MESSAGE( (*clit)->inError() == false, "Runtime error (inError() == true) encountered" + cerrormsg.str() );
00294 if ( (*clit)->inError() == false && sm->inError() == true) {
00295 cout << "Child Status:" << cerrormsg.str() << endl;
00296 }
00297 ++clit;
00298 }
00299 }
00300 }
00301
00302 void RtStringStateTest::finishState(std::string const& name, TaskContext* tc, bool test)
00303 {
00304 StateMachinePtr sm = sa->getStateMachine(name);
00305 BOOST_REQUIRE( sm );
00306 BOOST_CHECK( sa->getStateMachine( name )->stop() );
00307 BOOST_CHECK( SimulationThread::Instance()->run(500) );
00308 if (test) {
00309 stringstream errormsg;
00310 errormsg << " on line " << sm->getLineNumber() <<", status is "<< sa->getStateMachineStatusStr(name) <<endl <<"here > " << sline << endl;;
00311 BOOST_CHECK_MESSAGE( sm->isStopped(), "StateMachine stalled " + errormsg.str() );
00312 }
00313
00314
00315 BOOST_CHECK( sa->getStateMachine( name )->deactivate() );
00316 BOOST_CHECK( SimulationThread::Instance()->run(200) );
00317 if ( sm->isActive() )
00318 BOOST_CHECK( sa->getStateMachine( name )->deactivate() );
00319 BOOST_CHECK( SimulationThread::Instance()->run(200) );
00320 BOOST_CHECK( sa->getStateMachine( name )->isActive() == false );
00321
00322
00323 tc->stop();
00324
00325 try {
00326 BOOST_CHECK( sa->unloadStateMachine( name ) );
00327 }
00328 catch( const program_unload_exception& e)
00329 {
00330 BOOST_REQUIRE_MESSAGE( false, e.what() );
00331 }
00332 catch( ... ) {
00333 BOOST_REQUIRE_MESSAGE( false, "Uncaught Processor unload exception" );
00334 }
00335
00336 }