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 <rtt-config.h>
00022 #include <extras/SimulationThread.hpp>
00023 #include <extras/SimulationActivity.hpp>
00024 #include <scripting/StateMachine.hpp>
00025 #include <scripting/ParsedStateMachine.hpp>
00026 #include <scripting/DumpObject.hpp>
00027 #include <scripting/parse_exception.hpp>
00028 #include <rtt/internal/GlobalEngine.hpp>
00029
00030 #include <Service.hpp>
00031 #include <TaskContext.hpp>
00032 #include <OperationCaller.hpp>
00033 #include <Port.hpp>
00034 #include <scripting/ScriptingService.hpp>
00035 #include <rt_string.hpp>
00036 #include "operations_fixture.hpp"
00037
00038 #include <string>
00039 #include <iostream>
00040 #include <sstream>
00041
00042 using namespace RTT;
00043 using namespace RTT::detail;
00044 using namespace RTT::internal;
00045 using namespace std;
00046
00047 class StateTest
00048 : public OperationsFixture
00049 {
00050 public:
00051 InputPort<double> d_event;
00052 InputPort<bool> b_event;
00053 InputPort<int> t_event;
00054 Operation<void(void)> v_event;
00055 Operation<void(double)> o_event;
00056 Operation<void(void)> v1_event;
00057 Operation<void(void)> v2_event;
00058 Operation<void(void)> v3_event;
00059 Operation<void(double)> c_event;
00060 OutputPort<double> d_event_source;
00061 OutputPort<bool> b_event_source;
00062 OutputPort<int> t_event_source;
00063 ScriptingService::shared_ptr sa;
00064
00065 RTT::Operation<void(RTT::rt_string)> setState_op;
00066 void setState(RTT::rt_string state) {
00067 mrt_state = state;
00068
00069 }
00070
00071 RTT::rt_string mrt_state;
00072
00073 void log(const std::string& msg) {
00074 Logger::log(Logger::Info) << msg << endlog();
00075 }
00076 void doState(const std::string& name, const std::string& prog, TaskContext*, bool test=true, int runs = 1000 );
00077 void parseState( const std::string& prog, TaskContext*, bool test=true );
00078 void runState(const std::string& name, TaskContext*, bool trace=true, bool test=true, int runs = 1000 );
00079 void checkState( const std::string& name, TaskContext*, bool test=true );
00080 void finishState( std::string const& name, TaskContext*, bool test=true );
00081
00082 std::string sline;
00083 public:
00084 StateTest()
00085 :
00086 d_event("d_event"), b_event("b_event"), t_event("t_event"), v_event("v_event"),o_event("o_event"),
00087 v1_event("v1_event"),v2_event("v2_event"),v3_event("v3_event"),c_event("c_event"),
00088 d_event_source("d_event_source"), b_event_source("b_event_source"), t_event_source("t_event_source")
00089 ,sa( ScriptingService::Create(tc) ),
00090 setState_op("setState", &StateTest::setState, this, RTT::OwnThread)
00091 {
00092 tc->stop();
00093 tc->setActivity( new SimulationActivity(0.001) );
00094
00095 tc->addPeer(caller);
00096
00097 tc->ports()->addPort( d_event );
00098 tc->ports()->addPort( b_event );
00099 tc->ports()->addPort( t_event );
00100 #ifdef ORO_SIGNALLING_OPERATIONS
00101 tc->provides()->addEventOperation( o_event );
00102 tc->provides()->addEventOperation( v_event );
00103 tc->provides()->addEventOperation( v1_event );
00104 tc->provides()->addEventOperation( v2_event );
00105 tc->provides()->addEventOperation( v3_event );
00106 caller->provides()->addEventOperation( c_event );
00107 #else
00108 tc->provides()->addOperation( o_event );
00109 tc->provides()->addOperation( v_event );
00110 tc->provides()->addOperation( v1_event );
00111 tc->provides()->addOperation( v2_event );
00112 tc->provides()->addOperation( v3_event );
00113 caller->provides()->addOperation( c_event );
00114 #endif
00115
00116 tc->provides()->addOperation(setState_op).doc("Communicates state from SM").arg("state", "Name of state");
00117
00118 tc->ports()->addPort( d_event_source );
00119 tc->ports()->addPort( b_event_source );
00120 tc->ports()->addPort( t_event_source );
00121
00122 d_event_source.connectTo( &d_event );
00123 b_event_source.connectTo( &b_event );
00124 t_event_source.connectTo( &t_event );
00125 tc->start();
00126 i = 0;
00127 SimulationThread::Instance()->stop();
00128
00129 tc->addOperation("log", &StateTest::log, this);
00130 }
00131 ~StateTest(){
00132 }
00133 };
00134
00135 BOOST_FIXTURE_TEST_SUITE( StateTestSuite, StateTest )
00136
00137 BOOST_AUTO_TEST_CASE( testParseState)
00138 {
00139
00140 string prog = string("StateMachine X {\n")
00141 + " param int isten\n"
00142 + " param bool isflse\n"
00143 + " param bool isok\n"
00144 + " param double isnegative\n"
00145 + " var bool istrrue = true\n"
00146 + " var double d_dummy = -1.0\n"
00147 + " var int i_dummy = -1\n"
00148 + " var bool varinit = false\n"
00149 + " var bool b_dummy = true\n"
00150 + " initial state INIT {\n"
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 + " entry {\n"
00162 + " set varinit = (d_dummy != -1.) || (i_dummy != -1) \n"
00163 + " do test.good()\n"
00164 + " set d_dummy = 1.234\n"
00165 + " set i_dummy = -2\n"
00166 + " do test.good()\n"
00167 + " }\n"
00168 + " handle {\n"
00169 + " do test.good()\n"
00170 + " }\n"
00171 + " exit {\n"
00172 + " do test.good()\n"
00173 + " set d_dummy = 0.0\n"
00174 + " set i_dummy = 0\n"
00175 + " }\n"
00176 + " transitions {\n"
00177 + " if false then select ERROR\n"
00178 + " if varinit == true then select PRE_VARFAIL\n"
00179 + " if (d_dummy != 1.234) || (i_dummy != -2) then select ENTRYFAIL\n"
00180 + " }\n"
00181 + " transition if (istrrue == false) || (isflse == true) || (isten != 10) ||( isnegative >= 0. ) then select PARAMFAIL\n"
00182 + " transition if isok == false then select PARAMFAIL\n"
00183 + " transition select FINI\n"
00184 + " transition select ERROR\n"
00185 + " }\n"
00186 + " state PRE_ERROR { entry { do test.assert(false) }\n"
00187 + " }\n"
00188 + " state PRE_PARAMFAIL { entry { do test.assert(false) }\n"
00189 + " }\n"
00190 + " state PRE_VARFAIL { entry { do test.assert(false) }\n"
00191 + " }\n"
00192 + " state ERROR { entry { do test.assert(false) }\n"
00193 + " }\n"
00194 + " state PARAMFAIL {\n"
00195 + " entry { \n"
00196 + " do test.assertMsg( isten == 10, \"isten parameter not correctly initialised\")\n"
00197 + " do test.assertMsg( istrrue == true, \"istrrue parameter not correctly initialised\")\n"
00198 + " do test.assertMsg( isok == true, \"isok parameter not correctly initialised\")\n"
00199 + " do test.assertMsg( isflse == false, \"isflse parameter not correctly initialised\")\n"
00200 + " do test.assertMsg( true == true, \"true ident not correctly done\")\n"
00201 + " do test.assertMsg( false == false, \"false ident not correctly done\")\n"
00202 + " do test.assertMsg( isnegative == -1.0, \"isnegative parameter not correctly initialised\")\n"
00203 + " }\n"
00204 + " }\n"
00205 + " state VARFAIL { entry { do test.assert(false) }\n"
00206 + " }\n"
00207 + " state EXITFAIL { entry { do test.assert(false) }\n"
00208 + " }\n"
00209 + " state ENTRYFAIL { entry { do test.assert(false) }\n"
00210 + " }\n"
00211 + " final state FINI {\n"
00212 + " preconditions {\n"
00213 + " if (d_dummy != 0.) || (i_dummy != 0) then select EXITFAIL\n"
00214 + " if false then select ERROR\n"
00215 + " }\n"
00216 + " entry {\n"
00217 + " do test.good()\n"
00218 + " set d_dummy = -1.\n"
00219 + " set i_dummy = -1\n"
00220 + " }\n"
00221 + " handle {\n"
00222 + " do test.good()\n"
00223 + " }\n"
00224 + " exit {\n"
00225 + " do test.good()\n"
00226 + " }\n"
00227 + " transitions {\n"
00228 + " if false then select ERROR\n"
00229 + " select INIT\n"
00230 + " select ERROR\n"
00231 + " }\n"
00232 + " }\n"
00233 + " }\n"
00234
00235 + " RootMachine X x( isten = 10, isok = true, isflse=false, isnegative = -1.0) \n"
00236 ;
00237
00238 this->doState("x", prog, tc );
00239 this->finishState( "x", tc );
00240 }
00241
00242 BOOST_AUTO_TEST_CASE( testStateFailure)
00243 {
00244
00245
00246
00247 string prog = string("StateMachine X {\n")
00248 + " initial state INIT {\n"
00249 + " entry {\n"
00250 + " do test.increase()\n"
00251 + " do test.assert( test.i != 1)\n"
00252 + " }\n"
00253 + " run {\n"
00254 + " do test.assert( test.i != 2)\n"
00255 + " }\n"
00256 + " exit {\n"
00257 + " do test.assert( test.i != 3)\n"
00258 + " }\n"
00259 + " transitions {\n"
00260 + " if (true) then { do test.assert( test.i != 7); } select FINI\n"
00261 + " }\n"
00262 + " }\n"
00263 + " state ERROR {\n"
00264 + " }\n"
00265 + " final state FINI {\n"
00266 + " entry {\n"
00267 + " do test.assert( test.i != 4)\n"
00268 + " }\n"
00269 + " run {\n"
00270 + " do test.assert( test.i != 5)\n"
00271 + " }\n"
00272 + " exit {\n"
00273 + " do test.assert( test.i != 6)\n"
00274 + " }\n"
00275 + " transitions {\n"
00276 + " select ERROR\n"
00277 + " }\n"
00278 + " }\n"
00279 + " }\n"
00280 + " RootMachine X x\n"
00281 ;
00282
00283
00284 const int max = 7;
00285 int x = 0;
00286 while ( i < max && x < max) {
00287 this->doState("x", prog, tc, false );
00288
00289
00290 BOOST_CHECK_MESSAGE( sa->getStateMachineStatus("x") == StateMachine::Status::error, "Status is: " + sa->getStateMachineStatusStr("x") );
00291
00292 this->finishState( "x", tc, false);
00293 ++x;
00294 }
00295 }
00296 BOOST_AUTO_TEST_CASE( testStateChildren)
00297 {
00298
00299 string prog = string("StateMachine Y {\n")
00300 + " param double isnegative\n"
00301 + " var double t = 1.0\n"
00302 + " initial state INIT {\n"
00303 + " entry {\n"
00304 + " do test.good()\n"
00305 + " }\n"
00306 + " transitions {\n"
00307 + " if isnegative >= 0. then select PARAMFAIL\n"
00308 + " select FINI\n"
00309 + " }\n"
00310 + " }\n"
00311 + " state ERROR { entry { do test.assert(false) }\n"
00312 + " }\n"
00313 + " state PARAMFAIL { entry { do test.assert(false) }\n"
00314 + " }\n"
00315 + " state VARFAIL { entry { do test.assert(false) }\n"
00316 + " }\n"
00317 + " state EXITFAIL { entry { do test.assert(false) }\n"
00318 + " }\n"
00319 + " state ENTRYFAIL { entry { do test.assert(false) }\n"
00320 + " }\n"
00321 + " final state FINI {\n"
00322 + " entry {\n"
00323 + " do test.good()\n"
00324 + " }\n"
00325 + " transitions {\n"
00326 + " select INIT\n"
00327 + " }\n"
00328 + " }\n"
00329 + " }\n"
00330 + string("StateMachine Z {\n")
00331 + " param double neg\n"
00332 + " initial state INIT {\n"
00333 + " transitions {\n"
00334 + " if neg >= 0. then select PARAMFAIL\n"
00335 + " select FINI\n"
00336 + " }\n"
00337 + " }\n"
00338 + " state PARAMFAIL { entry { do test.assert(false) }\n"
00339 + " }\n"
00340 + " final state FINI {\n"
00341 + " transitions {\n"
00342 + " select INIT\n"
00343 + " }\n"
00344 + " }\n"
00345 + " }\n"
00346 + string("StateMachine X {\n")
00347 + " param double isnegative\n"
00348 + " var double d_dummy = -2.0\n"
00349 + " var int i_dummy = -1\n"
00350 + " SubMachine Y y1(isnegative = d_dummy)\n"
00351 + " SubMachine Y y2(isnegative = -3.0)\n"
00352 + " SubMachine Y y3(isnegative = isnegative)\n"
00353 + " SubMachine Z z1( neg = d_dummy)\n"
00354 + " initial state INIT {\n"
00355 + " entry {\n"
00356 + " do test.good()\n"
00357 + " do y1.activate()\n"
00358 + " do y2.activate()\n"
00359 + " do y3.activate()\n"
00360 + " do z1.activate()\n"
00361 + " }\n"
00362 + " exit {\n"
00363 + " do y1.start()\n"
00364 + " do y2.start()\n"
00365 + " do y3.start()\n"
00366 + " do z1.start()\n"
00367 + " }\n"
00368 + " transitions {\n"
00369 + " select FINI\n"
00370 + " }\n"
00371 + " }\n"
00372 + " state ERROR { entry { do test.assert(false) }\n"
00373 + " }\n"
00374 + " state PARAMFAIL {\n"
00375 + " entry { \n"
00376 + " do test.assertMsg( y3.isnegative == isnegative, \"y3 parameter not correctly initialised\")\n"
00377 + " do test.assertMsg( y2.isnegative == -3.0, \"y2 parameter not correctly initialised\")\n"
00378 + " do test.assertMsg( y1.isnegative == d_dummy, \"y1 parameter not correctly initialised\")\n"
00379 + " do test.assertMsg( z1.neg == d_dummy, \"z1 parameter not correctly initialised\")\n"
00380 + " }\n"
00381 + " }\n"
00382 + " state VARFAIL { entry { do test.assert(false) }\n"
00383 + " }\n"
00384 + " state EXITFAIL { entry { do test.assert(false) }\n"
00385 + " }\n"
00386 + " state ENTRYFAIL { entry { do test.assert(false) }\n"
00387 + " }\n"
00388 + " final state FINI {\n"
00389 + " entry {\n"
00390 + " do test.good()\n"
00391 + " do y1.stop()\n"
00392 + " do y2.stop()\n"
00393 + " do y3.stop()\n"
00394 + " do z1.stop()\n"
00395 + " }\n"
00396 + " exit {\n"
00397 + " do test.good()\n"
00398 + " do y1.deactivate()\n"
00399 + " do y2.deactivate()\n"
00400 + " do y3.deactivate()\n"
00401 + " do z1.deactivate()\n"
00402 + " }\n"
00403 + " transitions {\n"
00404 + " if z1.neg != d_dummy then select PARAMFAIL\n"
00405 + " if y1.isnegative != d_dummy then select PARAMFAIL\n"
00406 + " if y2.isnegative != -3.0 then select PARAMFAIL\n"
00407 + " if y3.isnegative != isnegative then select PARAMFAIL\n"
00408 + " select INIT\n"
00409 + " }\n"
00410 + " }\n"
00411 + " }\n"
00412 + " RootMachine X x( isnegative = -1.0) \n"
00413 ;
00414
00415 this->doState("x", prog, tc );
00416 this->finishState( "x", tc);
00417 }
00418
00419 BOOST_AUTO_TEST_CASE( testStateEmpty)
00420 {
00421
00422 string prog = string("StateMachine X {\n")
00423 + " initial state INIT {\n"
00424 + " transitions {\n"
00425 + " select TEST;\n"
00426 + " }\n"
00427 + " }\n"
00428 + " state TEST {\n"
00429 + " }\n"
00430 + " final state FINI {\n"
00431 + " }\n"
00432 + " }\n"
00433 + " RootMachine X x\n"
00434 ;
00435 this->doState("x", prog, tc );
00436 this->finishState( "x", tc);
00437 }
00438
00439 BOOST_AUTO_TEST_CASE( testStateEmptyChild)
00440 {
00441
00442 string prog = string("StateMachine Y {\n")
00443 + " initial state INIT {\n"
00444 + " }\n"
00445 + " final state FINI {\n"
00446 + " }\n"
00447 + "}\n"
00448 + "StateMachine X {\n"
00449 + " SubMachine Y y;\n"
00450 + " initial state INIT {\n"
00451 + " }\n"
00452 + " final state FINI {\n"
00453 + " }\n"
00454 + "}\n"
00455 + "RootMachine X x\n"
00456 ;
00457
00458 this->doState("x", prog, tc );
00459 this->finishState( "x", tc);
00460 }
00461
00462 BOOST_AUTO_TEST_CASE( testStateComments)
00463 {
00464
00465 string prog = string("// Start here\n")
00466 + "StateMachine X { //\n"
00467 + " // comment on INIT\n"
00468 + " initial state INIT /* INIT */ { // \n"
00469 + " // comment in INIT\n"
00470 + " entry /* entry */ { // \n"
00471 + " // in entry\n"
00472 + " } // end \n\n"
00473 + "//\n"
00474 + " }\n"
00475 + " // intermediate comment \n"
00476 + " final state FINI // \n"
00477 + " /* ... */\n"
00478 + " {\n"
00479 + "//\n"
00480 + " entry {\n"
00481 + " // in entry\n"
00482 + " /* in entry */\n"
00483 + " }\n\n"
00484 + "//\n"
00485 + " }\n"
00486 + "// final comment\n"
00487 + "//\n"
00488 + "}\n"
00489 + "// instantiate comment\n"
00490 + "//\n"
00491 + "RootMachine X x // end\n"
00492 ;
00493 this->doState("x", prog, tc );
00494 this->finishState( "x", tc);
00495 }
00496
00497 BOOST_AUTO_TEST_CASE( testStateOperations)
00498 {
00499
00500 string prog = string("StateMachine X {\n")
00501 + " initial state INIT {\n"
00502 + " entry {\n"
00503 + " setState( rt_string(\"INIT-ENTRY\") )\n"
00504 + " }\n"
00505 + " transitions {\n"
00506 + " select TEST;\n"
00507 + " }\n"
00508 + " }\n"
00509 + " state TEST {\n"
00510 + " var double dret\n"
00511 + " entry {\n"
00512 + " setState( rt_string(\"TEST-ENTRY\") )\n"
00513 + " methods.m0()\n"
00514 + " methods.m1(1)\n"
00515 + " methods.m2(1,2.0)\n"
00516 + " methods.m3(1,2.0,true)\n"
00517 + " methods.m4(1,2.0,true,\"hello\")\n"
00518 + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
00519 + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
00520 + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00521 + " test.assert( dret == -8.0 )\n"
00522 + " methods.o0()\n"
00523 + " methods.o1(1)\n"
00524 + " methods.o2(1,2.0)\n"
00525 + " methods.o3(1,2.0,true)\n"
00526 + " methods.o4(1,2.0,true,\"hello\")\n"
00527 + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
00528 + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
00529 + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00530 + " test.assert( dret == -8.0 )\n"
00531 + " }\n"
00532 + " run {"
00533 + " setState( rt_string(\"TEST-RUN\") )\n"
00534 + " methods.m0()\n"
00535 + " methods.m1(1)\n"
00536 + " methods.m2(1,2.0)\n"
00537 + " methods.m3(1,2.0,true)\n"
00538 + " methods.m4(1,2.0,true,\"hello\")\n"
00539 + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
00540 + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
00541 + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00542 + " test.assert( dret == -8.0 )\n"
00543 + " methods.o0()\n"
00544 + " methods.o1(1)\n"
00545 + " methods.o2(1,2.0)\n"
00546 + " methods.o3(1,2.0,true)\n"
00547 + " methods.o4(1,2.0,true,\"hello\")\n"
00548 + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
00549 + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
00550 + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00551 + " test.assert( dret == -8.0 )\n"
00552 + " }\n"
00553 + " exit {"
00554 + " setState( rt_string(\"TEST-EXIT\") )\n"
00555 + " methods.m0()\n"
00556 + " methods.m1(1)\n"
00557 + " methods.m2(1,2.0)\n"
00558 + " methods.m3(1,2.0,true)\n"
00559 + " methods.m4(1,2.0,true,\"hello\")\n"
00560 + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
00561 + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
00562 + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00563 + " test.assert( dret == -8.0 )\n"
00564 + " methods.o0()\n"
00565 + " methods.o1(1)\n"
00566 + " methods.o2(1,2.0)\n"
00567 + " methods.o3(1,2.0,true)\n"
00568 + " methods.o4(1,2.0,true,\"hello\")\n"
00569 + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
00570 + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
00571 + " methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00572 + " }\n"
00573 + " transitions {\n"
00574 + " if true then \n"
00575 + " {"
00576 + " setState( rt_string(\"TEST-TRANSIT\") )\n"
00577 + " methods.m0()\n"
00578 + " methods.m1(1)\n"
00579 + " methods.m2(1,2.0)\n"
00580 + " methods.m3(1,2.0,true)\n"
00581 + " methods.m4(1,2.0,true,\"hello\")\n"
00582 + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
00583 + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
00584 + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00585 + " test.assert( dret == -8.0 )\n"
00586 + " methods.o0()\n"
00587 + " methods.o1(1)\n"
00588 + " methods.o2(1,2.0)\n"
00589 + " methods.o3(1,2.0,true)\n"
00590 + " methods.o4(1,2.0,true,\"hello\")\n"
00591 + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
00592 + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
00593 + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00594 + " test.assert( dret == -8.0 )\n"
00595 + " } select TEST2;\n"
00596 + " }\n"
00597 + " }\n"
00598 + " state TEST2 {\n"
00599 + " entry {\n"
00600 + " setState( rt_string(\"TEST-ENTRY\") )\n"
00601 + " methods.m0()\n"
00602 + " methods.m1(1)\n"
00603 + " methods.m2(1,2.0)\n"
00604 + " methods.m3(1,2.0,true)\n"
00605 + " methods.m4(1,2.0,true,\"hello\")\n"
00606 + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
00607 + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
00608 + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00609 + " test.assert( dret == -8.0 )\n"
00610 + " methods.o0()\n"
00611 + " methods.o1(1)\n"
00612 + " methods.o2(1,2.0)\n"
00613 + " methods.o3(1,2.0,true)\n"
00614 + " methods.o4(1,2.0,true,\"hello\")\n"
00615 + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
00616 + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
00617 + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00618 + " test.assert( dret == -8.0 )\n"
00619 + " }\n"
00620 + " run {"
00621 + " setState( rt_string(\"TEST-RUN\") )\n"
00622 + " methods.m0()\n"
00623 + " methods.m1(1)\n"
00624 + " methods.m2(1,2.0)\n"
00625 + " methods.m3(1,2.0,true)\n"
00626 + " methods.m4(1,2.0,true,\"hello\")\n"
00627 + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
00628 + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
00629 + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00630 + " test.assert( dret == -8.0 )\n"
00631 + " methods.o0()\n"
00632 + " methods.o1(1)\n"
00633 + " methods.o2(1,2.0)\n"
00634 + " methods.o3(1,2.0,true)\n"
00635 + " methods.o4(1,2.0,true,\"hello\")\n"
00636 + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
00637 + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
00638 + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00639 + " test.assert( dret == -8.0 )\n"
00640 + " }\n"
00641 + " exit {"
00642 + " setState( rt_string(\"TEST-EXIT\") )\n"
00643 + " methods.m0()\n"
00644 + " methods.m1(1)\n"
00645 + " methods.m2(1,2.0)\n"
00646 + " methods.m3(1,2.0,true)\n"
00647 + " methods.m4(1,2.0,true,\"hello\")\n"
00648 + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
00649 + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
00650 + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00651 + " test.assert( dret == -8.0 )\n"
00652 + " methods.o0()\n"
00653 + " methods.o1(1)\n"
00654 + " methods.o2(1,2.0)\n"
00655 + " methods.o3(1,2.0,true)\n"
00656 + " methods.o4(1,2.0,true,\"hello\")\n"
00657 + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
00658 + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
00659 + " methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00660 + " }\n"
00661 + " transitions {\n"
00662 + " if true then \n"
00663 + " {"
00664 + " setState( rt_string(\"TEST-TRANSIT\") )\n"
00665 + " methods.m0()\n"
00666 + " methods.m1(1)\n"
00667 + " methods.m2(1,2.0)\n"
00668 + " methods.m3(1,2.0,true)\n"
00669 + " methods.m4(1,2.0,true,\"hello\")\n"
00670 + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
00671 + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
00672 + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00673 + " test.assert( dret == -8.0 )\n"
00674 + " methods.o0()\n"
00675 + " methods.o1(1)\n"
00676 + " methods.o2(1,2.0)\n"
00677 + " methods.o3(1,2.0,true)\n"
00678 + " methods.o4(1,2.0,true,\"hello\")\n"
00679 + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
00680 + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
00681 + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
00682 + " test.assert( dret == -8.0 )\n"
00683 + " } select FINI;\n"
00684 + " }\n"
00685 + " }\n"
00686 + " final state FINI {\n"
00687 + " }\n"
00688 + " }\n"
00689 + " RootMachine X x\n"
00690 ;
00691 parseState( prog, tc, true);
00692
00693 tc->stop();
00694 tc->setActivity( new Activity(0, 0.001) );
00695 tc->start();
00696
00697 StateMachinePtr sm = sa->getStateMachine("x");
00698 BOOST_REQUIRE( sm );
00699 sm->trace(true);
00700 OperationCaller<bool(StateMachine*)> act = tc->provides("x")->getOperation("activate");
00701 OperationCaller<bool(StateMachine*)> autom = tc->provides("x")->getOperation("automatic");
00702 BOOST_CHECK( act(sm.get()) );
00703 BOOST_CHECK( autom(sm.get()) );
00704
00705 sleep(1);
00706
00707 checkState( "x", tc);
00708 BOOST_CHECK( sa->getStateMachine( "x" )->inState("FINI") );
00709 this->finishState( "x", tc, false);
00710 }
00711
00712
00713 BOOST_AUTO_TEST_CASE( testStateTransitions)
00714 {
00715
00716 string prog = string("StateMachine X {\n")
00717 + " initial state INIT {\n"
00718 + " var int i = 0;\n"
00719 + " var int j = 0;\n"
00720 + " var int k = 0;\n"
00721 + " entry {\n"
00722 + " set j = j + 1\n"
00723 + " }\n"
00724 + " run {\n"
00725 + " set k = k + 1\n"
00726 + " }\n"
00727 + " transitions {\n"
00728 + " if i < 5 then {\n"
00729 + " set i = i + 1;\n"
00730 + " } select INIT\n"
00731 + " if i < 10 then {\n"
00732 + " set i = i + 1;\n"
00733 + " }\n"
00734 + " if i < 10 then {\n"
00735 + " } select TRANS_SHOULD_NOT_CHECK\n"
00736 + " if i == 10 then {\n"
00737 + " set i = i + 1;\n"
00738 + " } select TEST_ENTRY\n"
00739 + " }\n"
00740 + " }\n"
00741 + " state TEST_ENTRY {\n"
00742 + " transitions {\n"
00743 + " if k != i then {\n"
00744 + " } select RUN_FAILED\n"
00745 + " if j != 1 then {\n"
00746 + " } select ENTRY_FAILED\n"
00747 + " else select FINI\n"
00748 + " }\n"
00749 + " }\n"
00750 + " state TRANS_SHOULD_NOT_CHECK {\n"
00751 + " entry { do test.assert(false); }\n"
00752 + " }\n"
00753 + " state ENTRY_FAILED {\n"
00754 + " entry { do test.assert(false); }\n"
00755 + " }\n"
00756 + " state RUN_FAILED {\n"
00757 + " entry { do test.assert(false); }\n"
00758 + " }\n"
00759 + " final state FINI {\n"
00760 + " }\n"
00761 + " }\n"
00762 + " RootMachine X x\n"
00763 ;
00764 this->doState("x", prog, tc );
00765 BOOST_CHECK( sa->getStateMachine( "x" )->inState("FINI") );
00766 this->finishState( "x", tc);
00767 }
00768
00769 BOOST_AUTO_TEST_CASE( testStateTransitionStop )
00770 {
00771
00772 string prog = string("StateMachine X {\n")
00773 + " initial state INIT {\n"
00774 + " transitions {\n"
00775 + " if stop() == true then select NEXT\n"
00776 + " }\n"
00777 + " }\n"
00778 + " state NEXT {\n"
00779 + " entry { do test.assert(true); }\n"
00780 + " }\n"
00781 + " final state FINI {\n"
00782 + " entry { do test.assert(true); }\n"
00783 + " }\n"
00784 + " }\n"
00785 + " RootMachine X x\n"
00786 ;
00787 this->doState("x", prog, tc );
00788 BOOST_CHECK( sa->getStateMachine( "x" )->inState("NEXT") );
00789 this->finishState( "x", tc);
00790 }
00791
00792 BOOST_AUTO_TEST_CASE( testStateYield )
00793 {
00794
00795 string prog = string("StateMachine X {\n")
00796 + " initial state INIT {\n"
00797 + " var double d = 0.0\n"
00798 + " run { do o_event(1.0); test.i = 5; do test.assert(test.i == 5);\n"
00799 + " do yield;\n"
00800 + " test.i = 10;\n"
00801 + " do test.assert(false); }\n"
00802 + " transition o_event(d) select NEXT;\n"
00803 + " transitions {\n"
00804 + " select FINI\n"
00805 + " }\n"
00806 + " }\n"
00807 + " state NEXT {\n"
00808 + " entry { do test.assert(test.i == 5); }\n"
00809 + " }\n"
00810 + " final state FINI {\n"
00811 + " entry { do test.assert(true); }\n"
00812 + " }\n"
00813 + " }\n"
00814 + " RootMachine X x\n"
00815 ;
00816 this->doState("x", prog, tc );
00817 BOOST_CHECK( sa->getStateMachine( "x" )->inState("NEXT") );
00818 this->finishState( "x", tc);
00819 }
00820
00821 BOOST_AUTO_TEST_CASE( testStateYieldbySend )
00822 {
00823
00824
00825 this->o_event.getOperationCaller()->setThread(OwnThread, tc->engine() );
00826 string prog = string("StateMachine X {\n")
00827 + " initial state INIT {\n"
00828 + " var double d = 0.0\n"
00829 + " run { do o_event.send(1.0); test.i = 5; do test.assert(test.i == 5);\n"
00830 + " do yield;\n"
00831 + " test.i = 10;\n"
00832 + " do test.assert(false); }\n"
00833 + " transition o_event(d) select NEXT;\n"
00834 + " transitions {\n"
00835 + " select FINI\n"
00836 + " }\n"
00837 + " }\n"
00838 + " state NEXT {\n"
00839 + " entry { do test.assert(test.i == 5); }\n"
00840 + " }\n"
00841 + " final state FINI {\n"
00842 + " entry { do test.assert(true); }\n"
00843 + " }\n"
00844 + " }\n"
00845 + " RootMachine X x\n"
00846 ;
00847 this->doState("x", prog, tc );
00848 BOOST_CHECK( sa->getStateMachine( "x" )->inState("NEXT") );
00849 this->finishState( "x", tc);
00850 }
00851
00852 BOOST_AUTO_TEST_CASE( testStateGlobalTransitions)
00853 {
00854
00855 string prog = string("StateMachine X {\n")
00856 + " var int gi = 0;\n"
00857 + " transitions {\n"
00858
00859 + " if gi < 5 then {\n"
00860 + " set gi = gi + 1;\n"
00861 + " } select INIT\n"
00862
00863 + " if gi < 10 then {\n"
00864 + " if gi < 5 then do test.assert(false);\n"
00865 + " set gi = gi + 1;\n"
00866 + " }\n"
00867 + " if gi < 10 then {\n"
00868 + " do test.assert(false);\n"
00869 + " } select TRANS_SHOULD_NOT_CHECK\n"
00870 + " if gi >= 10 then {\n"
00871 + " } select FINI\n"
00872 + " }\n"
00873 + " initial state INIT {\n"
00874 + " var int i = 0;\n"
00875 + " var int j = 0;\n"
00876 + " var int k = 0;\n"
00877 + " entry {\n"
00878 + " set j = j + 1\n"
00879 + " }\n"
00880 + " run {\n"
00881 + " set k = k + 1\n"
00882 + " }\n"
00883 + " transitions {\n"
00884 + " if i < 5 then {\n"
00885 + " set i = i + 1;\n"
00886 + " } select INIT\n"
00887 + " if i < 10 then {\n"
00888 + " set i = i + 1;\n"
00889 + " }\n"
00890 + " if i < 10 then {\n"
00891 + " } select TRANS_SHOULD_NOT_CHECK\n"
00892 + " }\n"
00893 + " }\n"
00894 + " state TRANS_SHOULD_NOT_CHECK {\n"
00895 + " entry { do test.assert(false); }\n"
00896 + " }\n"
00897 + " state ENTRY_FAILED {\n"
00898 + " entry { do test.assert(false); }\n"
00899 + " }\n"
00900 + " state RUN_FAILED {\n"
00901 + " entry { do test.assert(false); }\n"
00902 + " }\n"
00903 + " final state FINI {\n"
00904 + " }\n"
00905 + " }\n"
00906 + " RootMachine X x\n"
00907 ;
00908 this->doState("x", prog, tc );
00909 BOOST_CHECK( sa->getStateMachine( "x" )->inState("FINI") );
00910 this->finishState( "x", tc);
00911 }
00912
00913
00914 BOOST_AUTO_TEST_CASE( testStateSubStateVars)
00915 {
00916
00917 string prog = string("StateMachine Y {\n")
00918 + " param double isnegative\n"
00919 + " var double t = 1.0\n"
00920 + " initial state INIT {\n"
00921 + " transitions {\n"
00922 + " if isnegative >= 0. then select PARAMFAIL\n"
00923 + " if t >= 0. then select VARFAIL\n"
00924 + " select FINI\n"
00925 + " }\n"
00926 + " exit { set isnegative = +1.0 }\n"
00927 + " }\n"
00928 + " state ERROR { entry { do test.assert(false) }\n"
00929 + " }\n"
00930 + " state PARAMFAIL { entry { do test.assert(false) }\n"
00931 + " }\n"
00932 + " state VARFAIL { entry { do test.assert(false) }\n"
00933 + " }\n"
00934 + " state EXITFAIL { entry { do test.assert(false) }\n"
00935 + " }\n"
00936 + " state ENTRYFAIL { entry { do test.assert(false) }\n"
00937 + " }\n"
00938 + " final state FINI {\n"
00939 + " transitions {\n"
00940 + " if isnegative <= 0. then select PARAMFAIL\n"
00941 + " }\n"
00942 + " }\n"
00943 + " }\n"
00944 + string("StateMachine X {\n")
00945 + " param double isnegative\n"
00946 + " var double d_dummy = -2.0\n"
00947 + " var int i_dummy = -1\n"
00948 + " SubMachine Y y1(isnegative = d_dummy)\n"
00949 + " initial state INIT {\n"
00950 + " entry {\n"
00951 + " do y1.trace(true)\n"
00952 + " do y1.activate()\n"
00953 + " set y1.t = -1.0 \n"
00954 + " }\n"
00955 + " exit {\n"
00956 + " do y1.start()\n"
00957 + " }\n"
00958 + " transitions {\n"
00959 + " select TEST\n"
00960 + " }\n"
00961 + " }\n"
00962 + " state TEST {\n"
00963 + " entry {\n"
00964 + " do yield\n"
00965 + " do test.assert( y1.inState(\"FINI\") )\n"
00966 + " }\n"
00967 + " transitions {\n"
00968 + " select FINI\n"
00969 + " }\n"
00970 + " }\n"
00971 + " final state FINI {\n"
00972 + " entry {\n"
00973 + " do y1.stop()\n"
00974 + " }\n"
00975 + " exit {\n"
00976 + " set y1.isnegative = -1.0 \n"
00977 + " do y1.deactivate()\n"
00978 + " }\n"
00979 + " transitions {\n"
00980 + " select INIT\n"
00981 + " }\n"
00982 + " }\n"
00983 + " }\n"
00984 + " RootMachine X x( isnegative = -1.0) \n"
00985 ;
00986
00987 this->doState("x", prog, tc );
00988 this->finishState( "x", tc);
00989 }
00990
00991 BOOST_AUTO_TEST_CASE( testStateSubStateCommands)
00992 {
00993
00994 string prog = string("StateMachine Y {\n")
00995 + " param double isnegative\n"
00996 + " var double t = 1.0\n"
00997 + " initial state INIT {\n"
00998 + " transitions {\n"
00999 + " if isnegative < 0. then select ISNEGATIVE\n"
01000 + " if t >= 0. then select ISPOSITIVE\n"
01001 + " select DEFAULT\n"
01002 + " }\n"
01003 + " }\n"
01004 + " state ISNEGATIVE {\n"
01005 + " transitions {\n"
01006 + " select INIT\n"
01007 + " }\n"
01008 + " }\n"
01009 + " state ISPOSITIVE {\n"
01010 + " transitions {\n"
01011 + " select INIT\n"
01012 + " }\n"
01013
01014 + " }\n"
01015 + " state DEFAULT {\n"
01016 + " transitions {\n"
01017 + " select FINI\n"
01018 + " }\n"
01019 + " }\n"
01020 + " final state FINI {\n"
01021 + " }\n"
01022 + " }\n"
01023 + string("StateMachine X {\n")
01024 + " SubMachine Y y1(isnegative = -1.0)\n"
01025 + " initial state INIT {\n"
01026 + " entry {\n"
01027 + " set y1.t = -1.0 \n"
01028 + " do y1.activate()\n"
01029 + " do y1.requestState(\"ISNEGATIVE\")\n"
01030 + " do test.assert( y1.inState(\"ISNEGATIVE\") )\n"
01031 + " do y1.requestState(\"INIT\")\n"
01032 + " do test.assert( y1.inState(\"INIT\") )\n"
01033 + " set y1.isnegative = +1.0 \n"
01034 + " try y1.requestState(\"ISNEGATIVE\") \n "
01035 + " catch \n{\n"
01036 + " do test.assert( y1.inState(\"INIT\") )\n"
01037 + " }\n"
01038 + " do test.assert( y1.inState(\"INIT\") )\n"
01039 + " do y1.requestState(\"FINI\")\n"
01040 + " do test.assert( y1.inState(\"FINI\") )\n"
01041 + " }\n"
01042 + " exit {\n"
01043 + " do y1.requestState(\"INIT\")\n"
01044 + " do test.assert( y1.inState(\"INIT\") )\n"
01045 + " set y1.isnegative = +1.0 \n"
01046 + " set y1.t = -1.0 \n"
01047 + " do y1.start()\n"
01048 + " while ! y1.inState(\"FINI\") \n"
01049 + " do nothing\n"
01050 + " }\n"
01051 + " transitions {\n"
01052 + " select FINI\n"
01053 + " }\n"
01054 + " }\n"
01055 + " final state FINI {\n"
01056 + " entry {\n"
01057 + " do y1.stop()\n"
01058 + " }\n"
01059 + " exit {\n"
01060 + " do y1.deactivate()\n"
01061 + " }\n"
01062 + " transitions {\n"
01063 + " select INIT\n"
01064 + " }\n"
01065 + " }\n"
01066 + " }\n"
01067 + " RootMachine X x() \n"
01068 ;
01069
01070 this->doState("x", prog, tc );
01071 this->finishState( "x", tc);
01072 }
01073
01074 #ifdef ORO_SIGNALLING_OPERATIONS
01075 BOOST_AUTO_TEST_CASE( testStateOperationSignalTransition )
01076 {
01077
01078 string prog = string("StateMachine X {\n")
01079 + " var double et = 0.0\n"
01080 + " initial state INIT {\n"
01081 + " transition o_event(et) select FINI\n"
01082 + " }\n"
01083 + " final state FINI {} \n"
01084 + "}\n"
01085 + "RootMachine X x()\n";
01086 this->parseState( prog, tc );
01087 StateMachinePtr sm = sa->getStateMachine("x");
01088 BOOST_REQUIRE( sm );
01089 this->runState("x", tc);
01090 checkState( "x", tc);
01091 OperationCaller<void(double)> mo( tc->provides()->getOperation("o_event") );
01092 mo(3.33);
01093 checkState( "x", tc);
01094 BOOST_CHECK( SimulationThread::Instance()->run(2) );
01095 checkState( "x", tc);
01096 BOOST_CHECK( sm->inState("FINI") );
01097 this->checkState("x",tc);
01098 this->finishState("x", tc);
01099 }
01100
01101 BOOST_AUTO_TEST_CASE( testStateOperationCallerSignalTransition )
01102 {
01103
01104 string prog = string("StateMachine X {\n")
01105 + " var double et = 0.0\n"
01106 + " initial state INIT {\n"
01107 + " transition caller.c_event(et) select FINI\n"
01108 + " }\n"
01109 + " final state FINI {} \n"
01110 + "}\n"
01111 + "RootMachine X x()\n";
01112 this->parseState( prog, tc );
01113 StateMachinePtr sm = sa->getStateMachine("x");
01114 BOOST_REQUIRE( sm );
01115 this->runState("x", tc);
01116 checkState( "x", tc);
01117 BOOST_CHECK( SimulationThread::Instance()->run(2) );
01118 checkState( "x", tc);
01119 OperationCaller<void(double)> mc( caller->provides()->getOperation("c_event") );
01120 mc(6.66);
01121 checkState( "x", tc);
01122 BOOST_CHECK( SimulationThread::Instance()->run(2) );
01123 checkState( "x", tc);
01124 BOOST_CHECK( sm->inState("FINI") );
01125 this->checkState("x",tc);
01126 this->finishState("x", tc);
01127 }
01128
01129 BOOST_AUTO_TEST_CASE( testStateOperationSignalMultiTransition )
01130 {
01131
01132 string prog = string("StateMachine X {\n")
01133 + " initial state INIT {\n"
01134 + " transitions { select STATE1 }\n"
01135 + " }\n"
01136 + " state STATE1 {\n"
01137 + " transition v_event() select STATE2\n"
01138 + " }\n"
01139 + " state STATE2 {\n"
01140 + " transition v_event() select FINI\n"
01141 + " }\n"
01142 + " final state FINI {} \n"
01143 + "}\n"
01144 + "RootMachine X x()\n";
01145 this->parseState( prog, tc );
01146 StateMachinePtr sm = sa->getStateMachine("x");
01147 BOOST_REQUIRE( sm );
01148 sm->trace(true);
01149
01150 this->runState("x", tc);
01151 checkState( "x", tc);
01152 BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
01153
01154 BOOST_CHECK( SimulationThread::Instance()->run(100) );
01155 checkState( "x", tc);
01156 BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
01157
01158 OperationCaller<void(void)> mo( tc->provides()->getOperation("v_event"), tc->engine());
01159 BOOST_REQUIRE( mo.ready() );
01160 mo();
01161 BOOST_CHECK( SimulationThread::Instance()->run(1) );
01162 checkState( "x", tc);
01163 BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
01164
01165 BOOST_CHECK( SimulationThread::Instance()->run(100) );
01166 checkState( "x", tc);
01167 BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
01168
01169 mo();
01170 BOOST_CHECK( SimulationThread::Instance()->run(1) );
01171 checkState( "x", tc);
01172 BOOST_CHECK_EQUAL( "FINI", sm->getCurrentStateName() );
01173 BOOST_CHECK( SimulationThread::Instance()->run(100) );
01174 checkState( "x", tc);
01175 BOOST_CHECK_EQUAL( "FINI", sm->getCurrentStateName() );
01176 this->checkState("x",tc);
01177 this->finishState("x", tc);
01178 }
01179
01180 BOOST_AUTO_TEST_CASE( testStateOperationSignalTransitionPriority )
01181 {
01182
01183 string prog = string("StateMachine X {\n")
01184 + " initial state INIT {\n"
01185 + " transitions { select STATE1 }\n"
01186 + " }\n"
01187 + " state STATE1 {\n"
01188 + " var double d;\n"
01189 + " transition v_event() select STATE2\n"
01190 + " transition v_event() select ERROR\n"
01191 + " transition o_event(d) select ERROR\n"
01192 + " transition v_event() select ERROR\n"
01193 + " }\n"
01194 + " state STATE2 {\n"
01195 + " transition v_event() select FINI\n"
01196 + " transition v_event() select ERROR\n"
01197 + " transition o_event(d) select ERROR\n"
01198 + " transition v_event() select ERROR\n"
01199 + " }\n"
01200 + " state ERROR {} \n"
01201 + " final state FINI {} \n"
01202 + "}\n"
01203 + "RootMachine X x()\n";
01204 this->parseState( prog, tc );
01205 StateMachinePtr sm = sa->getStateMachine("x");
01206 BOOST_REQUIRE( sm );
01207 sm->trace(true);
01208
01209 this->runState("x", tc);
01210 checkState( "x", tc);
01211 BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
01212
01213 BOOST_CHECK( SimulationThread::Instance()->run(100) );
01214 checkState( "x", tc);
01215 BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
01216
01217 OperationCaller<void(void)> mo( tc->provides()->getOperation("v_event"), tc->engine());
01218 OperationCaller<void(double)> mo2( tc->provides()->getOperation("o_event"), tc->engine());
01219 BOOST_REQUIRE( mo.ready() );
01220 mo();
01221 mo();
01222 mo2(3);
01223 mo2(3);
01224 BOOST_CHECK( SimulationThread::Instance()->run(1) );
01225 checkState( "x", tc);
01226 BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
01227
01228 BOOST_CHECK( SimulationThread::Instance()->run(100) );
01229 checkState( "x", tc);
01230 BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
01231
01232 mo();
01233 mo();
01234 mo2(3);
01235 mo2(3);
01236 BOOST_CHECK( SimulationThread::Instance()->run(1) );
01237 checkState( "x", tc);
01238 BOOST_CHECK_EQUAL( "FINI", sm->getCurrentStateName() );
01239 BOOST_CHECK( SimulationThread::Instance()->run(100) );
01240 checkState( "x", tc);
01241 BOOST_CHECK_EQUAL( "FINI", sm->getCurrentStateName() );
01242 this->checkState("x",tc);
01243 this->finishState("x", tc);
01244 }
01245
01246 BOOST_AUTO_TEST_CASE( testStateOperationSignalTransitionAround )
01247 {
01248
01249 string prog = string("StateMachine X {\n")
01250 + " initial state INIT {\n"
01251 + " transitions { select IDLE }\n"
01252 + " }\n"
01253 + " state IDLE {\n"
01254 + " transition v1_event() select STATE1\n"
01255 + " transition v2_event() select STATE2\n"
01256 + " transition v3_event() select STATE3\n"
01257 + " }\n"
01258 + " state STATE1 {\n"
01259 + " transition v_event() select IDLE\n"
01260 + " transition v2_event() select STATE2\n"
01261 + " transition v3_event() select STATE3\n"
01262 + " }\n"
01263 + " state STATE2 {\n"
01264 + " transition v_event() select IDLE\n"
01265 + " transition v1_event() select STATE1\n"
01266 + " transition v3_event() select STATE3\n"
01267 + " }\n"
01268 + " state STATE3 {\n"
01269 + " transition v_event() select IDLE\n"
01270 + " transition v1_event() select STATE1\n"
01271 + " transition v2_event() select STATE2\n"
01272 + " }\n"
01273 + " final state FINI {} \n"
01274 + "}\n"
01275 + "RootMachine X x()\n";
01276 this->parseState( prog, tc );
01277 StateMachinePtr sm = sa->getStateMachine("x");
01278 BOOST_REQUIRE( sm );
01279 this->runState("x", tc);
01280
01281 checkState( "x", tc);
01282 BOOST_CHECK_EQUAL( "IDLE", sm->getCurrentStateName() );
01283 BOOST_CHECK( SimulationThread::Instance()->run(100) );
01284 checkState( "x", tc);
01285 BOOST_CHECK_EQUAL( "IDLE", sm->getCurrentStateName() );
01286
01287 OperationCaller<void(void)> v( tc->provides()->getOperation("v_event"), tc->engine());
01288 BOOST_REQUIRE( v.ready() );
01289 OperationCaller<void(void)> v1( tc->provides()->getOperation("v1_event"), tc->engine());
01290 BOOST_REQUIRE( v1.ready() );
01291 OperationCaller<void(void)> v2( tc->provides()->getOperation("v2_event"), tc->engine());
01292 BOOST_REQUIRE( v2.ready() );
01293 OperationCaller<void(void)> v3( tc->provides()->getOperation("v3_event"), tc->engine());
01294 BOOST_REQUIRE( v3.ready() );
01295
01296 #define DO_EVENT(event, name) \
01297 event(); \
01298 BOOST_CHECK( SimulationThread::Instance()->run(1) ); \
01299 checkState( "x", tc); \
01300 BOOST_CHECK_EQUAL( name, sm->getCurrentStateName() ); \
01301 BOOST_CHECK( SimulationThread::Instance()->run(100) ); \
01302 checkState( "x", tc); \
01303 BOOST_CHECK_EQUAL( name, sm->getCurrentStateName() )
01304
01305 DO_EVENT(v2, "STATE2");
01306 DO_EVENT(v1, "STATE1");
01307 DO_EVENT(v1, "STATE1");
01308 DO_EVENT(v3, "STATE3");
01309 DO_EVENT(v, "IDLE");
01310 DO_EVENT(v3, "STATE3");
01311 DO_EVENT(v, "IDLE");
01312 DO_EVENT(v1, "STATE1");
01313
01314 #undef DO_EVENT
01315
01316 this->checkState("x",tc);
01317 this->finishState("x", tc);
01318 }
01319
01320 BOOST_AUTO_TEST_CASE( testStateOperationSignalTransitionProgram )
01321 {
01322 string prog = string("StateMachine X {\n")
01323 + " var double et = 0.0\n"
01324 + " initial state INIT {\n"
01325 + " transition o_event(et) { test.i = 5; } select FINI\n"
01326 + " }\n"
01327 + " final state FINI {} \n"
01328 + "}\n"
01329 + "RootMachine X x()\n";
01330 this->parseState( prog, tc );
01331 StateMachinePtr sm = sa->getStateMachine("x");
01332 BOOST_REQUIRE( sm );
01333
01334 this->runState("x", tc);
01335 checkState( "x", tc);
01336
01337 OperationCaller<void(double)> mo( tc->provides()->getOperation("o_event"), tc->engine());
01338 mo(3.33);
01339 mo(6.33);
01340 checkState( "x", tc);
01341 BOOST_CHECK( SimulationThread::Instance()->run(10) );
01342 BOOST_CHECK_EQUAL( i, 5 );
01343 checkState( "x", tc);
01344 BOOST_CHECK( sm->inState("FINI") );
01345 this->checkState("x",tc);
01346 this->finishState("x", tc);
01347 }
01348
01349 BOOST_AUTO_TEST_CASE( testStateOperationSignalGuard )
01350 {
01351 string prog = string("StateMachine X {\n")
01352 + " var double et = 0.0\n"
01353 + " initial state INIT {\n"
01354 + " transition o_event(et) if (et == 3.33) then \n"
01355 + " select FINI\n"
01356 + " else {log(\"received et != 3.33: \"+et+\": will fail.\") } select FAIL\n"
01357 + " }\n"
01358 + " final state FINI {} \n"
01359 + " state FAIL {} \n"
01360 + "}\n"
01361 + "RootMachine X x()\n";
01362 this->parseState( prog, tc );
01363 StateMachinePtr sm = sa->getStateMachine("x");
01364 BOOST_REQUIRE( sm );
01365
01366 this->runState("x", tc);
01367 checkState( "x", tc);
01368
01369 OperationCaller<void(double)> mo( tc->provides()->getOperation("o_event"), GlobalEngine::Instance() );
01370 mo(3.33);
01371 mo(6.33);
01372 checkState( "x", tc);
01373 BOOST_CHECK( SimulationThread::Instance()->run(10) );
01374 checkState( "x", tc);
01375 BOOST_CHECK( sm->inState("FINI") );
01376 this->checkState("x",tc);
01377 this->finishState("x", tc);
01378 }
01379
01380 BOOST_AUTO_TEST_CASE( testStateOperationCallerSignalGuard )
01381 {
01382 string prog = string("StateMachine X {\n")
01383 + " var double et = 0.0\n"
01384 + " initial state INIT {\n"
01385 + " transition caller.c_event(et) if (et == 3.33) then\n"
01386 + " select FINI\n"
01387 + " else select FAIL\n"
01388 + " }\n"
01389 + " final state FINI {} \n"
01390 + " state FAIL {} \n"
01391 + "}\n"
01392 + "RootMachine X x()\n";
01393 this->parseState( prog, tc );
01394 StateMachinePtr sm = sa->getStateMachine("x");
01395 BOOST_REQUIRE( sm );
01396
01397 this->runState("x", tc);
01398 checkState( "x", tc);
01399
01400 OperationCaller<void(double)> mo( caller->provides()->getOperation("c_event") );
01401 mo(3.33);
01402 checkState( "x", tc);
01403 BOOST_CHECK( SimulationThread::Instance()->run(1000) );
01404 checkState( "x", tc);
01405 BOOST_CHECK( sm->inState("FINI") );
01406 this->checkState("x",tc);
01407 this->finishState("x", tc);
01408 }
01409 #endif
01410
01411 BOOST_AUTO_TEST_CASE( testStateEvents)
01412 {
01413
01414 string prog = string("StateMachine Y {\n")
01415 + " var int t = 0\n"
01416 + " var double et_global = 0.0, et_local = 0.0\n"
01417 + " var bool eb = false\n"
01418 + " var bool eflag = false\n"
01419 + " transition t_event(t) { do log(\"Global Transition to TESTSELF\");} select TESTSELF\n"
01420 + " transition d_event(et_global)\n"
01421 + " if et_global < 0. then { do log(\"Global ISNEGATIVE Transition\");} select ISNEGATIVE\n"
01422 + " else { do log(\"Global ISPOSITIVE Transition\");} select ISPOSITIVE\n"
01423 + " initial state INIT {\n"
01424 + " entry { do log(\"INIT\"); set eb = false; }\n"
01425 + " }\n"
01426 + " state ISNEGATIVE {\n"
01427 + " entry { do log(\"ISNEGATIVE\");}\n"
01428 + " transition b_event(eb)\n"
01429 + " if (eb) then { do log(\"Local ISNEGATIVE->INIT Transition\");} select INIT\n"
01430 + " }\n"
01431 + " state ISPOSITIVE {\n"
01432 + " entry { do log(\"ISPOSITIVE\");}\n"
01433 + " transition b_event(eb)\n"
01434 + " if (eb == true) then { do log(\"Local ISPOSITIVE->INIT Transition for b_event\");} select INIT\n"
01435 #ifdef ORO_SIGNALLING_OPERATIONS
01436 + " transition o_event(et_local)\n"
01437 + " if ( et_local == 3.0 ) then { do log(\"Local ISPOSITIVE->INIT Transition for o_event == \" + et_local);} select INIT\n"
01438 #endif
01439 + " }\n"
01440 + " state TESTSELF {\n"
01441 + " entry {\n"
01442 + " do log(\"TESTSELF\");\n"
01443 + " set eflag = !eflag\n"
01444 + " }\n"
01445 + " transition t_event(t) { do log(\"Self Transition in TESTSELF\");} select TESTSELF\n"
01446 + " transition b_event(eb)\n"
01447 + " if (eb == true) then { do log(\"Local TESTSELF->INIT Transition\");} select INIT\n"
01448 + " else { log(\"Failed to select INIT upon event.\");}\n"
01449 + " }\n"
01450 + " final state FINI {\n"
01451 + " entry { do log(\"FINI\");}\n"
01452 + " }\n"
01453 + " }\n"
01454 + string("StateMachine X {\n")
01455 + " SubMachine Y y1()\n"
01456 + " initial state INIT {\n"
01457 + " entry {\n"
01458 + " do y1.trace(true)\n"
01459 + " do y1.activate()\n"
01460 + " do y1.start()\n"
01461 + " do yield\n"
01462 + " }"
01463 + " run {\n"
01464
01465 + " do d_event_source.write(-1.0)\n"
01466 + " do nothing\n"
01467 + " do test.assert( !y1.inState(\"INIT\") )\n"
01468 + " do test.assert( !y1.inState(\"ISPOSITIVE\") )\n"
01469 + " do test.assert( y1.inState(\"ISNEGATIVE\") )\n"
01470 + " do b_event_source.write( true )\n"
01471 + " do yield\n"
01472 + " do test.assert( y1.inState(\"INIT\") )\n"
01473
01474 + " do d_event_source.write(+1.0)\n"
01475 + " do nothing\n"
01476 + " do test.assert( !y1.inState(\"INIT\") )\n"
01477 + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
01478 + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
01479 + " if ( !y1.inState(\"ISPOSITIVE\") ) then\n"
01480 + " do test.assertMsg( false, \"Not ISNEGATIVE but \" + y1.getState() )\n"
01481 + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
01482 + " do b_event_source.write( true )\n"
01483 + " do yield\n"
01484
01485 + " do test.assert( y1.inState(\"INIT\") )\n"
01486 #ifdef ORO_SIGNALLING_OPERATIONS
01487
01488 + " do d_event_source.write(+1.0)\n"
01489 + " do nothing\n"
01490 + " do test.assert( !y1.inState(\"INIT\") )\n"
01491 + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
01492 + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
01493 + " if ( !y1.inState(\"ISPOSITIVE\") ) then\n"
01494 + " do test.assertMsg( false, \"Not ISPOSITIVE but \" + y1.getState() )\n"
01495 + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
01496 + " do o_event( 3.0 )\n"
01497 + " do yield\n"
01498 + " do yield\n"
01499 + " do yield\n"
01500 + " do test.assert( y1.inState(\"INIT\") )\n"
01501 #endif
01502
01503 + " set y1.eflag = true;\n"
01504 + " do t_event_source.write(1)\n"
01505 + " do nothing\n"
01506 + " do test.assert( !y1.inState(\"INIT\") )\n"
01507 + " do test.assert( !y1.inState(\"ISPOSITIVE\") )\n"
01508 + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
01509 + " do test.assert( y1.inState(\"TESTSELF\") )\n"
01510 + " do test.assert( y1.eflag == false ) /* first */\n"
01511 + " do t_event_source.write(1)\n"
01512 + " do nothing\n"
01513 + " do test.assert( y1.inState(\"TESTSELF\") )\n"
01514 + " do test.assert( y1.eflag == false ) /* second */\n"
01515 + " do log(\"Trigger b_event.\");\n"
01516 + " do b_event_source.write(true);\n"
01517 + " yield;\n"
01518 + " do test.assert( y1.inState(\"INIT\") ) /* last */\n"
01519 + " }\n"
01520 + " transitions {\n"
01521 + " select FINI\n"
01522 + " }\n"
01523 + " }\n"
01524 + " final state FINI {\n"
01525 + " entry {\n"
01526 + " do y1.deactivate()\n"
01527
01528 + " }\n"
01529 + " transitions {\n"
01530 + " select INIT\n"
01531 + " }\n"
01532 + " }\n"
01533 + " }\n"
01534 + " RootMachine X x() \n"
01535 ;
01536
01537 this->doState("x", prog, tc );
01538
01539 this->finishState( "x", tc);
01540 }
01541
01542
01543 BOOST_AUTO_TEST_CASE( testStateLevelEvents)
01544 {
01545
01546 string prog = string("StateMachine Y {\n")
01547 + " var int t = 0\n"
01548 + " var double et_global = 0.0, et_local = 0.0\n"
01549 + " var bool eb = false\n"
01550 + " var bool eflag = false\n"
01551 + " transition if ( t_event.read(t) == NewData && t == 1 ) then { do log(\"Global Transition to TESTSELF\");} select TESTSELF\n"
01552 + " transition d_event(et_global) if ( et_global < 0.) then \n"
01553 + " { do log(\"Global ISNEGATIVE Transition\");} select ISNEGATIVE\n"
01554 + " else { do log(\"Global ISPOSITIVE Transition\");} select ISPOSITIVE\n"
01555 + " initial state INIT {\n"
01556 + " entry { do log(\"INIT\"); set eb = false; }\n"
01557 + " }\n"
01558 + " state ISNEGATIVE {\n"
01559 + " entry { do log(\"ISNEGATIVE\");}\n"
01560 + " transition if ( b_event.read(eb) != NoData && eb )\n"
01561 + " then { do log(\"Local ISNEGATIVE->INIT Transition\");} select INIT\n"
01562 + " }\n"
01563 + " state ISPOSITIVE {\n"
01564 + " entry { do log(\"ISPOSITIVE\");}\n"
01565 + " transition if ( b_event.read(eb) != NoData && eb == true) \n"
01566 + " then { do log(\"Local ISPOSITIVE->INIT Transition for b_event\");} select INIT\n"
01567 #ifdef ORO_SIGNALLING_OPERATIONS
01568 + " transition o_event(et_local) if ( et_local == 3.0)\n"
01569 + " then { do log(\"Local ISPOSITIVE->INIT Transition for o_event == \" + et_local);} select INIT\n"
01570 + " else { do log(\"Local ISPOSITIVE->INIT Transition FAILED for o_event == \" + et_local);}\n"
01571 #endif
01572 + " }\n"
01573 + " state TESTSELF {\n"
01574 + " entry {\n"
01575 + " do log(\"TESTSELF\");\n"
01576 + " set eflag = !eflag\n"
01577 + " }\n"
01578 + " transition if ( t_event.read(t) == NewData ) { do log(\"Self Transition in TESTSELF\");} select TESTSELF\n"
01579 + " transition if ( b_event.read(eb) == NewData && eb == true )\n"
01580 + " then { do log(\"Local TESTSELF->INIT Transition\");} select INIT\n"
01581 + " else { log(\"Failed to select INIT upon event.\");}\n"
01582 + " }\n"
01583 + " final state FINI {\n"
01584 + " entry { do log(\"FINI\");}\n"
01585 + " }\n"
01586 + " }\n"
01587 + string("StateMachine X {\n")
01588 + " SubMachine Y y1()\n"
01589 + " initial state INIT {\n"
01590 + " entry {\n"
01591 + " do y1.trace(true)\n"
01592 + " do y1.activate()\n"
01593 + " do y1.start()\n"
01594 + " do yield\n"
01595 + " }"
01596 + " run {\n"
01597
01598 + " do d_event_source.write(-1.0)\n"
01599 + " do nothing\n"
01600 + " do test.assert( !y1.inState(\"INIT\") )\n"
01601 + " do test.assert( !y1.inState(\"ISPOSITIVE\") )\n"
01602 + " do test.assert( y1.inState(\"ISNEGATIVE\") )\n"
01603 + " do b_event_source.write( true )\n"
01604 + " do yield\n"
01605 + " do test.assert( y1.inState(\"INIT\") )\n"
01606 + " do b_event_source.write( false )\n"
01607
01608 + " do d_event_source.write(+1.0)\n"
01609 + " do nothing\n"
01610 + " do test.assert( !y1.inState(\"INIT\") )\n"
01611 + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
01612 + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
01613 + " if ( !y1.inState(\"ISPOSITIVE\") ) then\n"
01614 + " do test.assertMsg( false, \"Not ISNEGATIVE but \" + y1.getState() )\n"
01615 + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
01616 + " do b_event_source.write( true )\n"
01617 + " do yield\n"
01618
01619 + " do test.assert( y1.inState(\"INIT\") )\n"
01620 + " do b_event_source.write( false )\n"
01621 #ifdef ORO_SIGNALLING_OPERATIONS
01622
01623 + " do d_event_source.write(+1.0)\n"
01624 + " do nothing\n"
01625 + " do test.assert( !y1.inState(\"INIT\") )\n"
01626 + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
01627 + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
01628 + " if ( !y1.inState(\"ISPOSITIVE\") ) then\n"
01629 + " do test.assertMsg( false, \"Not ISPOSITIVE but \" + y1.getState() )\n"
01630 + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
01631 + " do o_event( 3.0 )\n"
01632 + " do yield\n"
01633 + " do yield\n"
01634 + " do yield\n"
01635 + " do test.assert( y1.inState(\"INIT\") )\n"
01636 #endif
01637
01638 + " set y1.eflag = true;\n"
01639 + " do t_event_source.write(1)\n"
01640 + " do nothing\n"
01641 + " do test.assert( !y1.inState(\"INIT\") )\n"
01642 + " do test.assert( !y1.inState(\"ISPOSITIVE\") )\n"
01643 + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
01644 + " do test.assert( y1.inState(\"TESTSELF\") )\n"
01645 + " do test.assert( y1.eflag == false ) /* first */\n"
01646 + " do t_event_source.write(1)\n"
01647 + " do nothing\n"
01648 + " do test.assert( y1.inState(\"TESTSELF\") )\n"
01649 + " do test.assert( y1.eflag == false ) /* second */\n"
01650 + " do log(\"Trigger b_event.\");\n"
01651 + " do b_event_source.write(true);\n"
01652 + " yield;\n"
01653 + " do test.assert( y1.inState(\"INIT\") ) /* last */\n"
01654 + " }\n"
01655 + " transitions {\n"
01656 + " select FINI\n"
01657 + " }\n"
01658 + " }\n"
01659 + " final state FINI {\n"
01660 + " entry {\n"
01661 + " do y1.deactivate()\n"
01662
01663 + " }\n"
01664 + " transitions {\n"
01665 + " select INIT\n"
01666 + " }\n"
01667 + " }\n"
01668 + " }\n"
01669 + " RootMachine X x() \n"
01670 ;
01671
01672 this->doState("x", prog, tc, true, 100 );
01673
01674 this->finishState( "x", tc);
01675 }
01676
01677 BOOST_AUTO_TEST_CASE( testSelfDeactivatingStateMachineinEntry )
01678 {
01679 string prog = string("StateMachine X {\n")
01680 + " initial state INIT {\n"
01681 + " transitions {select FINI} \n"
01682 + " }\n"
01683 + " final state FINI {\n"
01684 + " entry{\n"
01685 + " try scripting.deactivateStateMachine(\"x\")\n"
01686 + " }\n"
01687 + " }\n"
01688 + "}\n"
01689 + "RootMachine X x()\n";
01690 this->parseState( prog, tc );
01691 StateMachinePtr sm = sa->getStateMachine("x");
01692 BOOST_REQUIRE( sm );
01693
01694 runState( "x", tc, false);
01695 BOOST_CHECK( !sm->isActive() );
01696
01697 runState( "x", tc, true);
01698 BOOST_CHECK( !sm->isActive() );
01699
01700 }
01701
01702 BOOST_AUTO_TEST_CASE( testSelfDeactivatingStateMachineinRun )
01703 {
01704 string prog = string("StateMachine X {\n")
01705 + " initial state INIT {\n"
01706 + " transitions {select FINI} \n"
01707 + " }\n"
01708 + " final state FINI {\n"
01709 + " run{\n"
01710 + " try scripting.deactivateStateMachine(\"x\")\n"
01711 + " }\n"
01712 + " }\n"
01713 + "}\n"
01714 + "RootMachine X x()\n";
01715 this->parseState( prog, tc );
01716 StateMachinePtr sm = sa->getStateMachine("x");
01717 BOOST_REQUIRE( sm );
01718
01719 runState( "x", tc, false);
01720 BOOST_CHECK( !sm->isActive() );
01721
01722 runState( "x", tc, true);
01723 BOOST_CHECK( !sm->isActive() );
01724 }
01725
01726 BOOST_AUTO_TEST_CASE( testSelfDeactivatingStateMachineinHandle )
01727 {
01728 string prog = string("StateMachine X {\n")
01729 + " initial state INIT {\n"
01730 + " handle{\n"
01731 + " try scripting.deactivateStateMachine(\"x\")\n"
01732 + " }\n"
01733 + " transition if false == true then select FINI \n"
01734 + " }\n"
01735 + " final state FINI {\n"
01736 + " }\n"
01737 + "}\n"
01738 + "RootMachine X x()\n";
01739 this->parseState( prog, tc );
01740 StateMachinePtr sm = sa->getStateMachine("x");
01741 BOOST_REQUIRE( sm );
01742
01743 runState( "x", tc, false);
01744 BOOST_CHECK( !sm->isActive() );
01745
01746 runState( "x", tc, true);
01747 BOOST_CHECK( !sm->isActive() );
01748 }
01749
01750 BOOST_AUTO_TEST_CASE( testSelfDeactivatingStateMachineinExit )
01751 {
01752 string prog = string("StateMachine X {\n")
01753 + " initial state INIT {\n"
01754 + " exit{\n"
01755 + " try scripting.deactivateStateMachine(\"x\")\n"
01756 + " }\n"
01757 + " transitions {select FINI} \n"
01758 + " }\n"
01759 + " final state FINI {\n"
01760 + " }\n"
01761 + "}\n"
01762 + "RootMachine X x()\n";
01763 this->parseState( prog, tc );
01764 StateMachinePtr sm = sa->getStateMachine("x");
01765 BOOST_REQUIRE( sm );
01766
01767 runState( "x", tc, false);
01768 BOOST_CHECK( !sm->isActive() );
01769
01770 runState( "x", tc, true);
01771 BOOST_CHECK( !sm->isActive() );
01772 }
01773
01774 BOOST_AUTO_TEST_CASE( testSelfDeactivatingStateMachineinTransition )
01775 {
01776 string prog = string("StateMachine X {\n")
01777 + " initial state INIT {\n"
01778 + " transition if true then {\n"
01779 + " scripting.deactivateStateMachine(\"x\")\n"
01780 + " }select FINI \n"
01781 + " }\n"
01782 + " final state FINI {\n"
01783 + " }\n"
01784 + "}\n"
01785 + "RootMachine X x()\n";
01786 this->parseState( prog, tc );
01787 StateMachinePtr sm = sa->getStateMachine("x");
01788 BOOST_REQUIRE( sm );
01789
01790 runState( "x", tc, false);
01791 BOOST_CHECK( !sm->isActive() );
01792
01793 runState( "x", tc, true);
01794 BOOST_CHECK( !sm->isActive() );
01795 }
01796
01797 BOOST_AUTO_TEST_SUITE_END()
01798
01799 void StateTest::doState( const std::string& name, const std::string& prog, TaskContext* tc, bool test, int runs )
01800 {
01801 BOOST_CHECK( tc->engine() );
01802
01803 parseState( prog, tc, test);
01804 runState(name, tc, true, test,runs);
01805 checkState(name, tc, test);
01806 }
01807
01808 void StateTest::parseState(const std::string& prog, TaskContext* tc, bool test )
01809 {
01810
01811 try {
01812 sa->loadStateMachines( prog, std::string("state_test.cpp"), true );
01813 }
01814 catch( const file_parse_exception& exc )
01815 {
01816 BOOST_REQUIRE_MESSAGE( !test, exc.what() );
01817 }
01818 catch( const parse_exception& exc )
01819 {
01820 BOOST_REQUIRE_MESSAGE( !test, exc.what() );
01821 }
01822 catch( const program_load_exception& e)
01823 {
01824 BOOST_REQUIRE_MESSAGE( !test, e.what() );
01825 }
01826 catch( const std::exception& e ) {
01827 BOOST_CHECK_MESSAGE( !test , e.what());
01828 BOOST_REQUIRE_MESSAGE( !test, "Uncaught Processor load exception" );
01829 }
01830 }
01831
01832 void StateTest::runState(const std::string& name, TaskContext* tc, bool trace, bool test, int runs )
01833 {
01834 StateMachinePtr sm = sa->getStateMachine(name);
01835 BOOST_REQUIRE( sm );
01836 sm->trace(trace);
01837 OperationCaller<bool(StateMachine*)> act = tc->provides(name)->getOperation("activate");
01838 OperationCaller<bool(StateMachine*)> autom = tc->provides(name)->getOperation("automatic");
01839 BOOST_CHECK( act(sm.get()) );
01840 BOOST_CHECK( SimulationThread::Instance()->run(1) );
01841 BOOST_CHECK_MESSAGE( sm->isActive(), "Error : Activate Command for '"+sm->getName()+"' did not have effect." );
01842 BOOST_CHECK( autom(sm.get()) || !test );
01843
01844 BOOST_CHECK( SimulationThread::Instance()->run(runs) );
01845 }
01846
01847 void StateTest::checkState(const std::string& name, TaskContext* tc, bool test )
01848 {
01849 StateMachinePtr sm = sa->getStateMachine(name);
01850 BOOST_REQUIRE( sm );
01851 if ( test ) {
01852
01853 BOOST_CHECK_MESSAGE( sm->isActive(), "Error : State Context '"+sm->getName()+"' did not get activated." );
01854 stringstream errormsg;
01855 int line = sm->getLineNumber();
01856 errormsg <<" in StateMachine "+sm->getName()
01857 <<" in state "<< (sm->currentState() ? sm->currentState()->getName() : "(null)")
01858 <<" on line " << line <<" of that StateMachine:"<<endl;
01859 {
01860 stringstream sctext( sm->getText() );
01861 int cnt = 1;
01862 while ( cnt++ <line && sctext ) {
01863 string garbage;
01864 getline( sctext, garbage, '\n' );
01865 }
01866 getline( sctext, sline, '\n' );
01867 }
01868 errormsg <<"here > " << sline << endl;
01869 if ( sm->inError() ) {
01870 RTT::scripting::DumpObject( tc->provides() );
01871 RTT::scripting::DumpObject( tc->provides(name) );
01872 }
01873 BOOST_CHECK_MESSAGE( sm->inError() == false, "Runtime error (inError() == true) encountered" + errormsg.str() );
01874
01875 StateMachine::ChildList cl = sm->getChildren();
01876 StateMachine::ChildList::iterator clit = cl.begin();
01877 while( clit != cl.end() ) {
01878 line = (*clit)->getLineNumber();
01879 {
01880 stringstream sctext( (*clit)->getText() );
01881 int cnt = 1;
01882 while ( cnt++ <line && sctext ) {
01883 string garbage;
01884 getline( sctext, garbage, '\n' );
01885 }
01886 getline( sctext, sline, '\n' );
01887 }
01888 stringstream cerrormsg;
01889 if ( (*clit)->currentState() )
01890 cerrormsg <<" in child "<< (*clit)->getName() <<" in state "<<(*clit)->currentState()->getName()<< " on line " << (*clit)->getLineNumber() <<" of that StateMachine."<<endl <<"here > " << sline << endl;
01891 else
01892 cerrormsg <<" child "<< (*clit)->getName() << " (deactivated) on line " << (*clit)->getLineNumber() <<" of that StateMachine."<<endl<<"here > " << sline << endl;
01893
01894 BOOST_CHECK_MESSAGE( (*clit)->inError() == false, "Runtime error (inError() == true) encountered" + cerrormsg.str() );
01895 if ( (*clit)->inError() == false && sm->inError() == true) {
01896 cout << "Child Status:" << cerrormsg.str() << endl;
01897 }
01898 ++clit;
01899 }
01900 }
01901 }
01902
01903 void StateTest::finishState(std::string const& name, TaskContext* tc, bool test)
01904 {
01905 StateMachinePtr sm = sa->getStateMachine(name);
01906 BOOST_REQUIRE( sm );
01907 BOOST_CHECK( sa->getStateMachine( name )->stop() );
01908 BOOST_CHECK( SimulationThread::Instance()->run(10) );
01909 if (test) {
01910 stringstream errormsg;
01911 errormsg << " on line " << sm->getLineNumber() <<", status is "<< sa->getStateMachineStatusStr(name) <<endl <<"here > " << sline << endl;;
01912 BOOST_CHECK_MESSAGE( sm->isStopped(), "StateMachine stalled " + errormsg.str() );
01913 }
01914
01915
01916 BOOST_CHECK( sa->getStateMachine( name )->deactivate() );
01917 BOOST_CHECK( SimulationThread::Instance()->run(10) );
01918 if ( sm->isActive() )
01919 BOOST_CHECK( sa->getStateMachine( name )->deactivate() );
01920 BOOST_CHECK( SimulationThread::Instance()->run(10) );
01921 BOOST_CHECK( sa->getStateMachine( name )->isActive() == false );
01922
01923
01924 tc->stop();
01925
01926 try {
01927 BOOST_CHECK( sa->unloadStateMachine( name ) );
01928 }
01929 catch( const program_unload_exception& e)
01930 {
01931 BOOST_REQUIRE_MESSAGE( false, e.what() );
01932 }
01933 catch( ... ) {
01934 BOOST_REQUIRE_MESSAGE( false, "Uncaught Processor unload exception" );
01935 }
01936
01937 }
01938