state_test.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   tag: Peter Soetens  Mon Jan 10 15:59:51 CET 2005  state_test.cpp
00003 
00004                         state_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 <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         //cout << "State = " << mrt_state.c_str() << endl;
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     // a state which should never fail
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" // 10
00150         + " initial state INIT {\n"
00151         // XXX bug : preconditions are not checked in the initial state.
00152 //         + " preconditions {\n"
00153 //         + "     if (istrrue == false) || (isflse == true) || (isten != 10) ||( isnegative >= 0. )  then select PRE_PARAMFAIL\n"
00154 //         + "     if false then select PRE_ERROR\n"
00155 //         + "     if (isnegative != -1.) then select PRE_PARAMFAIL\n"
00156 //         + "     if (istrrue != true) then select PRE_PARAMFAIL\n"
00157 //         + "     if (isflse != false) then select PRE_PARAMFAIL\n"
00158 //         + "     if (isten != 10 ) then select PRE_PARAMFAIL\n"
00159 //         + "     if (d_dummy != -1.) || (i_dummy != -1) then select PRE_VARFAIL\n"
00160 //         + " }\n"
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" // 20
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" // 30
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" // do not reach
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" // do not reach
00231         + " }\n"
00232         + " }\n"
00233         + " }\n"
00234         //        + " RootMachine X x( isten = 10, isflse = false, isnegative = -1.0) \n" // instantiate a non hierarchical SC
00235         + " RootMachine X x( isten = 10, isok = true, isflse=false, isnegative = -1.0) \n" // instantiate a non hierarchical SC
00236         ;
00237 
00238     this->doState("x", prog, tc );
00239     this->finishState( "x", tc );
00240 }
00241 
00242 BOOST_AUTO_TEST_CASE( testStateFailure)
00243 {
00244     // test _command_ (through methods though) failure detection on several places.
00245     // it is an incomplete test, even more that parsing should fail on the second
00246     // run since the type 'X' is defined twice.
00247     string prog = string("StateMachine X {\n")
00248         + " initial state INIT {\n"
00249         + " entry {\n"
00250         + "     do test.increase()\n"                // set i to i+1
00251         + "     do test.assert( test.i != 1)\n" // fail if i == 1
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" // instantiate a non hierarchical SC
00281         ;
00282 
00283     // should fail each time
00284     const int max = 7;
00285     int x = 0;
00286     while ( i < max && x < max) {
00287         this->doState("x", prog, tc, false );
00288         //cout << "i is: "<< i <<endl;
00289         // assert that an error happened :
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     // instantiate two children and check init of vars and params
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" // instantiate a hierarchical SC
00413         ;
00414 
00415     this->doState("x", prog, tc );
00416     this->finishState( "x", tc);
00417 }
00418 
00419 BOOST_AUTO_TEST_CASE( testStateEmpty)
00420 {
00421     // test processing of completely empty states
00422     string prog = string("StateMachine X {\n")
00423         + " initial state INIT {\n"
00424         + " transitions {\n"
00425         + "     select TEST;\n" // only a transition
00426         + " }\n"
00427         + " }\n"
00428         + " state TEST {\n"  // not even used
00429         + " }\n"
00430         + " final state FINI {\n" // completely empty
00431         + " }\n"
00432         + " }\n"
00433         + " RootMachine X x\n" // instantiate a non hierarchical SC
00434         ;
00435      this->doState("x", prog, tc );
00436      this->finishState( "x", tc);
00437 }
00438 
00439 BOOST_AUTO_TEST_CASE( testStateEmptyChild)
00440 {
00441     // test processing of completely empty states
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     // test parsing of comments
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     // test processing of operations (OwnThread + ClientThread):
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" // only a transition
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" // completely empty
00687         + " }\n"
00688         + " }\n"
00689         + " RootMachine X x\n" // instantiate a non hierarchical SC
00690         ;
00691      parseState( prog, tc, true);
00692 
00693      tc->stop();
00694      tc->setActivity( new Activity(0, 0.001) ); // deliberately test with real thread instead of simulation.
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); // we must allow the thread to transition...
00706 
00707      checkState( "x", tc);
00708      BOOST_CHECK( sa->getStateMachine( "x" )->inState("FINI") );
00709      this->finishState( "x", tc, false); // don't test
00710 }
00711 
00712 
00713 BOOST_AUTO_TEST_CASE( testStateTransitions)
00714 {
00715     // test processing of transition statements.
00716     string prog = string("StateMachine X {\n")
00717         + " initial state INIT {\n"
00718         + " var int i = 0;\n" // transition counter
00719         + " var int j = 0;\n" // entry counter
00720         + " var int k = 0;\n" // run counter
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" // execute this program
00730         + "  } select INIT\n" // test EXPLICIT transition to self: no entry/exit.
00731         + "  if i < 10 then {\n"
00732         + "    set i = i + 1;\n" // execute this program
00733         + "  }\n" // test IMPLICIT transition to self: no entry/exit.
00734         + "  if i < 10 then {\n"
00735         + "  } select TRANS_SHOULD_NOT_CHECK\n" // should never be reached.
00736         + "  if i == 10 then {\n"
00737         + "    set i = i + 1;\n" // execute this program
00738         + "  } select TEST_ENTRY\n"
00739         + " }\n"
00740         + " }\n"
00741         + " state TEST_ENTRY {\n" // test if entry was executed one time
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" // failure state
00751         + " entry { do test.assert(false); }\n"
00752         + " }\n"
00753         + " state ENTRY_FAILED {\n"           // failure state
00754         + " entry { do test.assert(false); }\n"
00755         + " }\n"
00756         + " state RUN_FAILED {\n"           // failure state
00757         + " entry { do test.assert(false); }\n"
00758         + " }\n"
00759         + " final state FINI {\n" // Success state.
00760         + " }\n"
00761         + " }\n"
00762         + " RootMachine X x\n" // instantiate a non hierarchical SC
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     // test processing of transition statements.
00772     string prog = string("StateMachine X {\n")
00773         + " initial state INIT {\n"
00774         + " transitions {\n"
00775         + "  if stop() == true then select NEXT\n" // calls stop on the component !
00776         + " }\n"
00777         + " }\n"
00778         + " state NEXT {\n" // Success state.
00779         + " entry { do test.assert(true); }\n"
00780         + " }\n"
00781         + " final state FINI {\n" // Failure state.
00782         + " entry { do test.assert(true); }\n"
00783         + " }\n"
00784         + " }\n"
00785         + " RootMachine X x\n" // instantiate a non hierarchical SC
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     // test processing of yield statements when an eventTransition occurs:
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" // synchronous call on o_event, so signal must be delivered when we return.
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" // Success state.
00808         + " entry { do test.assert(test.i == 5); }\n"
00809         + " }\n"
00810         + " final state FINI {\n" // Failure state.
00811         + " entry { do test.assert(true); }\n"
00812         + " }\n"
00813         + " }\n"
00814         + " RootMachine X x\n" // instantiate a non hierarchical SC
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     // test processing of yield statements when a sent eventTransition occurs:
00824     // make o_event an ownthread op :
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" // asynchronous send on o_event, so signal must be processed when we return.
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" // Success state.
00839         + " entry { do test.assert(test.i == 5); }\n"
00840         + " }\n"
00841         + " final state FINI {\n" // Failure state.
00842         + " entry { do test.assert(true); }\n"
00843         + " }\n"
00844         + " }\n"
00845         + " RootMachine X x\n" // instantiate a non hierarchical SC
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     // test processing of transition statements.
00855     string prog = string("StateMachine X {\n")
00856         + " var int gi = 0;\n" // transition counter
00857         + " transitions {\n"
00858 
00859         + "  if gi < 5 then {\n"
00860         + "    set gi = gi + 1;\n" // execute this program
00861         + "  } select INIT\n" // test EXPLICIT transition to self: no entry/exit.
00862 
00863         + "  if gi < 10 then {\n"
00864         + "    if gi < 5 then do test.assert(false);\n"
00865         + "    set gi = gi + 1;\n" // execute this program
00866         + "  }\n" // test IMPLICIT transition to self: no entry/exit.
00867         + "  if gi < 10 then {\n"
00868         + "   do test.assert(false);\n"
00869         + "  } select TRANS_SHOULD_NOT_CHECK\n" // should never be reached.
00870         + "  if gi >= 10 then {\n"
00871         + "  } select FINI\n" // we must be checked before
00872         + " }\n"
00873         + " initial state INIT {\n"
00874         + " var int i = 0;\n" // transition counter
00875         + " var int j = 0;\n" // entry counter
00876         + " var int k = 0;\n" // run counter
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" // execute this program
00886         + "  } select INIT\n" // test EXPLICIT transition to self: no entry/exit.
00887         + "  if i < 10 then {\n"
00888         + "    set i = i + 1;\n" // execute this program
00889         + "  }\n" // test IMPLICIT transition to self: no entry/exit.
00890         + "  if i < 10 then {\n"
00891         + "  } select TRANS_SHOULD_NOT_CHECK\n" // should never be reached.
00892         + " }\n"
00893         + " }\n"
00894         + " state TRANS_SHOULD_NOT_CHECK {\n" // failure state
00895         + " entry { do test.assert(false); }\n"
00896         + " }\n"
00897         + " state ENTRY_FAILED {\n"           // failure state
00898         + " entry { do test.assert(false); }\n"
00899         + " }\n"
00900         + " state RUN_FAILED {\n"           // failure state
00901         + " entry { do test.assert(false); }\n"
00902         + " }\n"
00903         + " final state FINI {\n" // Success state.
00904         + " }\n"
00905         + " }\n"
00906         + " RootMachine X x\n" // instantiate a non hierarchical SC
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     // test get/set access of substate variables and parameters
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" // 11
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" // 21
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" //31
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" // if y1 not in FINI, stop here.
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" // prepare y1 to start-over
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" // start-over y1.
00981         + " }\n"
00982         + " }\n"
00983         + " }\n"
00984         + " RootMachine X x( isnegative = -1.0) \n" // instantiate a hierarchical SC
00985         ;
00986 
00987      this->doState("x", prog, tc );
00988      this->finishState( "x", tc);
00989 }
00990 
00991 BOOST_AUTO_TEST_CASE( testStateSubStateCommands)
00992 {
00993     // test get/set access of substate variables and parameters
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         // 20 :
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") // 1
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" // do not leave INIT
01037         + "     }\n"
01038         + "     do test.assert( y1.inState(\"INIT\") )\n" // do not leave INIT
01039         + "     do y1.requestState(\"FINI\")\n"      // request final state
01040         + "     do test.assert( y1.inState(\"FINI\") )\n"
01041         + " }\n"
01042         + " exit {\n"
01043         + "     do y1.requestState(\"INIT\")\n"      // request initial state
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"  // must reach FINI after a while.
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" // instantiate a hierarchical SC
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     // test event reception from own component
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" // test signal transition
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     // test event reception from another component
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" // test signal transition
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     // test multi-event reception from own component
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" // test signal transition
01138     + " }\n"
01139     + " state STATE2 {\n"
01140     + "    transition v_event() select FINI\n"   // test signal transition
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     // into STATE1
01150     this->runState("x", tc);
01151     checkState( "x", tc);
01152     BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
01153     // remain in STATE1
01154     BOOST_CHECK( SimulationThread::Instance()->run(100) );
01155     checkState( "x", tc);
01156     BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
01157     // into STATE2
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) ); // allow to transition
01162     checkState( "x", tc);
01163     BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
01164     // remain in STATE2
01165     BOOST_CHECK( SimulationThread::Instance()->run(100) );
01166     checkState( "x", tc);
01167     BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
01168     // into FINI
01169     mo();
01170     BOOST_CHECK( SimulationThread::Instance()->run(1) ); // allow to transition
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     // test event reception transition priority
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" // test signal transition
01190     + "    transition v_event() select ERROR\n"   // This one should not be taken.
01191     + "    transition o_event(d) select ERROR\n"   // This one should not be taken.
01192     + "    transition v_event() select ERROR\n"   // This one should not be taken.
01193     + " }\n"
01194     + " state STATE2 {\n"
01195     + "    transition v_event() select FINI\n"   // test signal transition
01196     + "    transition v_event() select ERROR\n"   // This one should not be taken.
01197     + "    transition o_event(d) select ERROR\n"   // This one should not be taken.
01198     + "    transition v_event() select ERROR\n"   // This one should not be taken.
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     // into STATE1
01209     this->runState("x", tc);
01210     checkState( "x", tc);
01211     BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
01212     // remain in STATE1
01213     BOOST_CHECK( SimulationThread::Instance()->run(100) );
01214     checkState( "x", tc);
01215     BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
01216     // into STATE2
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) ); // allow to transition
01225     checkState( "x", tc);
01226     BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
01227     // remain in STATE2
01228     BOOST_CHECK( SimulationThread::Instance()->run(100) );
01229     checkState( "x", tc);
01230     BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
01231     // into FINI
01232     mo();
01233     mo();
01234     mo2(3);
01235     mo2(3);
01236     BOOST_CHECK( SimulationThread::Instance()->run(1) ); // allow to transition
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     // test event reception hopping from one state to another
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     // into IDLE
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");     // no change
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" // test program
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     //checkState( prog, tc);
01334     this->runState("x", tc);
01335     checkState( "x", tc);
01336     // transition to FINI:
01337     OperationCaller<void(double)> mo( tc->provides()->getOperation("o_event"), tc->engine());
01338     mo(3.33);
01339     mo(6.33); // should be ignored
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" // test guard
01356         + "        else {log(\"received et != 3.33: \"+et+\": will fail.\") } select FAIL\n" // test guard
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     //checkState( prog, tc);
01366     this->runState("x", tc);
01367     checkState( "x", tc);
01368     // transition to FINI:
01369     OperationCaller<void(double)> mo( tc->provides()->getOperation("o_event"), GlobalEngine::Instance() );
01370     mo(3.33);
01371     mo(6.33); // should be ignored
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" // test guard
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     //checkState( prog, tc);
01397     this->runState("x", tc);
01398     checkState( "x", tc);
01399     // causes error state when received in INIT:
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     // test event reception in sub states.
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" // test self transition
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" // NewData == false !!!
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" // 20
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"     // does not execute entry {}, overrides global t_event()
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" // 40
01454         + string("StateMachine X {\n") // 1
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" // 11
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" // go to INIT.
01471         + "     do yield\n"
01472         + "     do test.assert( y1.inState(\"INIT\") )\n"
01473 
01474         + "     do d_event_source.write(+1.0)\n" // 21
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" // go to INIT.
01483         + "     do yield\n"
01484 
01485         + "     do test.assert( y1.inState(\"INIT\") )\n" // 31
01486 #ifdef ORO_SIGNALLING_OPERATIONS
01487         // test operation
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" // go to INIT.
01497         + "     do yield\n"
01498         + "     do yield\n"
01499         + "     do yield\n"
01500         + "     do test.assert( y1.inState(\"INIT\") )\n"
01501 #endif
01502         // test self transitions
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" // no entry
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         //+ "     do test.assert(false)\n"
01528         + " }\n"
01529         + " transitions {\n"
01530         + "     select INIT\n"
01531         + " }\n"
01532         + " }\n"
01533         + " }\n"
01534         + " RootMachine X x() \n" // instantiate a hierarchical SC
01535         ;
01536 
01537      this->doState("x", prog, tc );
01538      //BOOST_CHECK( tc->engine()->states()->getStateMachine( "x" )->inState("FINI") );
01539      this->finishState( "x", tc);
01540 }
01541 
01542 
01543 BOOST_AUTO_TEST_CASE( testStateLevelEvents)
01544 {
01545     // test event reception in sub states.
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" // test self transition
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" // once eb is true (or was true already), transition
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" // 20
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"     // does not execute entry {}, overrides global t_event()
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" // 40
01587         + string("StateMachine X {\n") // 1
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" // 11
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" // go to INIT.
01604         + "     do yield\n"
01605         + "     do test.assert( y1.inState(\"INIT\") )\n"
01606         + "     do b_event_source.write( false )\n" // clear the b_event for level sake
01607 
01608         + "     do d_event_source.write(+1.0)\n"
01609         + "     do nothing\n"
01610         + "     do test.assert( !y1.inState(\"INIT\") )\n"//21
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" // go to INIT.
01617         + "     do yield\n"
01618 
01619         + "     do test.assert( y1.inState(\"INIT\") )\n"
01620         + "     do b_event_source.write( false )\n" // clear the b_event for level sake
01621 #ifdef ORO_SIGNALLING_OPERATIONS
01622         // test operation
01623         + "     do d_event_source.write(+1.0)\n"
01624         + "     do nothing\n" // 31
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" // go to INIT.
01632         + "     do yield\n"
01633         + "     do yield\n" // 40
01634         + "     do yield\n"
01635         + "     do test.assert( y1.inState(\"INIT\") )\n"
01636 #endif
01637         // test self transitions
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" // no entry
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         //+ "     do test.assert(false)\n"
01663         + " }\n"
01664         + " transitions {\n"
01665         + "     select INIT\n"
01666         + " }\n"
01667         + " }\n"
01668         + " }\n"
01669         + " RootMachine X x() \n" // instantiate a hierarchical SC
01670         ;
01671 
01672      this->doState("x", prog, tc, true, 100 );
01673      //BOOST_CHECK( tc->engine()->states()->getStateMachine( "x" )->inState("FINI") );
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     // causes deactivation of SM:
01694     runState( "x", tc, false);//without trace
01695     BOOST_CHECK( !sm->isActive() );
01696     // causes deactivation of SM:
01697     runState( "x", tc, true);//with trace
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     // causes deactivation of SM:
01719     runState( "x", tc, false);//without trace
01720     BOOST_CHECK( !sm->isActive() );
01721     // causes deactivation of SM:
01722     runState( "x", tc, true);//with trace
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     // causes deactivation of SM:
01743     runState( "x", tc, false);//without trace
01744     BOOST_CHECK( !sm->isActive() );
01745     // causes deactivation of SM:
01746     runState( "x", tc, true);//with trace
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     // causes deactivation of SM:
01767     runState( "x", tc, false);//without trace
01768     BOOST_CHECK( !sm->isActive() );
01769     // causes deactivation of SM:
01770     runState( "x", tc, true);//with trace
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     // causes deactivation of SM:
01790     runState( "x", tc, false);//without trace
01791     BOOST_CHECK( !sm->isActive() );
01792     // causes deactivation of SM:
01793     runState( "x", tc, true);//with trace
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     // Alternative way: test ScriptingService as well.
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         // check error status of parent :
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         // check error status of all children:
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     // you can call deactivate even when the proc is not running.
01915     // but deactivation may be 'in progress if exit state has commands in it.
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     // only stop now, since deactivate won't work if simtask not running.
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 


rtt
Author(s): RTT Developers
autogenerated on Fri Sep 9 2016 04:02:15