state_test.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Mon Jan 10 15:59:51 CET 2005 state_test.cpp
3 
4  state_test.cpp - description
5  -------------------
6  begin : Mon January 10 2005
7  copyright : (C) 2005 Peter Soetens
8  email : peter.soetens@mech.kuleuven.ac.be
9 
10  ***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "unit.hpp"
20 
21 #include <rtt-config.h>
26 #include <scripting/DumpObject.hpp>
29 
30 #include <Service.hpp>
31 #include <TaskContext.hpp>
32 #include <OperationCaller.hpp>
33 #include <Port.hpp>
35 #include <rt_string.hpp>
36 #include "operations_fixture.hpp"
37 
38 #include <string>
39 #include <iostream>
40 #include <sstream>
41 
42 using namespace RTT;
43 using namespace RTT::detail;
44 using namespace RTT::internal;
45 using namespace std;
46 
47 class StateTest
48  : public OperationsFixture
49 {
50 public:
64 
66  void setState(RTT::rt_string state) {
67  mrt_state = state;
68  //cout << "State = " << mrt_state.c_str() << endl;
69  }
70 
72 
73  int var_i;
74  int const_i;
76 
77  void log(const std::string& msg) {
78  Logger::log(Logger::Info) << msg << endlog();
79  }
80  void doState(const std::string& name, const std::string& prog, TaskContext*, bool test=true, int runs = 1000 );
81  void parseState( const std::string& prog, TaskContext*, bool test=true );
82  void runState(const std::string& name, TaskContext*, bool trace=true, bool test=true, int runs = 1000 );
83  void checkState( const std::string& name, TaskContext*, bool test=true );
84  void finishState( std::string const& name, TaskContext*, bool test=true );
85 
86  std::string sline;
87 public:
89  :
90  d_event("d_event"), b_event("b_event"), t_event("t_event"), v_event("v_event"),o_event("o_event"),
91  v1_event("v1_event"),v2_event("v2_event"),v3_event("v3_event"),c_event("c_event"),
92  d_event_source("d_event_source"), b_event_source("b_event_source"), t_event_source("t_event_source")
93  ,sa( ScriptingService::Create(tc) ),
94  setState_op("setState", &StateTest::setState, this, RTT::OwnThread)
95  {
96  tc->stop();
97  tc->setActivity( new SimulationActivity(0.001) );
98 
99  tc->addPeer(caller);
100 
101  tc->ports()->addPort( d_event );
102  tc->ports()->addPort( b_event );
103  tc->ports()->addPort( t_event );
104 #ifdef ORO_SIGNALLING_OPERATIONS
105  tc->provides()->addEventOperation( o_event );
106  tc->provides()->addEventOperation( v_event );
107  tc->provides()->addEventOperation( v1_event );
108  tc->provides()->addEventOperation( v2_event );
109  tc->provides()->addEventOperation( v3_event );
110  caller->provides()->addEventOperation( c_event );
111 #else
112  tc->provides()->addOperation( o_event );
113  tc->provides()->addOperation( v_event );
114  tc->provides()->addOperation( v1_event );
115  tc->provides()->addOperation( v2_event );
116  tc->provides()->addOperation( v3_event );
117  caller->provides()->addOperation( c_event );
118 #endif
119 
120  tc->provides()->addOperation(setState_op).doc("Communicates state from SM").arg("state", "Name of state");
121 
122  tc->ports()->addPort( d_event_source );
123  tc->ports()->addPort( b_event_source );
124  tc->ports()->addPort( t_event_source );
125 
126  d_event_source.connectTo( &d_event );
127  b_event_source.connectTo( &b_event );
128  t_event_source.connectTo( &t_event );
129  tc->start();
130  i = 0;
131  SimulationThread::Instance()->stop();
132 
133  tc->addOperation("log", &StateTest::log, this);
134 
135  tc->provides()->addAttribute("tvar_i", var_i);
136  tc->provides()->addAttribute("tss", tss);
137  tc->provides()->addConstant("tconst_i", const_i);
138 
139  const_i = -1;
140  var_i = -1;
141  tss = SendNotReady;
142  }
144  }
145 };
146 
147 BOOST_FIXTURE_TEST_SUITE( StateTestSuite, StateTest )
148 
149 BOOST_AUTO_TEST_CASE( testParseState)
150 {
151  // a state which should never fail
152  string prog = string("StateMachine X {\n")
153  + " param int isten\n"
154  + " param bool isflse\n"
155  + " param bool isok\n"
156  + " param double isnegative\n"
157  + " var bool istrrue = true\n"
158  + " var double d_dummy = -1.0\n"
159  + " var int i_dummy = -1\n"
160  + " var bool varinit = false\n"
161  + " var bool b_dummy = true\n" // 10
162  + " initial state INIT {\n"
163  // XXX bug : preconditions are not checked in the initial state.
164 // + " preconditions {\n"
165 // + " if (istrrue == false) || (isflse == true) || (isten != 10) ||( isnegative >= 0. ) then select PRE_PARAMFAIL\n"
166 // + " if false then select PRE_ERROR\n"
167 // + " if (isnegative != -1.) then select PRE_PARAMFAIL\n"
168 // + " if (istrrue != true) then select PRE_PARAMFAIL\n"
169 // + " if (isflse != false) then select PRE_PARAMFAIL\n"
170 // + " if (isten != 10 ) then select PRE_PARAMFAIL\n"
171 // + " if (d_dummy != -1.) || (i_dummy != -1) then select PRE_VARFAIL\n"
172 // + " }\n"
173  + " entry {\n"
174  + " set varinit = (d_dummy != -1.) || (i_dummy != -1) \n"
175  + " do test.good()\n"
176  + " set d_dummy = 1.234\n"
177  + " set i_dummy = -2\n"
178  + " do test.good()\n"
179  + " }\n"
180  + " handle {\n"
181  + " do test.good()\n" // 20
182  + " }\n"
183  + " exit {\n"
184  + " do test.good()\n"
185  + " set d_dummy = 0.0\n"
186  + " set i_dummy = 0\n"
187  + " }\n"
188  + " transitions {\n"
189  + " if false then select ERROR\n"
190  + " if varinit == true then select PRE_VARFAIL\n"
191  + " if (d_dummy != 1.234) || (i_dummy != -2) then select ENTRYFAIL\n" // 30
192  + " }\n"
193  + " transition if (istrrue == false) || (isflse == true) || (isten != 10) ||( isnegative >= 0. ) then select PARAMFAIL\n"
194  + " transition if isok == false then select PARAMFAIL\n"
195  + " transition select FINI\n"
196  + " transition select ERROR\n" // do not reach
197  + " }\n"
198  + " state PRE_ERROR { entry { do test.assert(false) }\n"
199  + " }\n"
200  + " state PRE_PARAMFAIL { entry { do test.assert(false) }\n"
201  + " }\n"
202  + " state PRE_VARFAIL { entry { do test.assert(false) }\n"
203  + " }\n"
204  + " state ERROR { entry { do test.assert(false) }\n"
205  + " }\n"
206  + " state PARAMFAIL {\n"
207  + " entry { \n"
208  + " do test.assertMsg( isten == 10, \"isten parameter not correctly initialised\")\n"
209  + " do test.assertMsg( istrrue == true, \"istrrue parameter not correctly initialised\")\n"
210  + " do test.assertMsg( isok == true, \"isok parameter not correctly initialised\")\n"
211  + " do test.assertMsg( isflse == false, \"isflse parameter not correctly initialised\")\n"
212  + " do test.assertMsg( true == true, \"true ident not correctly done\")\n"
213  + " do test.assertMsg( false == false, \"false ident not correctly done\")\n"
214  + " do test.assertMsg( isnegative == -1.0, \"isnegative parameter not correctly initialised\")\n"
215  + " }\n"
216  + " }\n"
217  + " state VARFAIL { entry { do test.assert(false) }\n"
218  + " }\n"
219  + " state EXITFAIL { entry { do test.assert(false) }\n"
220  + " }\n"
221  + " state ENTRYFAIL { entry { do test.assert(false) }\n"
222  + " }\n"
223  + " final state FINI {\n"
224  + " preconditions {\n"
225  + " if (d_dummy != 0.) || (i_dummy != 0) then select EXITFAIL\n"
226  + " if false then select ERROR\n"
227  + " }\n"
228  + " entry {\n"
229  + " do test.good()\n"
230  + " set d_dummy = -1.\n"
231  + " set i_dummy = -1\n"
232  + " }\n"
233  + " handle {\n"
234  + " do test.good()\n"
235  + " }\n"
236  + " exit {\n"
237  + " do test.good()\n"
238  + " }\n"
239  + " transitions {\n"
240  + " if false then select ERROR\n"
241  + " select INIT\n"
242  + " select ERROR\n" // do not reach
243  + " }\n"
244  + " }\n"
245  + " }\n"
246  // + " RootMachine X x( isten = 10, isflse = false, isnegative = -1.0) \n" // instantiate a non hierarchical SC
247  + " RootMachine X x( isten = 10, isok = true, isflse=false, isnegative = -1.0) \n" // instantiate a non hierarchical SC
248  ;
249 
250  this->doState("x", prog, tc );
251  this->finishState( "x", tc );
252 }
253 
254 BOOST_AUTO_TEST_CASE( testStateFailure)
255 {
256  // test _command_ (through methods though) failure detection on several places.
257  // it is an incomplete test, even more that parsing should fail on the second
258  // run since the type 'X' is defined twice.
259  string prog = string("StateMachine X {\n")
260  + " initial state INIT {\n"
261  + " entry {\n"
262  + " do test.increase()\n" // set i to i+1
263  + " do test.assert( test.i != 1)\n" // fail if i == 1
264  + " }\n"
265  + " run {\n"
266  + " do test.assert( test.i != 2)\n"
267  + " }\n"
268  + " exit {\n"
269  + " do test.assert( test.i != 3)\n"
270  + " }\n"
271  + " transitions {\n"
272  + " if (true) then { do test.assert( test.i != 7); } select FINI\n"
273  + " }\n"
274  + " }\n"
275  + " state ERROR {\n"
276  + " }\n"
277  + " final state FINI {\n"
278  + " entry {\n"
279  + " do test.assert( test.i != 4)\n"
280  + " }\n"
281  + " run {\n"
282  + " do test.assert( test.i != 5)\n"
283  + " }\n"
284  + " exit {\n"
285  + " do test.assert( test.i != 6)\n"
286  + " }\n"
287  + " transitions {\n"
288  + " select ERROR\n"
289  + " }\n"
290  + " }\n"
291  + " }\n"
292  + " RootMachine X x\n" // instantiate a non hierarchical SC
293  ;
294 
295  // should fail each time
296  const int max = 7;
297  int x = 0;
298  while ( i < max && x < max) {
299  this->doState("x", prog, tc, false );
300  //cout << "i is: "<< i <<endl;
301  // assert that an error happened :
302  BOOST_CHECK_MESSAGE( sa->getStateMachineStatus("x") == StateMachine::Status::error, "Status is: " + sa->getStateMachineStatusStr("x") );
303 
304  this->finishState( "x", tc, false);
305  ++x;
306  }
307 }
308 BOOST_AUTO_TEST_CASE( testStateChildren)
309 {
310  // instantiate two children and check init of vars and params
311  string prog = string("StateMachine Y {\n")
312  + " param double isnegative\n"
313  + " var double t = 1.0\n"
314  + " initial state INIT {\n"
315  + " entry {\n"
316  + " do test.good()\n"
317  + " }\n"
318  + " transitions {\n"
319  + " if isnegative >= 0. then select PARAMFAIL\n"
320  + " select FINI\n"
321  + " }\n"
322  + " }\n"
323  + " state ERROR { entry { do test.assert(false) }\n"
324  + " }\n"
325  + " state PARAMFAIL { entry { do test.assert(false) }\n"
326  + " }\n"
327  + " state VARFAIL { entry { do test.assert(false) }\n"
328  + " }\n"
329  + " state EXITFAIL { entry { do test.assert(false) }\n"
330  + " }\n"
331  + " state ENTRYFAIL { entry { do test.assert(false) }\n"
332  + " }\n"
333  + " final state FINI {\n"
334  + " entry {\n"
335  + " do test.good()\n"
336  + " }\n"
337  + " transitions {\n"
338  + " select INIT\n"
339  + " }\n"
340  + " }\n"
341  + " }\n"
342  + string("StateMachine Z {\n")
343  + " param double neg\n"
344  + " initial state INIT {\n"
345  + " transitions {\n"
346  + " if neg >= 0. then select PARAMFAIL\n"
347  + " select FINI\n"
348  + " }\n"
349  + " }\n"
350  + " state PARAMFAIL { entry { do test.assert(false) }\n"
351  + " }\n"
352  + " final state FINI {\n"
353  + " transitions {\n"
354  + " select INIT\n"
355  + " }\n"
356  + " }\n"
357  + " }\n"
358  + string("StateMachine X {\n")
359  + " param double isnegative\n"
360  + " var double d_dummy = -2.0\n"
361  + " var int i_dummy = -1\n"
362  + " SubMachine Y y1(isnegative = d_dummy)\n"
363  + " SubMachine Y y2(isnegative = -3.0)\n"
364  + " SubMachine Y y3(isnegative = isnegative)\n"
365  + " SubMachine Z z1( neg = d_dummy)\n"
366  + " initial state INIT {\n"
367  + " entry {\n"
368  + " do test.good()\n"
369  + " do y1.activate()\n"
370  + " do y2.activate()\n"
371  + " do y3.activate()\n"
372  + " do z1.activate()\n"
373  + " }\n"
374  + " exit {\n"
375  + " do y1.start()\n"
376  + " do y2.start()\n"
377  + " do y3.start()\n"
378  + " do z1.start()\n"
379  + " }\n"
380  + " transitions {\n"
381  + " select FINI\n"
382  + " }\n"
383  + " }\n"
384  + " state ERROR { entry { do test.assert(false) }\n"
385  + " }\n"
386  + " state PARAMFAIL {\n"
387  + " entry { \n"
388  + " do test.assertMsg( y3.isnegative == isnegative, \"y3 parameter not correctly initialised\")\n"
389  + " do test.assertMsg( y2.isnegative == -3.0, \"y2 parameter not correctly initialised\")\n"
390  + " do test.assertMsg( y1.isnegative == d_dummy, \"y1 parameter not correctly initialised\")\n"
391  + " do test.assertMsg( z1.neg == d_dummy, \"z1 parameter not correctly initialised\")\n"
392  + " }\n"
393  + " }\n"
394  + " state VARFAIL { entry { do test.assert(false) }\n"
395  + " }\n"
396  + " state EXITFAIL { entry { do test.assert(false) }\n"
397  + " }\n"
398  + " state ENTRYFAIL { entry { do test.assert(false) }\n"
399  + " }\n"
400  + " final state FINI {\n"
401  + " entry {\n"
402  + " do test.good()\n"
403  + " do y1.stop()\n"
404  + " do y2.stop()\n"
405  + " do y3.stop()\n"
406  + " do z1.stop()\n"
407  + " }\n"
408  + " exit {\n"
409  + " do test.good()\n"
410  + " do y1.deactivate()\n"
411  + " do y2.deactivate()\n"
412  + " do y3.deactivate()\n"
413  + " do z1.deactivate()\n"
414  + " }\n"
415  + " transitions {\n"
416  + " if z1.neg != d_dummy then select PARAMFAIL\n"
417  + " if y1.isnegative != d_dummy then select PARAMFAIL\n"
418  + " if y2.isnegative != -3.0 then select PARAMFAIL\n"
419  + " if y3.isnegative != isnegative then select PARAMFAIL\n"
420  + " select INIT\n"
421  + " }\n"
422  + " }\n"
423  + " }\n"
424  + " RootMachine X x( isnegative = -1.0) \n" // instantiate a hierarchical SC
425  ;
426 
427  this->doState("x", prog, tc );
428  this->finishState( "x", tc);
429 }
430 
431 BOOST_AUTO_TEST_CASE( testStateEmpty)
432 {
433  // test processing of completely empty states
434  string prog = string("StateMachine X {\n")
435  + " initial state INIT {\n"
436  + " transitions {\n"
437  + " select TEST;\n" // only a transition
438  + " }\n"
439  + " }\n"
440  + " state TEST {\n" // not even used
441  + " }\n"
442  + " final state FINI {\n" // completely empty
443  + " }\n"
444  + " }\n"
445  + " RootMachine X x\n" // instantiate a non hierarchical SC
446  ;
447  this->doState("x", prog, tc );
448  this->finishState( "x", tc);
449 }
450 
451 BOOST_AUTO_TEST_CASE( testStateEmptyChild)
452 {
453  // test processing of completely empty states
454  string prog = string("StateMachine Y {\n")
455  + " initial state INIT {\n"
456  + " }\n"
457  + " final state FINI {\n"
458  + " }\n"
459  + "}\n"
460  + "StateMachine X {\n"
461  + " SubMachine Y y;\n"
462  + " initial state INIT {\n"
463  + " }\n"
464  + " final state FINI {\n"
465  + " }\n"
466  + "}\n"
467  + "RootMachine X x\n"
468  ;
469 
470  this->doState("x", prog, tc );
471  this->finishState( "x", tc);
472 }
473 
474 BOOST_AUTO_TEST_CASE( testStateComments)
475 {
476  // test parsing of comments
477  string prog = string("// Start here\n")
478  + "StateMachine X { //\n"
479  + " // comment on INIT\n"
480  + " initial state INIT /* INIT */ { // \n"
481  + " // comment in INIT\n"
482  + " entry /* entry */ { // \n"
483  + " // in entry\n"
484  + " } // end \n\n"
485  + "//\n"
486  + " }\n"
487  + " // intermediate comment \n"
488  + " final state FINI // \n"
489  + " /* ... */\n"
490  + " {\n"
491  + "//\n"
492  + " entry {\n"
493  + " // in entry\n"
494  + " /* in entry */\n"
495  + " }\n\n"
496  + "//\n"
497  + " }\n"
498  + "// final comment\n"
499  + "//\n"
500  + "}\n"
501  + "// instantiate comment\n"
502  + "//\n"
503  + "RootMachine X x // end\n"
504  ;
505  this->doState("x", prog, tc );
506  this->finishState( "x", tc);
507 }
508 
509 BOOST_AUTO_TEST_CASE( testStateOperations)
510 {
511  // test processing of operations (OwnThread + ClientThread):
512  string prog = string("StateMachine X {\n")
513  + " initial state INIT {\n"
514  + " entry {\n"
515  + " setState( rt_string(\"INIT-ENTRY\") )\n"
516  + " }\n"
517  + " transitions {\n"
518  + " select TEST;\n" // only a transition
519  + " }\n"
520  + " }\n"
521  + " state TEST {\n"
522  + " var double dret\n"
523  + " entry {\n"
524  + " setState( rt_string(\"TEST-ENTRY\") )\n"
525  + " methods.m0()\n"
526  + " methods.m1(1)\n"
527  + " methods.m2(1,2.0)\n"
528  + " methods.m3(1,2.0,true)\n"
529  + " methods.m4(1,2.0,true,\"hello\")\n"
530  + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
531  + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
532  + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
533  + " test.assert( dret == -8.0 )\n"
534  + " methods.o0()\n"
535  + " methods.o1(1)\n"
536  + " methods.o2(1,2.0)\n"
537  + " methods.o3(1,2.0,true)\n"
538  + " methods.o4(1,2.0,true,\"hello\")\n"
539  + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
540  + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
541  + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
542  + " test.assert( dret == -8.0 )\n"
543  + " }\n"
544  + " run {"
545  + " setState( rt_string(\"TEST-RUN\") )\n"
546  + " methods.m0()\n"
547  + " methods.m1(1)\n"
548  + " methods.m2(1,2.0)\n"
549  + " methods.m3(1,2.0,true)\n"
550  + " methods.m4(1,2.0,true,\"hello\")\n"
551  + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
552  + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
553  + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
554  + " test.assert( dret == -8.0 )\n"
555  + " methods.o0()\n"
556  + " methods.o1(1)\n"
557  + " methods.o2(1,2.0)\n"
558  + " methods.o3(1,2.0,true)\n"
559  + " methods.o4(1,2.0,true,\"hello\")\n"
560  + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
561  + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
562  + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
563  + " test.assert( dret == -8.0 )\n"
564  + " }\n"
565  + " exit {"
566  + " setState( rt_string(\"TEST-EXIT\") )\n"
567  + " methods.m0()\n"
568  + " methods.m1(1)\n"
569  + " methods.m2(1,2.0)\n"
570  + " methods.m3(1,2.0,true)\n"
571  + " methods.m4(1,2.0,true,\"hello\")\n"
572  + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
573  + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
574  + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
575  + " test.assert( dret == -8.0 )\n"
576  + " methods.o0()\n"
577  + " methods.o1(1)\n"
578  + " methods.o2(1,2.0)\n"
579  + " methods.o3(1,2.0,true)\n"
580  + " methods.o4(1,2.0,true,\"hello\")\n"
581  + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
582  + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
583  + " methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
584  + " }\n"
585  + " transitions {\n"
586  + " if true then \n"
587  + " {"
588  + " setState( rt_string(\"TEST-TRANSIT\") )\n"
589  + " methods.m0()\n"
590  + " methods.m1(1)\n"
591  + " methods.m2(1,2.0)\n"
592  + " methods.m3(1,2.0,true)\n"
593  + " methods.m4(1,2.0,true,\"hello\")\n"
594  + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
595  + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
596  + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
597  + " test.assert( dret == -8.0 )\n"
598  + " methods.o0()\n"
599  + " methods.o1(1)\n"
600  + " methods.o2(1,2.0)\n"
601  + " methods.o3(1,2.0,true)\n"
602  + " methods.o4(1,2.0,true,\"hello\")\n"
603  + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
604  + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
605  + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
606  + " test.assert( dret == -8.0 )\n"
607  + " } select TEST2;\n"
608  + " }\n"
609  + " }\n"
610  + " state TEST2 {\n"
611  + " entry {\n"
612  + " setState( rt_string(\"TEST-ENTRY\") )\n"
613  + " methods.m0()\n"
614  + " methods.m1(1)\n"
615  + " methods.m2(1,2.0)\n"
616  + " methods.m3(1,2.0,true)\n"
617  + " methods.m4(1,2.0,true,\"hello\")\n"
618  + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
619  + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
620  + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
621  + " test.assert( dret == -8.0 )\n"
622  + " methods.o0()\n"
623  + " methods.o1(1)\n"
624  + " methods.o2(1,2.0)\n"
625  + " methods.o3(1,2.0,true)\n"
626  + " methods.o4(1,2.0,true,\"hello\")\n"
627  + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
628  + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
629  + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
630  + " test.assert( dret == -8.0 )\n"
631  + " }\n"
632  + " run {"
633  + " setState( rt_string(\"TEST-RUN\") )\n"
634  + " methods.m0()\n"
635  + " methods.m1(1)\n"
636  + " methods.m2(1,2.0)\n"
637  + " methods.m3(1,2.0,true)\n"
638  + " methods.m4(1,2.0,true,\"hello\")\n"
639  + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
640  + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
641  + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
642  + " test.assert( dret == -8.0 )\n"
643  + " methods.o0()\n"
644  + " methods.o1(1)\n"
645  + " methods.o2(1,2.0)\n"
646  + " methods.o3(1,2.0,true)\n"
647  + " methods.o4(1,2.0,true,\"hello\")\n"
648  + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
649  + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
650  + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
651  + " test.assert( dret == -8.0 )\n"
652  + " }\n"
653  + " exit {"
654  + " setState( rt_string(\"TEST-EXIT\") )\n"
655  + " methods.m0()\n"
656  + " methods.m1(1)\n"
657  + " methods.m2(1,2.0)\n"
658  + " methods.m3(1,2.0,true)\n"
659  + " methods.m4(1,2.0,true,\"hello\")\n"
660  + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
661  + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
662  + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
663  + " test.assert( dret == -8.0 )\n"
664  + " methods.o0()\n"
665  + " methods.o1(1)\n"
666  + " methods.o2(1,2.0)\n"
667  + " methods.o3(1,2.0,true)\n"
668  + " methods.o4(1,2.0,true,\"hello\")\n"
669  + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
670  + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
671  + " methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
672  + " }\n"
673  + " transitions {\n"
674  + " if true then \n"
675  + " {"
676  + " setState( rt_string(\"TEST-TRANSIT\") )\n"
677  + " methods.m0()\n"
678  + " methods.m1(1)\n"
679  + " methods.m2(1,2.0)\n"
680  + " methods.m3(1,2.0,true)\n"
681  + " methods.m4(1,2.0,true,\"hello\")\n"
682  + " methods.m5(1,2.0,true,\"hello\",5.0)\n"
683  + " methods.m6(1,2.0,true,\"hello\",5.0,'a')\n"
684  + " dret = methods.m7(1,2.0,true,\"hello\",5.0,'a',7)\n"
685  + " test.assert( dret == -8.0 )\n"
686  + " methods.o0()\n"
687  + " methods.o1(1)\n"
688  + " methods.o2(1,2.0)\n"
689  + " methods.o3(1,2.0,true)\n"
690  + " methods.o4(1,2.0,true,\"hello\")\n"
691  + " methods.o5(1,2.0,true,\"hello\",5.0)\n"
692  + " methods.o6(1,2.0,true,\"hello\",5.0,'a')\n"
693  + " dret = methods.o7(1,2.0,true,\"hello\",5.0,'a',7)\n"
694  + " test.assert( dret == -8.0 )\n"
695  + " } select FINI;\n"
696  + " }\n"
697  + " }\n"
698  + " final state FINI {\n" // completely empty
699  + " }\n"
700  + " }\n"
701  + " RootMachine X x\n" // instantiate a non hierarchical SC
702  ;
703  parseState( prog, tc, true);
704 
705  tc->stop();
706  BOOST_REQUIRE( tc->getActivity()->stop() );
707  BOOST_REQUIRE( tc->setActivity( new Activity(0, 0.001) ) ); // deliberately test with real thread instead of simulation.
708  BOOST_REQUIRE( tc->start() );
709 
710  StateMachinePtr sm = sa->getStateMachine("x");
711  BOOST_REQUIRE( sm );
712  sm->trace(true);
713  OperationCaller<bool(StateMachinePtr)> act = tc->provides("x")->getOperation("activate");
714  OperationCaller<bool(StateMachinePtr)> autom = tc->provides("x")->getOperation("automatic");
715  BOOST_CHECK( act(sm) );
716  BOOST_CHECK( autom(sm) );
717 
718  sleep(1); // we must allow the thread to transition...
719 
720  checkState( "x", tc);
721  BOOST_CHECK( sa->getStateMachine( "x" )->inState("FINI") );
722  this->finishState( "x", tc, false); // don't test
723 }
724 
725 
726 BOOST_AUTO_TEST_CASE( testStateTransitions)
727 {
728  // test processing of transition statements.
729  string prog = string("StateMachine X {\n")
730  + " initial state INIT {\n"
731  + " var int i = 0;\n" // transition counter
732  + " var int j = 0;\n" // entry counter
733  + " var int k = 0;\n" // run counter
734  + " entry {\n"
735  + " set j = j + 1\n"
736  + " }\n"
737  + " run {\n"
738  + " set k = k + 1\n"
739  + " }\n"
740  + " transitions {\n"
741  + " if i < 5 then {\n"
742  + " set i = i + 1;\n" // execute this program
743  + " } select INIT\n" // test EXPLICIT transition to self: no entry/exit.
744  + " if i < 10 then {\n"
745  + " set i = i + 1;\n" // execute this program
746  + " }\n" // test IMPLICIT transition to self: no entry/exit.
747  + " if i < 10 then {\n"
748  + " } select TRANS_SHOULD_NOT_CHECK\n" // should never be reached.
749  + " if i == 10 then {\n"
750  + " set i = i + 1;\n" // execute this program
751  + " } select TEST_ENTRY\n"
752  + " }\n"
753  + " }\n"
754  + " state TEST_ENTRY {\n" // test if entry was executed one time
755  + " transitions {\n"
756  + " if k != i then {\n"
757  + " } select RUN_FAILED\n"
758  + " if j != 1 then {\n"
759  + " } select ENTRY_FAILED\n"
760  + " else select FINI\n"
761  + " }\n"
762  + " }\n"
763  + " state TRANS_SHOULD_NOT_CHECK {\n" // failure state
764  + " entry { do test.assert(false); }\n"
765  + " }\n"
766  + " state ENTRY_FAILED {\n" // failure state
767  + " entry { do test.assert(false); }\n"
768  + " }\n"
769  + " state RUN_FAILED {\n" // failure state
770  + " entry { do test.assert(false); }\n"
771  + " }\n"
772  + " final state FINI {\n" // Success state.
773  + " }\n"
774  + " }\n"
775  + " RootMachine X x\n" // instantiate a non hierarchical SC
776  ;
777  this->doState("x", prog, tc );
778  BOOST_CHECK( sa->getStateMachine( "x" )->inState("FINI") );
779  this->finishState( "x", tc);
780 }
781 
782 BOOST_AUTO_TEST_CASE( testStateTransitionStop )
783 {
784  // test processing of transition statements.
785  string prog = string("StateMachine X {\n")
786  + " initial state INIT {\n"
787  + " transitions {\n"
788  + " if stop() == true then select NEXT\n" // calls stop on the component !
789  + " }\n"
790  + " }\n"
791  + " state NEXT {\n" // Success state.
792  + " entry { do test.assert(true); }\n"
793  + " }\n"
794  + " final state FINI {\n" // Failure state.
795  + " entry { do test.assert(true); }\n"
796  + " }\n"
797  + " }\n"
798  + " RootMachine X x\n" // instantiate a non hierarchical SC
799  ;
800  this->doState("x", prog, tc );
801  BOOST_CHECK( sa->getStateMachine( "x" )->inState("NEXT") );
802  this->finishState( "x", tc);
803 }
804 
805 BOOST_AUTO_TEST_CASE( testStateYield )
806 {
807  // test processing of yield statements when an eventTransition occurs:
808  string prog = string("StateMachine X {\n")
809  + " initial state INIT {\n"
810  + " var double d = 0.0\n"
811  + " 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.
812  + " do yield;\n"
813  + " test.i = 10;\n"
814  + " do test.assert(false); }\n"
815  + " transition o_event(d) select NEXT;\n"
816  + " transitions {\n"
817  + " select FINI\n"
818  + " }\n"
819  + " }\n"
820  + " state NEXT {\n" // Success state.
821  + " entry { do test.assert(test.i == 5); }\n"
822  + " }\n"
823  + " final state FINI {\n" // Failure state.
824  + " entry { do test.assert(true); }\n"
825  + " }\n"
826  + " }\n"
827  + " RootMachine X x\n" // instantiate a non hierarchical SC
828  ;
829  this->doState("x", prog, tc );
830  BOOST_CHECK( sa->getStateMachine( "x" )->inState("NEXT") );
831  this->finishState( "x", tc);
832 }
833 
834 BOOST_AUTO_TEST_CASE( testStateYieldbySend )
835 {
836  // test processing of yield statements when a sent eventTransition occurs:
837  // make o_event an ownthread op :
838  this->o_event.getOperationCaller()->setThread(OwnThread, tc->engine() );
839  string prog = string("StateMachine X {\n")
840  + " initial state INIT {\n"
841  + " var double d = 0.0\n"
842  + " 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.
843  + " do yield;\n"
844  + " test.i = 10;\n"
845  + " do test.assert(false); }\n"
846  + " transition o_event(d) select NEXT;\n"
847  + " transitions {\n"
848  + " select FINI\n"
849  + " }\n"
850  + " }\n"
851  + " state NEXT {\n" // Success state.
852  + " entry { do test.assert(test.i == 5); }\n"
853  + " }\n"
854  + " final state FINI {\n" // Failure state.
855  + " entry { do test.assert(true); }\n"
856  + " }\n"
857  + " }\n"
858  + " RootMachine X x\n" // instantiate a non hierarchical SC
859  ;
860  this->doState("x", prog, tc );
861  BOOST_CHECK( sa->getStateMachine( "x" )->inState("NEXT") );
862  this->finishState( "x", tc);
863 }
864 
865 BOOST_AUTO_TEST_CASE( testStateYieldbyCmd )
866 {
867  // test yielding and checking .cmd syntax
868  string prog = string("StateMachine X {\n")
869  + " initial state INIT {\n"
870  + " var double d = 0.0\n"
871  + " run {\n"
872  + " test.assertEqual( test.i, 0 )\n"
873  + " var SendStatus ss\n"
874  + " ss = test.increaseCmd.cmd() \n"
875  + " test.assert( ss == SendSuccess )\n"
876  + " test.assertEqual( test.i, 1 )\n"
877  + " ss = test.increaseCmd.cmd()\n"
878  + " test.assert( ss == SendSuccess )\n"
879  + " test.assertEqual( test.i , 2 )\n"
880 
881  + " tss = methods.vo0.cmd() \n" // bug : does not evaluate conditions !
882  + " test.assert( tss == SendSuccess )\n"
883  + " tss = methods.vo0.cmd()\n"
884  + " test.assert( tss == SendSuccess )\n"
885  + " }\n"
886  + " transitions {\n"
887  + " select FINI\n"
888  + " }\n"
889  + " }\n"
890  + " final state FINI {\n" // Success state.
891  + " entry { do test.assert(true); }\n"
892  + " }\n"
893  + " }\n"
894  + " RootMachine X x\n" // instantiate a non hierarchical SC
895  ;
896  this->doState("x", prog, tc );
897  BOOST_CHECK( sa->getStateMachine( "x" )->inState("FINI") );
898  this->finishState( "x", tc);
899 }
900 
901 BOOST_AUTO_TEST_CASE( testStateSendFunction )
902 {
903  // test yielding and checking .send syntax
904  string func = string("export function foo(int arg) {\n")
905  + " do test.assert( tvar_i == arg ) \n"
906  + " do test.assert( tvar_i != tconst_i ) \n"
907  + " set tvar_i = tvar_i+2\n"
908  + " do test.assert( tvar_i == arg + 2 ) \n"
909  + "}\n";
910  string prog = string("StateMachine X {\n")
911  + " initial state INIT {\n"
912  + " run {\n"
913  + " tvar_i = 0\n"
914 
915  + " var SendHandle sh, sh2\n"
916  + " sh = foo.send(tvar_i) \n"
917 
918  + " sh\n" // tests accidental sh evaluation
919 
920  + " test.assert( sh.collectIfDone() == SendNotReady )\n"
921  + " test.assertEqual( tvar_i, 0 )\n"
922 
923  + " while ( sh.collectIfDone() == SendNotReady) \n"
924  + " yield\n"
925  + " test.assert( sh.collectIfDone() == SendSuccess )\n"
926  + " test.assertEqual( tvar_i, 2 )\n"
927 
928  + " sh2 = foo.send(tvar_i) \n"
929  + " test.assert( sh2.collectIfDone() == SendNotReady )\n"
930  + " test.assertEqual( tvar_i, 2 )\n"
931  + " while ( sh2.collectIfDone() == SendNotReady) \n"
932  + " yield\n"
933  + " test.assert( sh2.collectIfDone() == SendSuccess )\n"
934  + " test.assertEqual( tvar_i , 4 )\n"
935 
936  + " }\n"
937  + " transitions {\n"
938  + " select FINI\n"
939  + " }\n"
940  + " }\n"
941  + " final state FINI {\n" // Success state.
942  + " entry { do test.assert(true); }\n"
943  + " }\n"
944  + " }\n"
945  + " RootMachine X x\n" // instantiate a non hierarchical SC
946  ;
947  BOOST_REQUIRE( sa->loadPrograms(func, "func.ops", false) );
948  this->doState("x", prog, tc, true, 25 );
949  BOOST_CHECK( sa->getStateMachine( "x" )->inState("FINI") );
950  this->finishState( "x", tc);
951 }
952 
953 BOOST_AUTO_TEST_CASE( testStateCmdFunction )
954 {
955  // test yielding and checking .cmd syntax
956  string func = string("export function foo(int arg) {\n")
957  + " do test.assert( tvar_i == arg ) \n"
958  + " do test.assert( tvar_i != tconst_i ) \n"
959  + " set tvar_i = tvar_i+2\n"
960  + " do test.assert( tvar_i == arg + 2 ) \n"
961  + "}\n";
962  string prog = string("StateMachine X {\n")
963  + " initial state INIT {\n"
964  + " run {\n"
965  + " var SendStatus ss\n"
966  + " tvar_i = 0\n"
967 
968  + " ss = foo.cmd(tvar_i)\n"
969  + " test.assert( ss == SendSuccess )\n"
970  + " test.assertEqual( tvar_i, 2 )\n"
971 
972  + " ss = foo.cmd(tvar_i)\n"
973  + " test.assert( ss == SendSuccess )\n"
974  + " test.assertEqual( tvar_i , 4 )\n"
975 
976  + " tss = foo.cmd(tvar_i)\n"
977  + " test.assert( tss == SendSuccess )\n"
978  + " tss = foo.cmd(tvar_i)\n"
979  + " test.assert( tss == SendSuccess )\n"
980  + " test.assertEqual( tvar_i , 8 )\n"
981 
982  + " }\n"
983  + " transitions {\n"
984  + " select FINI\n"
985  + " }\n"
986  + " }\n"
987  + " final state FINI {\n" // Success state.
988  + " entry { do test.assert(true); }\n"
989  + " }\n"
990  + " }\n"
991  + " RootMachine X x\n" // instantiate a non hierarchical SC
992  ;
993  BOOST_REQUIRE( sa->loadPrograms(func, "func.ops", false) );
994  this->doState("x", prog, tc, true, 25 );
995  BOOST_CHECK( sa->getStateMachine( "x" )->inState("FINI") );
996  this->finishState( "x", tc);
997 }
998 
999 
1000 BOOST_AUTO_TEST_CASE( testStateGlobalTransitions)
1001 {
1002  // test processing of transition statements.
1003  string prog = string("StateMachine X {\n")
1004  + " var int gi = 0;\n" // transition counter
1005  + " transitions {\n"
1006 
1007  + " if gi < 5 then {\n"
1008  + " set gi = gi + 1;\n" // execute this program
1009  + " } select INIT\n" // test EXPLICIT transition to self: no entry/exit.
1010 
1011  + " if gi < 10 then {\n"
1012  + " if gi < 5 then do test.assert(false);\n"
1013  + " set gi = gi + 1;\n" // execute this program
1014  + " }\n" // test IMPLICIT transition to self: no entry/exit.
1015  + " if gi < 10 then {\n"
1016  + " do test.assert(false);\n"
1017  + " } select TRANS_SHOULD_NOT_CHECK\n" // should never be reached.
1018  + " if gi >= 10 then {\n"
1019  + " } select FINI\n" // we must be checked before
1020  + " }\n"
1021  + " initial state INIT {\n"
1022  + " var int i = 0;\n" // transition counter
1023  + " var int j = 0;\n" // entry counter
1024  + " var int k = 0;\n" // run counter
1025  + " entry {\n"
1026  + " set j = j + 1\n"
1027  + " }\n"
1028  + " run {\n"
1029  + " set k = k + 1\n"
1030  + " }\n"
1031  + " transitions {\n"
1032  + " if i < 5 then {\n"
1033  + " set i = i + 1;\n" // execute this program
1034  + " } select INIT\n" // test EXPLICIT transition to self: no entry/exit.
1035  + " if i < 10 then {\n"
1036  + " set i = i + 1;\n" // execute this program
1037  + " }\n" // test IMPLICIT transition to self: no entry/exit.
1038  + " if i < 10 then {\n"
1039  + " } select TRANS_SHOULD_NOT_CHECK\n" // should never be reached.
1040  + " }\n"
1041  + " }\n"
1042  + " state TRANS_SHOULD_NOT_CHECK {\n" // failure state
1043  + " entry { do test.assert(false); }\n"
1044  + " }\n"
1045  + " state ENTRY_FAILED {\n" // failure state
1046  + " entry { do test.assert(false); }\n"
1047  + " }\n"
1048  + " state RUN_FAILED {\n" // failure state
1049  + " entry { do test.assert(false); }\n"
1050  + " }\n"
1051  + " final state FINI {\n" // Success state.
1052  + " }\n"
1053  + " }\n"
1054  + " RootMachine X x\n" // instantiate a non hierarchical SC
1055  ;
1056  this->doState("x", prog, tc );
1057  BOOST_CHECK( sa->getStateMachine( "x" )->inState("FINI") );
1058  this->finishState( "x", tc);
1059 }
1060 
1061 
1062 BOOST_AUTO_TEST_CASE( testStateSubStateVars)
1063 {
1064  // test get/set access of substate variables and parameters
1065  string prog = string("StateMachine Y {\n")
1066  + " param double isnegative\n"
1067  + " var double t = 1.0\n"
1068  + " initial state INIT {\n"
1069  + " transitions {\n"
1070  + " if isnegative >= 0. then select PARAMFAIL\n"
1071  + " if t >= 0. then select VARFAIL\n"
1072  + " select FINI\n"
1073  + " }\n"
1074  + " exit { set isnegative = +1.0 }\n"
1075  + " }\n" // 11
1076  + " state ERROR { entry { do test.assert(false) }\n"
1077  + " }\n"
1078  + " state PARAMFAIL { entry { do test.assert(false) }\n"
1079  + " }\n"
1080  + " state VARFAIL { entry { do test.assert(false) }\n"
1081  + " }\n"
1082  + " state EXITFAIL { entry { do test.assert(false) }\n"
1083  + " }\n"
1084  + " state ENTRYFAIL { entry { do test.assert(false) }\n"
1085  + " }\n" // 21
1086  + " final state FINI {\n"
1087  + " transitions {\n"
1088  + " if isnegative <= 0. then select PARAMFAIL\n"
1089  + " }\n"
1090  + " }\n"
1091  + " }\n"
1092  + string("StateMachine X {\n")
1093  + " param double isnegative\n"
1094  + " var double d_dummy = -2.0\n"
1095  + " var int i_dummy = -1\n" //31
1096  + " SubMachine Y y1(isnegative = d_dummy)\n"
1097  + " initial state INIT {\n"
1098  + " entry {\n"
1099  + " do y1.trace(true)\n"
1100  + " do y1.activate()\n"
1101  + " set y1.t = -1.0 \n"
1102  + " }\n"
1103  + " exit {\n"
1104  + " do test.assert( y1.start() )\n"
1105  + " }\n"
1106  + " transitions {\n"
1107  + " select TEST\n"
1108  + " }\n"
1109  + " }\n"
1110  + " state TEST {\n"
1111  + " entry {\n"
1112  + " do yield\n"
1113  + " do test.assert( y1.inState(\"FINI\") )\n" // if y1 not in FINI, stop here.
1114  + " }\n"
1115  + " transitions {\n"
1116  + " select FINI\n"
1117  + " }\n"
1118  + " }\n"
1119  + " final state FINI {\n"
1120  + " entry {\n"
1121  + " do y1.stop()\n" // prepare y1 to start-over
1122  + " }\n"
1123  + " exit {\n"
1124  + " set y1.isnegative = -1.0 \n"
1125  + " do y1.deactivate()\n"
1126  + " }\n"
1127  + " transitions {\n"
1128  + " select INIT\n" // start-over y1.
1129  + " }\n"
1130  + " }\n"
1131  + " }\n"
1132  + " RootMachine X x( isnegative = -1.0) \n" // instantiate a hierarchical SC
1133  ;
1134 
1135  this->doState("x", prog, tc );
1136  this->finishState( "x", tc);
1137 }
1138 
1139 BOOST_AUTO_TEST_CASE( testStateSubStateCommands)
1140 {
1141  // test get/set access of substate variables and parameters
1142  string prog = string("StateMachine Y {\n")
1143  + " param double isnegative\n"
1144  + " var double t = 1.0\n"
1145  + " initial state INIT {\n"
1146  + " transitions {\n"
1147  + " if isnegative < 0. then select ISNEGATIVE\n"
1148  + " if t >= 0. then select ISPOSITIVE\n"
1149  + " select DEFAULT\n"
1150  + " }\n"
1151  + " }\n"
1152  + " state ISNEGATIVE {\n"
1153  + " transitions {\n"
1154  + " select INIT\n"
1155  + " }\n"
1156  + " }\n"
1157  + " state ISPOSITIVE {\n"
1158  + " transitions {\n"
1159  + " select INIT\n"
1160  + " }\n"
1161  // 20 :
1162  + " }\n"
1163  + " state DEFAULT {\n"
1164  + " transitions {\n"
1165  + " select FINI\n"
1166  + " }\n"
1167  + " }\n"
1168  + " final state FINI {\n"
1169  + " }\n"
1170  + " }\n"
1171  + string("StateMachine X {\n") // 1
1172  + " SubMachine Y y1(isnegative = -1.0)\n"
1173  + " initial state INIT {\n"
1174  + " entry {\n"
1175  + " set y1.t = -1.0 \n"
1176  + " do y1.activate()\n"
1177  + " do y1.requestState(\"ISNEGATIVE\")\n"
1178  + " do test.assert( y1.inState(\"ISNEGATIVE\") )\n"
1179  + " do y1.requestState(\"INIT\")\n"
1180  + " do test.assert( y1.inState(\"INIT\") )\n"
1181  + " set y1.isnegative = +1.0 \n"
1182  + " try y1.requestState(\"ISNEGATIVE\") \n "
1183  + " catch \n{\n"
1184  + " do test.assert( y1.inState(\"INIT\") )\n" // do not leave INIT
1185  + " }\n"
1186  + " do test.assert( y1.inState(\"INIT\") )\n" // do not leave INIT
1187  + " do y1.requestState(\"FINI\")\n" // request final state
1188  + " do test.assert( y1.inState(\"FINI\") )\n"
1189  + " }\n"
1190  + " exit {\n"
1191  + " do y1.requestState(\"INIT\")\n" // request initial state
1192  + " do test.assert( y1.inState(\"INIT\") )\n"
1193  + " set y1.isnegative = +1.0 \n"
1194  + " set y1.t = -1.0 \n"
1195  + " do y1.start()\n" // must reach FINI after a while.
1196  + " while ! y1.inState(\"FINI\") \n"
1197  + " do nothing\n"
1198  + " }\n"
1199  + " transitions {\n"
1200  + " select FINI\n"
1201  + " }\n"
1202  + " }\n"
1203  + " final state FINI {\n"
1204  + " entry {\n"
1205  + " do y1.stop()\n"
1206  + " }\n"
1207  + " exit {\n"
1208  + " do y1.deactivate()\n"
1209  + " }\n"
1210  + " transitions {\n"
1211  + " select INIT\n"
1212  + " }\n"
1213  + " }\n"
1214  + " }\n"
1215  + " RootMachine X x() \n" // instantiate a hierarchical SC
1216  ;
1217 
1218  this->doState("x", prog, tc );
1219  this->finishState( "x", tc);
1220 }
1221 
1222 #ifdef ORO_SIGNALLING_OPERATIONS
1223 BOOST_AUTO_TEST_CASE( testStateOperationSignalTransition )
1224 {
1225  // test event reception from own component
1226  string prog = string("StateMachine X {\n")
1227  + " var double et = 0.0\n"
1228  + " initial state INIT {\n"
1229  + " transition o_event(et) { test.assert(et == 3.33); } select FINI\n" // test signal transition
1230  + " }\n"
1231  + " final state FINI { entry { test.assert( et == 3.33);} } \n"
1232  + "}\n"
1233  + "RootMachine X x()\n";
1234  this->parseState( prog, tc );
1235  StateMachinePtr sm = sa->getStateMachine("x");
1236  BOOST_REQUIRE( sm );
1237  this->runState("x", tc);
1238  checkState( "x", tc);
1239  OperationCaller<void(double)> mo( tc->provides()->getOperation("o_event") );
1240  mo(3.33);
1241  checkState( "x", tc);
1242  BOOST_CHECK( SimulationThread::Instance()->run(2) );
1243  checkState( "x", tc);
1244  BOOST_CHECK( sm->inState("FINI") );
1245  this->checkState("x",tc);
1246  this->finishState("x", tc);
1247 }
1248 
1249 BOOST_AUTO_TEST_CASE( testStateOperationCallerSignalTransition )
1250 {
1251  // test event reception from another component
1252  string prog = string("StateMachine X {\n")
1253  + " var double et = 0.0\n"
1254  + " initial state INIT {\n"
1255  + " transition caller.c_event(et) select FINI\n" // test signal transition
1256  + " }\n"
1257  + " final state FINI {} \n"
1258  + "}\n"
1259  + "RootMachine X x()\n";
1260  this->parseState( prog, tc );
1261  StateMachinePtr sm = sa->getStateMachine("x");
1262  BOOST_REQUIRE( sm );
1263  this->runState("x", tc);
1264  checkState( "x", tc);
1265  BOOST_CHECK( SimulationThread::Instance()->run(2) );
1266  checkState( "x", tc);
1267  OperationCaller<void(double)> mc( caller->provides()->getOperation("c_event") );
1268  mc(6.66);
1269  checkState( "x", tc);
1270  BOOST_CHECK( SimulationThread::Instance()->run(2) );
1271  checkState( "x", tc);
1272  BOOST_CHECK( sm->inState("FINI") );
1273  this->checkState("x",tc);
1274  this->finishState("x", tc);
1275 }
1276 
1277 BOOST_AUTO_TEST_CASE( testStateOperationSignalMultiTransition )
1278 {
1279  // test multi-event reception from own component
1280  string prog = string("StateMachine X {\n")
1281  + " initial state INIT {\n"
1282  + " transitions { select STATE1 }\n"
1283  + " }\n"
1284  + " state STATE1 {\n"
1285  + " transition v_event() select STATE2\n" // test signal transition
1286  + " }\n"
1287  + " state STATE2 {\n"
1288  + " transition v_event() select FINI\n" // test signal transition
1289  + " }\n"
1290  + " final state FINI {} \n"
1291  + "}\n"
1292  + "RootMachine X x()\n";
1293  this->parseState( prog, tc );
1294  StateMachinePtr sm = sa->getStateMachine("x");
1295  BOOST_REQUIRE( sm );
1296  sm->trace(true);
1297  // into STATE1
1298  this->runState("x", tc);
1299  checkState( "x", tc);
1300  BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
1301  // remain in STATE1
1302  BOOST_CHECK( SimulationThread::Instance()->run(100) );
1303  checkState( "x", tc);
1304  BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
1305  // into STATE2
1306  OperationCaller<void(void)> mo( tc->provides()->getOperation("v_event"), tc->engine());
1307  BOOST_REQUIRE( mo.ready() );
1308  mo();
1309  BOOST_CHECK( SimulationThread::Instance()->run(1) ); // allow to transition
1310  checkState( "x", tc);
1311  BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
1312  // remain in STATE2
1313  BOOST_CHECK( SimulationThread::Instance()->run(100) );
1314  checkState( "x", tc);
1315  BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
1316  // into FINI
1317  mo();
1318  BOOST_CHECK( SimulationThread::Instance()->run(1) ); // allow to transition
1319  checkState( "x", tc);
1320  BOOST_CHECK_EQUAL( "FINI", sm->getCurrentStateName() );
1321  BOOST_CHECK( SimulationThread::Instance()->run(100) );
1322  checkState( "x", tc);
1323  BOOST_CHECK_EQUAL( "FINI", sm->getCurrentStateName() );
1324  this->checkState("x",tc);
1325  this->finishState("x", tc);
1326 }
1327 
1328 BOOST_AUTO_TEST_CASE( testStateOperationSignalTransitionPriority )
1329 {
1330  // test event reception transition priority
1331  string prog = string("StateMachine X {\n")
1332  + " initial state INIT {\n"
1333  + " transitions { select STATE1 }\n"
1334  + " }\n"
1335  + " state STATE1 {\n"
1336  + " var double d;\n"
1337  + " transition v_event() select STATE2\n" // test signal transition
1338  + " transition v_event() select ERROR\n" // This one should not be taken.
1339  + " transition o_event(d) select ERROR\n" // This one should not be taken.
1340  + " transition v_event() select ERROR\n" // This one should not be taken.
1341  + " }\n"
1342  + " state STATE2 {\n"
1343  + " transition v_event() select FINI\n" // test signal transition
1344  + " transition v_event() select ERROR\n" // This one should not be taken.
1345  + " transition o_event(d) select ERROR\n" // This one should not be taken.
1346  + " transition v_event() select ERROR\n" // This one should not be taken.
1347  + " }\n"
1348  + " state ERROR {} \n"
1349  + " final state FINI {} \n"
1350  + "}\n"
1351  + "RootMachine X x()\n";
1352  this->parseState( prog, tc );
1353  StateMachinePtr sm = sa->getStateMachine("x");
1354  BOOST_REQUIRE( sm );
1355  sm->trace(true);
1356  // into STATE1
1357  this->runState("x", tc);
1358  checkState( "x", tc);
1359  BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
1360  // remain in STATE1
1361  BOOST_CHECK( SimulationThread::Instance()->run(100) );
1362  checkState( "x", tc);
1363  BOOST_CHECK_EQUAL( "STATE1", sm->getCurrentStateName() );
1364  // into STATE2
1365  OperationCaller<void(void)> mo( tc->provides()->getOperation("v_event"), tc->engine());
1366  OperationCaller<void(double)> mo2( tc->provides()->getOperation("o_event"), tc->engine());
1367  BOOST_REQUIRE( mo.ready() );
1368  mo();
1369  mo();
1370  mo2(3);
1371  mo2(3);
1372  BOOST_CHECK( SimulationThread::Instance()->run(1) ); // allow to transition
1373  checkState( "x", tc);
1374  BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
1375  // remain in STATE2
1376  BOOST_CHECK( SimulationThread::Instance()->run(100) );
1377  checkState( "x", tc);
1378  BOOST_CHECK_EQUAL( "STATE2", sm->getCurrentStateName() );
1379  // into FINI
1380  mo();
1381  mo();
1382  mo2(3);
1383  mo2(3);
1384  BOOST_CHECK( SimulationThread::Instance()->run(1) ); // allow to transition
1385  checkState( "x", tc);
1386  BOOST_CHECK_EQUAL( "FINI", sm->getCurrentStateName() );
1387  BOOST_CHECK( SimulationThread::Instance()->run(100) );
1388  checkState( "x", tc);
1389  BOOST_CHECK_EQUAL( "FINI", sm->getCurrentStateName() );
1390  this->checkState("x",tc);
1391  this->finishState("x", tc);
1392 }
1393 
1394 BOOST_AUTO_TEST_CASE( testStateOperationSignalTransitionAround )
1395 {
1396  // test event reception hopping from one state to another
1397  string prog = string("StateMachine X {\n")
1398  + " initial state INIT {\n"
1399  + " transitions { select IDLE }\n"
1400  + " }\n"
1401  + " state IDLE {\n"
1402  + " transition v1_event() select STATE1\n"
1403  + " transition v2_event() select STATE2\n"
1404  + " transition v3_event() select STATE3\n"
1405  + " }\n"
1406  + " state STATE1 {\n"
1407  + " transition v_event() select IDLE\n"
1408  + " transition v2_event() select STATE2\n"
1409  + " transition v3_event() select STATE3\n"
1410  + " }\n"
1411  + " state STATE2 {\n"
1412  + " transition v_event() select IDLE\n"
1413  + " transition v1_event() select STATE1\n"
1414  + " transition v3_event() select STATE3\n"
1415  + " }\n"
1416  + " state STATE3 {\n"
1417  + " transition v_event() select IDLE\n"
1418  + " transition v1_event() select STATE1\n"
1419  + " transition v2_event() select STATE2\n"
1420  + " }\n"
1421  + " final state FINI {} \n"
1422  + "}\n"
1423  + "RootMachine X x()\n";
1424  this->parseState( prog, tc );
1425  StateMachinePtr sm = sa->getStateMachine("x");
1426  BOOST_REQUIRE( sm );
1427  this->runState("x", tc);
1428  // into IDLE
1429  checkState( "x", tc);
1430  BOOST_CHECK_EQUAL( "IDLE", sm->getCurrentStateName() );
1431  BOOST_CHECK( SimulationThread::Instance()->run(100) );
1432  checkState( "x", tc);
1433  BOOST_CHECK_EQUAL( "IDLE", sm->getCurrentStateName() );
1434 
1435  OperationCaller<void(void)> v( tc->provides()->getOperation("v_event"), tc->engine());
1436  BOOST_REQUIRE( v.ready() );
1437  OperationCaller<void(void)> v1( tc->provides()->getOperation("v1_event"), tc->engine());
1438  BOOST_REQUIRE( v1.ready() );
1439  OperationCaller<void(void)> v2( tc->provides()->getOperation("v2_event"), tc->engine());
1440  BOOST_REQUIRE( v2.ready() );
1441  OperationCaller<void(void)> v3( tc->provides()->getOperation("v3_event"), tc->engine());
1442  BOOST_REQUIRE( v3.ready() );
1443 
1444 #define DO_EVENT(event, name) \
1445  event(); \
1446  BOOST_CHECK( SimulationThread::Instance()->run(1) ); \
1447  checkState( "x", tc); \
1448  BOOST_CHECK_EQUAL( name, sm->getCurrentStateName() ); \
1449  BOOST_CHECK( SimulationThread::Instance()->run(100) ); \
1450  checkState( "x", tc); \
1451  BOOST_CHECK_EQUAL( name, sm->getCurrentStateName() )
1452 
1453  DO_EVENT(v2, "STATE2");
1454  DO_EVENT(v1, "STATE1");
1455  DO_EVENT(v1, "STATE1"); // no change
1456  DO_EVENT(v3, "STATE3");
1457  DO_EVENT(v, "IDLE");
1458  DO_EVENT(v3, "STATE3");
1459  DO_EVENT(v, "IDLE");
1460  DO_EVENT(v1, "STATE1");
1461 
1462 #undef DO_EVENT
1463 
1464  this->checkState("x",tc);
1465  this->finishState("x", tc);
1466 }
1467 
1468 BOOST_AUTO_TEST_CASE( testStateOperationSignalTransitionProgram )
1469 {
1470  string prog = string("StateMachine X {\n")
1471  + " var double et = 0.0\n"
1472  + " initial state INIT {\n"
1473  + " transition o_event(et) { test.i = 5; } select FINI\n" // test program
1474  + " }\n"
1475  + " final state FINI {} \n"
1476  + "}\n"
1477  + "RootMachine X x()\n";
1478  this->parseState( prog, tc );
1479  StateMachinePtr sm = sa->getStateMachine("x");
1480  BOOST_REQUIRE( sm );
1481  //checkState( prog, tc);
1482  this->runState("x", tc);
1483  checkState( "x", tc);
1484  // transition to FINI:
1485  OperationCaller<void(double)> mo( tc->provides()->getOperation("o_event"), tc->engine());
1486  mo(3.33);
1487  mo(6.33); // should be ignored
1488  checkState( "x", tc);
1489  BOOST_CHECK( SimulationThread::Instance()->run(10) );
1490  BOOST_CHECK_EQUAL( i, 5 );
1491  checkState( "x", tc);
1492  BOOST_CHECK( sm->inState("FINI") );
1493  this->checkState("x",tc);
1494  this->finishState("x", tc);
1495 }
1496 
1497 BOOST_AUTO_TEST_CASE( testStateOperationSignalGuard )
1498 {
1499  string prog = string("StateMachine X {\n")
1500  + " var double et = 0.0\n"
1501  + " initial state INIT {\n"
1502  + " transition o_event(et) if (et == 3.33) then \n"
1503  + " select FINI\n" // test guard
1504  + " else {log(\"received et != 3.33: \"+et+\": will fail.\") } select FAIL\n" // test guard
1505  + " }\n"
1506  + " final state FINI {} \n"
1507  + " state FAIL {} \n"
1508  + "}\n"
1509  + "RootMachine X x()\n";
1510  this->parseState( prog, tc );
1511  StateMachinePtr sm = sa->getStateMachine("x");
1512  BOOST_REQUIRE( sm );
1513  //checkState( prog, tc);
1514  this->runState("x", tc);
1515  checkState( "x", tc);
1516  // transition to FINI:
1517  OperationCaller<void(double)> mo( tc->provides()->getOperation("o_event"), GlobalEngine::Instance() );
1518  mo(3.33);
1519  mo(6.33); // should be ignored
1520  checkState( "x", tc);
1521  BOOST_CHECK( SimulationThread::Instance()->run(10) );
1522  checkState( "x", tc);
1523  BOOST_CHECK( sm->inState("FINI") );
1524  this->checkState("x",tc);
1525  this->finishState("x", tc);
1526 }
1527 
1528 BOOST_AUTO_TEST_CASE( testStateOperationCallerSignalGuard )
1529 {
1530  string prog = string("StateMachine X {\n")
1531  + " var double et = 0.0\n"
1532  + " initial state INIT {\n"
1533  + " transition caller.c_event(et) if (et == 3.33) then\n"
1534  + " select FINI\n"
1535  + " else select FAIL\n" // test guard
1536  + " }\n"
1537  + " final state FINI {} \n"
1538  + " state FAIL {} \n"
1539  + "}\n"
1540  + "RootMachine X x()\n";
1541  this->parseState( prog, tc );
1542  StateMachinePtr sm = sa->getStateMachine("x");
1543  BOOST_REQUIRE( sm );
1544  //checkState( prog, tc);
1545  this->runState("x", tc);
1546  checkState( "x", tc);
1547  // causes error state when received in INIT:
1548  OperationCaller<void(double)> mo( caller->provides()->getOperation("c_event") );
1549  mo(3.33);
1550  checkState( "x", tc);
1551  BOOST_CHECK( SimulationThread::Instance()->run(1000) );
1552  checkState( "x", tc);
1553  BOOST_CHECK( sm->inState("FINI") );
1554  this->checkState("x",tc);
1555  this->finishState("x", tc);
1556 }
1557 #endif
1558 
1559 BOOST_AUTO_TEST_CASE( testStateEvents)
1560 {
1561  // test event reception in sub states.
1562  string prog = string("StateMachine Y {\n")
1563  + " var int t = 0\n"
1564  + " var double et_global = 0.0, et_local = 0.0\n"
1565  + " var bool eb = false\n"
1566  + " var bool eflag = false\n"
1567  + " transition t_event(t) { do log(\"Global Transition to TESTSELF\");} select TESTSELF\n" // test self transition
1568  + " transition d_event(et_global)\n"
1569  + " if et_global < 0. then { do log(\"Global ISNEGATIVE Transition\");} select ISNEGATIVE\n"
1570  + " else { do log(\"Global ISPOSITIVE Transition\");} select ISPOSITIVE\n" // NewData == false !!!
1571  + " initial state INIT {\n"
1572  + " entry { do log(\"INIT\"); set eb = false; }\n"
1573  + " }\n"
1574  + " state ISNEGATIVE {\n"
1575  + " entry { do log(\"ISNEGATIVE\");}\n"
1576  + " transition b_event(eb)\n"
1577  + " if (eb) then { do log(\"Local ISNEGATIVE->INIT Transition\");} select INIT\n"
1578  + " }\n"
1579  + " state ISPOSITIVE {\n"
1580  + " entry { do log(\"ISPOSITIVE\");}\n"
1581  + " transition b_event(eb)\n" // 20
1582  + " if (eb == true) then { do log(\"Local ISPOSITIVE->INIT Transition for b_event\");} select INIT\n"
1583 #ifdef ORO_SIGNALLING_OPERATIONS
1584  + " transition o_event(et_local)\n"
1585  + " if ( et_local == 3.0 ) then { do log(\"Local ISPOSITIVE->INIT Transition for o_event == \" + et_local);} select INIT\n"
1586  + " else { do log(\"Invalid et_local: \"+et_local); } \n"
1587 #endif
1588  + " }\n"
1589  + " state TESTSELF {\n"
1590  + " entry {\n"
1591  + " do log(\"TESTSELF\");\n"
1592  + " set eflag = !eflag\n"
1593  + " }\n"
1594  + " transition t_event(t) { do log(\"Self Transition in TESTSELF\");} select TESTSELF\n" // does not execute entry {}, overrides global t_event()
1595  + " transition b_event(eb)\n"
1596  + " if (eb == true) then { do log(\"Local TESTSELF->INIT Transition\");} select INIT\n"
1597  + " else { log(\"Failed to select INIT upon event.\");}\n"
1598  + " }\n"
1599  + " final state FINI {\n"
1600  + " entry { do log(\"FINI\");}\n"
1601  + " }\n"
1602  + " }\n" // 40
1603  + string("StateMachine X {\n") // 1
1604  + " SubMachine Y y1()\n"
1605  + " initial state XINIT {\n"
1606  + " entry {\n"
1607  + " do y1.trace(true)\n"
1608  + " do y1.activate()\n"
1609  + " do y1.start()\n"
1610  + " do yield\n"
1611  + " }\n"
1612  + " run {\n"
1613 
1614  + " do d_event_source.write(-1.0)\n" // 11
1615  + " do nothing\n"
1616  + " do test.assert( !y1.inState(\"INIT\") )\n"
1617  + " do test.assert( !y1.inState(\"ISPOSITIVE\") )\n"
1618  + " do test.assert( y1.inState(\"ISNEGATIVE\") )\n"
1619  + " do b_event_source.write( true )\n" // go to INIT.
1620  + " do yield\n"
1621  + " do test.assert( y1.inState(\"INIT\") )\n"
1622  + " do d_event_source.write(+1.0)\n" // 21
1623 
1624  + " do nothing\n"
1625  + " do test.assert( !y1.inState(\"INIT\") )\n"
1626  + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
1627  + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
1628  + " if ( !y1.inState(\"ISPOSITIVE\") ) then\n"
1629  + " do test.assertMsg( false, \"Not ISNEGATIVE but \" + y1.getState() )\n"
1630  + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
1631  + " do b_event_source.write( true )\n" // go to INIT.
1632  + " do yield\n"
1633  + " do test.assert( y1.inState(\"INIT\") )\n" // 31
1634 #ifdef ORO_SIGNALLING_OPERATIONS
1635  // test operation
1636  + " do d_event_source.write(+1.0)\n"
1637 
1638  + " do nothing\n"
1639  + " do test.assert( !y1.inState(\"INIT\") )\n"
1640  + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
1641  + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
1642  + " if ( !y1.inState(\"ISPOSITIVE\") ) then\n"
1643  + " do test.assertMsg( false, \"Not ISPOSITIVE but \" + y1.getState() )\n"
1644  + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
1645  + " do o_event( 3.0 )\n" // go to INIT.
1646  + " do yield\n"
1647  + " do yield\n"
1648  + " do yield\n"
1649  + " do test.assert( y1.inState(\"INIT\") )\n"
1650 #endif
1651  // test self transitions
1652  + " set y1.eflag = true;\n"
1653  + " do t_event_source.write(1)\n"
1654  + " do nothing\n"
1655  + " do test.assert( !y1.inState(\"INIT\") )\n"
1656  + " do test.assert( !y1.inState(\"ISPOSITIVE\") )\n"
1657  + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
1658  + " do test.assert( y1.inState(\"TESTSELF\") )\n"
1659  + " do test.assert( y1.eflag == false ) /* first */\n"
1660  + " do t_event_source.write(1)\n"
1661  + " do nothing\n"
1662  + " do test.assert( y1.inState(\"TESTSELF\") )\n"
1663  + " do test.assert( y1.eflag == false ) /* second */\n" // no entry
1664  + " do log(\"Trigger b_event.\");\n"
1665  + " do b_event_source.write(true);\n"
1666  + " yield;\n"
1667  + " do test.assert( y1.inState(\"INIT\") ) /* last */\n"
1668  + " }\n"
1669  + " transitions {\n"
1670  + " select XFINI\n"
1671  + " }\n"
1672  + " }\n"
1673  + " final state XFINI {\n"
1674  + " entry {\n"
1675  + " do y1.deactivate()\n"
1676  //+ " do test.assert(false)\n"
1677  + " }\n"
1678  + " transitions {\n"
1679  + " select XINIT\n"
1680  + " }\n"
1681  + " }\n"
1682  + " }\n"
1683  + " RootMachine X x() \n" // instantiate a hierarchical SC
1684  ;
1685 
1686  this->doState("x", prog, tc );
1687  //BOOST_CHECK( tc->engine()->states()->getStateMachine( "x" )->inState("FINI") );
1688  this->finishState( "x", tc);
1689 }
1690 
1691 
1692 BOOST_AUTO_TEST_CASE( testStateLevelEvents)
1693 {
1694  // test event reception in sub states.
1695  string prog = string("StateMachine Y {\n")
1696  + " var int t = 0\n"
1697  + " var double et_global = 0.0, et_local = 0.0\n"
1698  + " var bool eb = false\n"
1699  + " var bool eflag = false\n"
1700  + " transition if ( t_event.read(t) == NewData && t == 1 ) then { do log(\"Global Transition to TESTSELF\");} select TESTSELF\n" // test self transition
1701  + " transition d_event(et_global) if ( et_global < 0.) then \n"
1702  + " { do log(\"Global ISNEGATIVE Transition\");} select ISNEGATIVE\n"
1703  + " else { do log(\"Global ISPOSITIVE Transition\");} select ISPOSITIVE\n"
1704  + " initial state INIT {\n"
1705  + " entry { do log(\"INIT\"); set eb = false; }\n"
1706  + " }\n"
1707  + " state ISNEGATIVE {\n"
1708  + " entry { do log(\"ISNEGATIVE\");}\n"
1709  + " transition if ( b_event.read(eb) != NoData && eb )\n" // once eb is true (or was true already), transition
1710  + " then { do log(\"Local ISNEGATIVE->INIT Transition\");} select INIT\n"
1711  + " }\n"
1712  + " state ISPOSITIVE {\n"
1713  + " entry { do log(\"ISPOSITIVE\");}\n"
1714  + " transition if ( b_event.read(eb) != NoData && eb == true) \n" // 20
1715  + " then { do log(\"Local ISPOSITIVE->INIT Transition for b_event\");} select INIT\n"
1716 #ifdef ORO_SIGNALLING_OPERATIONS
1717  + " transition o_event(et_local) if ( et_local == 3.0)\n"
1718  + " then { do log(\"Local ISPOSITIVE->INIT Transition for o_event == \" + et_local);} select INIT\n"
1719  + " else { do log(\"Local ISPOSITIVE->INIT Transition FAILED for o_event == \" + et_local);}\n"
1720 #endif
1721  + " }\n"
1722  + " state TESTSELF {\n"
1723  + " entry {\n"
1724  + " do log(\"TESTSELF\");\n"
1725  + " set eflag = !eflag\n"
1726  + " }\n"
1727  + " transition if ( t_event.read(t) == NewData ) { do log(\"Self Transition in TESTSELF\");} select TESTSELF\n" // does not execute entry {}, overrides global t_event()
1728  + " transition if ( b_event.read(eb) == NewData && eb == true )\n"
1729  + " then { do log(\"Local TESTSELF->INIT Transition\");} select INIT\n"
1730  + " else { log(\"Failed to select INIT upon event.\");}\n"
1731  + " }\n"
1732  + " final state FINI {\n"
1733  + " entry { do log(\"FINI\");}\n"
1734  + " }\n"
1735  + " }\n" // 40
1736  + string("StateMachine X {\n") // 1
1737  + " SubMachine Y y1()\n"
1738  + " initial state INIT {\n"
1739  + " entry {\n"
1740  + " do y1.trace(true)\n"
1741  + " do y1.activate()\n"
1742  + " do y1.start()\n"
1743  + " do yield\n"
1744  + " }"
1745  + " run {\n"
1746 
1747  + " do d_event_source.write(-1.0)\n" // 11
1748  + " do nothing\n"
1749  + " do test.assert( !y1.inState(\"INIT\") )\n"
1750  + " do test.assert( !y1.inState(\"ISPOSITIVE\") )\n"
1751  + " do test.assert( y1.inState(\"ISNEGATIVE\") )\n"
1752  + " do b_event_source.write( true )\n" // go to INIT.
1753  + " do yield\n"
1754  + " do test.assert( y1.inState(\"INIT\") )\n"
1755  + " do b_event_source.write( false )\n" // clear the b_event for level sake
1756 
1757  + " do d_event_source.write(+1.0)\n"
1758  + " do nothing\n"
1759  + " do test.assert( !y1.inState(\"INIT\") )\n"//21
1760  + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
1761  + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
1762  + " if ( !y1.inState(\"ISPOSITIVE\") ) then\n"
1763  + " do test.assertMsg( false, \"Not ISNEGATIVE but \" + y1.getState() )\n"
1764  + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
1765  + " do b_event_source.write( true )\n" // go to INIT.
1766  + " do yield\n"
1767 
1768  + " do test.assert( y1.inState(\"INIT\") )\n"
1769  + " do b_event_source.write( false )\n" // clear the b_event for level sake
1770 #ifdef ORO_SIGNALLING_OPERATIONS
1771  // test operation
1772  + " do d_event_source.write(+1.0)\n"
1773  + " do nothing\n" // 31
1774  + " do test.assert( !y1.inState(\"INIT\") )\n"
1775  + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
1776  + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
1777  + " if ( !y1.inState(\"ISPOSITIVE\") ) then\n"
1778  + " do test.assertMsg( false, \"Not ISPOSITIVE but \" + y1.getState() )\n"
1779  + " do test.assert( y1.inState(\"ISPOSITIVE\") )\n"
1780  + " do o_event( 3.0 )\n" // go to INIT.
1781  + " do yield\n"
1782  + " do yield\n" // 40
1783  + " do yield\n"
1784  + " do test.assert( y1.inState(\"INIT\") )\n"
1785 #endif
1786  // test self transitions
1787  + " set y1.eflag = true;\n"
1788  + " do t_event_source.write(1)\n"
1789  + " do nothing\n"
1790  + " do test.assert( !y1.inState(\"INIT\") )\n"
1791  + " do test.assert( !y1.inState(\"ISPOSITIVE\") )\n"
1792  + " do test.assert( !y1.inState(\"ISNEGATIVE\") )\n"
1793  + " do test.assert( y1.inState(\"TESTSELF\") )\n"
1794  + " do test.assert( y1.eflag == false ) /* first */\n"
1795  + " do t_event_source.write(1)\n"
1796  + " do nothing\n"
1797  + " do test.assert( y1.inState(\"TESTSELF\") )\n"
1798  + " do test.assert( y1.eflag == false ) /* second */\n" // no entry
1799  + " do log(\"Trigger b_event.\");\n"
1800  + " do b_event_source.write(true);\n"
1801  + " yield;\n"
1802  + " do test.assert( y1.inState(\"INIT\") ) /* last */\n"
1803  + " }\n"
1804  + " transitions {\n"
1805  + " select FINI\n"
1806  + " }\n"
1807  + " }\n"
1808  + " final state FINI {\n"
1809  + " entry {\n"
1810  + " do y1.deactivate()\n"
1811  //+ " do test.assert(false)\n"
1812  + " }\n"
1813  + " transitions {\n"
1814  + " select INIT\n"
1815  + " }\n"
1816  + " }\n"
1817  + " }\n"
1818  + " RootMachine X x() \n" // instantiate a hierarchical SC
1819  ;
1820 
1821  this->doState("x", prog, tc, true, 100 );
1822  //BOOST_CHECK( tc->engine()->states()->getStateMachine( "x" )->inState("FINI") );
1823  this->finishState( "x", tc);
1824 }
1825 
1826 BOOST_AUTO_TEST_CASE( testSelfDeactivatingStateMachineinEntry )
1827 {
1828  string prog = string("StateMachine X {\n")
1829  + " initial state INIT {\n"
1830  + " transitions {select FINI} \n"
1831  + " }\n"
1832  + " final state FINI {\n"
1833  + " entry{\n"
1834  + " try scripting.deactivateStateMachine(\"x\")\n"
1835  + " }\n"
1836  + " }\n"
1837  + "}\n"
1838  + "RootMachine X x()\n";
1839  this->parseState( prog, tc );
1840  StateMachinePtr sm = sa->getStateMachine("x");
1841  BOOST_REQUIRE( sm );
1842  // causes deactivation of SM:
1843  runState( "x", tc, false);//without trace
1844  BOOST_CHECK( !sm->isActive() );
1845  // causes deactivation of SM:
1846  runState( "x", tc, true);//with trace
1847  BOOST_CHECK( !sm->isActive() );
1848 
1849 }
1850 
1851 BOOST_AUTO_TEST_CASE( testSelfDeactivatingStateMachineinRun )
1852 {
1853  string prog = string("StateMachine X {\n")
1854  + " initial state INIT {\n"
1855  + " transitions {select FINI} \n"
1856  + " }\n"
1857  + " final state FINI {\n"
1858  + " run{\n"
1859  + " try scripting.deactivateStateMachine(\"x\")\n"
1860  + " }\n"
1861  + " }\n"
1862  + "}\n"
1863  + "RootMachine X x()\n";
1864  this->parseState( prog, tc );
1865  StateMachinePtr sm = sa->getStateMachine("x");
1866  BOOST_REQUIRE( sm );
1867  // causes deactivation of SM:
1868  runState( "x", tc, false);//without trace
1869  BOOST_CHECK( !sm->isActive() );
1870  // causes deactivation of SM:
1871  runState( "x", tc, true);//with trace
1872  BOOST_CHECK( !sm->isActive() );
1873 }
1874 
1875 BOOST_AUTO_TEST_CASE( testSelfDeactivatingStateMachineinHandle )
1876 {
1877  string prog = string("StateMachine X {\n")
1878  + " initial state INIT {\n"
1879  + " handle{\n"
1880  + " try scripting.deactivateStateMachine(\"x\")\n"
1881  + " }\n"
1882  + " transition if false == true then select FINI \n"
1883  + " }\n"
1884  + " final state FINI {\n"
1885  + " }\n"
1886  + "}\n"
1887  + "RootMachine X x()\n";
1888  this->parseState( prog, tc );
1889  StateMachinePtr sm = sa->getStateMachine("x");
1890  BOOST_REQUIRE( sm );
1891  // causes deactivation of SM:
1892  runState( "x", tc, false);//without trace
1893  BOOST_CHECK( !sm->isActive() );
1894  // causes deactivation of SM:
1895  runState( "x", tc, true);//with trace
1896  BOOST_CHECK( !sm->isActive() );
1897 }
1898 
1899 BOOST_AUTO_TEST_CASE( testSelfDeactivatingStateMachineinExit )
1900 {
1901  string prog = string("StateMachine X {\n")
1902  + " initial state INIT {\n"
1903  + " exit{\n"
1904  + " try scripting.deactivateStateMachine(\"x\")\n"
1905  + " }\n"
1906  + " transitions {select FINI} \n"
1907  + " }\n"
1908  + " final state FINI {\n"
1909  + " }\n"
1910  + "}\n"
1911  + "RootMachine X x()\n";
1912  this->parseState( prog, tc );
1913  StateMachinePtr sm = sa->getStateMachine("x");
1914  BOOST_REQUIRE( sm );
1915  // causes deactivation of SM:
1916  runState( "x", tc, false);//without trace
1917  BOOST_CHECK( !sm->isActive() );
1918  // causes deactivation of SM:
1919  runState( "x", tc, true);//with trace
1920  BOOST_CHECK( !sm->isActive() );
1921 }
1922 
1923 BOOST_AUTO_TEST_CASE( testSelfDeactivatingStateMachineinTransition )
1924 {
1925  string prog = string("StateMachine X {\n")
1926  + " initial state INIT {\n"
1927  + " transition if true then {\n"
1928  + " scripting.deactivateStateMachine(\"x\")\n"
1929  + " }select FINI \n"
1930  + " }\n"
1931  + " final state FINI {\n"
1932  + " }\n"
1933  + "}\n"
1934  + "RootMachine X x()\n";
1935  this->parseState( prog, tc );
1936  StateMachinePtr sm = sa->getStateMachine("x");
1937  BOOST_REQUIRE( sm );
1938  // causes deactivation of SM:
1939  runState( "x", tc, false);//without trace
1940  BOOST_CHECK( !sm->isActive() );
1941  // causes deactivation of SM:
1942  runState( "x", tc, true);//with trace
1943  BOOST_CHECK( !sm->isActive() );
1944 }
1945 
1947 
1948 void StateTest::doState( const std::string& name, const std::string& prog, TaskContext* tc, bool test, int runs )
1949 {
1950  BOOST_CHECK( tc->engine() );
1951 
1952  parseState( prog, tc, test);
1953  runState(name, tc, true, test,runs);
1954  checkState(name, tc, test);
1955 }
1956 
1957 void StateTest::parseState(const std::string& prog, TaskContext* tc, bool test )
1958 {
1959  // Alternative way: test ScriptingService as well.
1960  try {
1961  sa->loadStateMachines( prog, std::string("state_test.cpp"), true );
1962  }
1963  catch( const file_parse_exception& exc )
1964  {
1965  BOOST_REQUIRE_MESSAGE( !test, exc.what() );
1966  }
1967  catch( const parse_exception& exc )
1968  {
1969  BOOST_REQUIRE_MESSAGE( !test, exc.what() );
1970  }
1971  catch( const program_load_exception& e)
1972  {
1973  BOOST_REQUIRE_MESSAGE( !test, e.what() );
1974  }
1975  catch( const std::exception& e ) {
1976  BOOST_CHECK_MESSAGE( !test , e.what());
1977  BOOST_REQUIRE_MESSAGE( !test, "Uncaught Processor load exception" );
1978  }
1979 }
1980 
1981 void StateTest::runState(const std::string& name, TaskContext* tc, bool trace, bool test, int runs )
1982 {
1983  StateMachinePtr sm = sa->getStateMachine(name);
1984  BOOST_REQUIRE( sm );
1985  sm->trace(trace);
1986  StateMachine::ChildList children = sm->getChildren();
1987  for( StateMachine::ChildList::iterator it = children.begin(); it != children.end(); ++it)
1988  (*it)->trace(trace);
1989  OperationCaller<bool(StateMachinePtr)> act = tc->provides(name)->getOperation("activate");
1990  OperationCaller<bool(StateMachinePtr)> autom = tc->provides(name)->getOperation("automatic");
1991  BOOST_CHECK( act(sm) );
1992  BOOST_CHECK( SimulationThread::Instance()->run(1) );
1993  BOOST_CHECK_MESSAGE( sm->isActive(), "Error : Activate Command for '"+sm->getName()+"' did not have effect." );
1994  BOOST_CHECK( autom(sm) || !test );
1995 
1996  BOOST_CHECK( SimulationThread::Instance()->run(runs) );
1997 }
1998 
1999 void StateTest::checkState(const std::string& name, TaskContext* tc, bool test )
2000 {
2001  StateMachinePtr sm = sa->getStateMachine(name);
2002  BOOST_REQUIRE( sm );
2003  if ( test ) {
2004  // check error status of parent :
2005  BOOST_CHECK_MESSAGE( sm->isActive(), "Error : State Context '"+sm->getName()+"' did not get activated." );
2006  stringstream errormsg;
2007  int line = sm->getLineNumber();
2008  errormsg <<" in StateMachine "+sm->getName()
2009  <<" in state "<< (sm->currentState() ? sm->currentState()->getName() : "(null)")
2010  <<" on line " << line <<" of that StateMachine:"<<endl;
2011  {
2012  stringstream sctext( sm->getText() );
2013  int cnt = 1;
2014  while ( cnt++ <line && sctext ) {
2015  string garbage;
2016  getline( sctext, garbage, '\n' );
2017  }
2018  getline( sctext, sline, '\n' );
2019  }
2020  errormsg <<"here > " << sline << endl;
2021  if ( sm->inError() ) {
2023  RTT::scripting::DumpObject( tc->provides(name) );
2024  }
2025  BOOST_CHECK_MESSAGE( sm->inError() == false, "Runtime error (inError() == true) encountered" + errormsg.str() );
2026  // check error status of all children:
2027  StateMachine::ChildList cl = sm->getChildren();
2028  StateMachine::ChildList::iterator clit = cl.begin();
2029  while( clit != cl.end() ) {
2030  line = (*clit)->getLineNumber();
2031  {
2032  stringstream sctext( (*clit)->getText() );
2033  int cnt = 1;
2034  while ( cnt++ <line && sctext ) {
2035  string garbage;
2036  getline( sctext, garbage, '\n' );
2037  }
2038  getline( sctext, sline, '\n' );
2039  }
2040  stringstream cerrormsg;
2041  if ( (*clit)->currentState() )
2042  cerrormsg <<" in child "<< (*clit)->getName() <<" in state "<<(*clit)->currentState()->getName()<< " on line " << (*clit)->getLineNumber() <<" of that StateMachine."<<endl <<"here > " << sline << endl;
2043  else
2044  cerrormsg <<" child "<< (*clit)->getName() << " (deactivated) on line " << (*clit)->getLineNumber() <<" of that StateMachine."<<endl<<"here > " << sline << endl;
2045 
2046  BOOST_CHECK_MESSAGE( (*clit)->inError() == false, "Runtime error (inError() == true) encountered" + cerrormsg.str() );
2047  if ( (*clit)->inError() == false && sm->inError() == true) {
2048  cout << "Child Status:" << cerrormsg.str() << endl;
2049  }
2050  ++clit;
2051  }
2052  }
2053 }
2054 
2055 void StateTest::finishState(std::string const& name, TaskContext* tc, bool test)
2056 {
2057  StateMachinePtr sm = sa->getStateMachine(name);
2058  BOOST_REQUIRE( sm );
2059  BOOST_CHECK( sa->getStateMachine( name )->stop() );
2060  BOOST_CHECK( SimulationThread::Instance()->run(10) );
2061  if (test) {
2062  stringstream errormsg;
2063  errormsg << " on line " << sm->getLineNumber() <<", status is "<< sa->getStateMachineStatusStr(name) <<endl <<"here > " << sline << endl;;
2064  BOOST_CHECK_MESSAGE( sm->isStopped(), "StateMachine stalled " + errormsg.str() );
2065  }
2066  // you can call deactivate even when the proc is not running.
2067  // but deactivation may be 'in progress if exit state has commands in it.
2068  BOOST_CHECK( sa->getStateMachine( name )->deactivate() );
2069  BOOST_CHECK( SimulationThread::Instance()->run(10) );
2070  if ( sm->isActive() )
2071  BOOST_CHECK( sa->getStateMachine( name )->deactivate() );
2072  BOOST_CHECK( SimulationThread::Instance()->run(10) );
2073  BOOST_CHECK( sa->getStateMachine( name )->isActive() == false );
2074 
2075  // only stop now, since deactivate won't work if simtask not running.
2076  tc->stop();
2077 
2078  try {
2079  BOOST_CHECK( sa->unloadStateMachine( name ) );
2080  }
2081  catch( const program_unload_exception& e)
2082  {
2083  BOOST_REQUIRE_MESSAGE( false, e.what() );
2084  }
2085  catch( ... ) {
2086  BOOST_REQUIRE_MESSAGE( false, "Uncaught Processor unload exception" );
2087  }
2088 
2089 }
2090 
void checkState(const std::string &name, TaskContext *, bool test=true)
Operation< Signature > & doc(const std::string &description)
Definition: Operation.hpp:128
const std::string what() const
#define BOOST_FIXTURE_TEST_SUITE(suite_name, F)
boost::shared_ptr< ScriptingService > shared_ptr
Service::shared_ptr provides()
virtual const std::string what() const =0
SendStatus tss
Definition: state_test.cpp:75
std::basic_string< char, std::char_traits< char >, RTT::os::rt_allocator< char > > rt_string
Real-time allocatable, dynamically-sized string.
Definition: rt_string.hpp:50
virtual bool stop()
#define BOOST_AUTO_TEST_SUITE_END()
Operation< void(double)> o_event
Definition: state_test.cpp:55
Definition: mystd.hpp:163
InputPort< double > d_event
Definition: state_test.cpp:51
BOOST_AUTO_TEST_CASE(testParseState)
Definition: state_test.cpp:149
Operation< void(void)> v_event
Definition: state_test.cpp:54
ScriptingService::shared_ptr sa
Definition: state_test.cpp:63
SendStatus
Definition: SendStatus.hpp:53
Operation< void(double)> c_event
Definition: state_test.cpp:59
static SimulationThreadPtr Instance(double period=0.001)
void DumpObject(Service::shared_ptr peer)
Definition: DumpObject.cpp:54
printstream cout
Definition: rtstreams.cpp:45
static RTT_API ExecutionEngine * Instance()
void log(const std::string &msg)
Definition: state_test.cpp:77
void finishState(std::string const &name, TaskContext *, bool test=true)
virtual bool connectTo(PortInterface *other, ConnPolicy const &policy)
boost::shared_ptr< StateMachine > StateMachinePtr
OutputPort< bool > b_event_source
Definition: state_test.cpp:61
Operation< void(void)> v2_event
Definition: state_test.cpp:57
basic_ostreams & endl(basic_ostreams &s)
Definition: rtstreams.cpp:110
RTT::rt_string mrt_state
Definition: state_test.cpp:71
An Activity executes a RunnableInterface object in a (periodic) thread.
Definition: Activity.hpp:70
std::vector< StateMachinePtr > ChildList
unsigned int sleep(unsigned int s)
Definition: fosi.cpp:51
void setState(RTT::rt_string state)
Definition: state_test.cpp:66
OutputPort< double > d_event_source
Definition: state_test.cpp:60
static Logger & log()
Definition: Logger.cpp:117
void parseState(const std::string &prog, TaskContext *, bool test=true)
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:53
RTT::Operation< void(RTT::rt_string)> setState_op
Definition: state_test.cpp:65
Operation< void(void)> v1_event
Definition: state_test.cpp:56
InputPort< int > t_event
Definition: state_test.cpp:53
A SimulationActivity is a PeriodicActivity which is used for simulation.
std::string sline
Definition: state_test.cpp:86
OutputPort< int > t_event_source
Definition: state_test.cpp:62
Operation< void(void)> v3_event
Definition: state_test.cpp:58
static Logger::LogFunction endlog()
Definition: Logger.hpp:362
void runState(const std::string &name, TaskContext *, bool trace=true, bool test=true, int runs=1000)
InputPort< bool > b_event
Definition: state_test.cpp:52


rtt
Author(s): RTT Developers
autogenerated on Tue Jun 25 2019 19:33:36