scripting_test.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: The SourceWorks Tue Sep 7 00:54:57 CEST 2010 scripting_test.cpp
3 
4  scripting_test.cpp - description
5  -------------------
6  begin : Tue September 07 2010
7  copyright : (C) 2010 The SourceWorks
8  email : peter@thesourceworks.com
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 "operations_fixture.hpp"
22 #include <scripting/Scripting.hpp>
25 #include <plugin/PluginLoader.hpp>
26 #include <scripting/Parser.hpp>
28 
29 
30 using namespace std;
31 using namespace boost;
32 using namespace RTT;
33 using namespace RTT::detail;
34 
35 #include <boost/shared_ptr.hpp>
36 
37 // note: Does not preserve newlines. Add them explicitly with \n or add semicolons after each line.
38 #define MULTILINE_STRING(...) #__VA_ARGS__
39 
40 // Registers the fixture into the 'registry'
41 BOOST_FIXTURE_TEST_SUITE( ScriptingTestSuite, OperationsFixture )
42 
43 BOOST_AUTO_TEST_CASE(TestGetProvider)
45 {
46  //ScriptingService* sa = new ScriptingService( tc ); // done by TC or plugin.
47 
48  PluginLoader::Instance()->loadService("scripting",tc);
49 
50  boost::shared_ptr<Scripting> sc = tc->getProvider<Scripting>("scripting");
51  BOOST_REQUIRE( sc );
52  BOOST_CHECK ( sc->ready() );
53  BOOST_REQUIRE( sc->loadProgramText( MULTILINE_STRING(
54  program Foo {
55  do test.assert(true);
56  set ret = 10.0;
57  })));
58  BOOST_CHECK( sc->hasProgram("Foo") );
59  BOOST_REQUIRE( sc->startProgram("Foo") );
60  BOOST_CHECK( sc->isProgramRunning("Foo") );
61 
62  // executes our script in the EE:
63  while(sc->isProgramRunning("Foo")) {
64  tc->trigger();
65  usleep(100);
66  }
67 
68  // test results:
69  BOOST_CHECK( sc->isProgramRunning("Foo") == false );
70  BOOST_CHECK( sc->inProgramError("Foo") == false );
71  BOOST_CHECK( ret == 10.0 );
72 
73 }
74 
75 BOOST_AUTO_TEST_CASE(TestScriptingParser)
76 {
77  PluginLoader::Instance()->loadService("scripting",tc);
78 
79  boost::shared_ptr<Scripting> sc = tc->getProvider<Scripting>("scripting");
80  BOOST_REQUIRE( sc );
81  BOOST_CHECK ( sc->ready() );
82 
83  // test plain statements:
84  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
85  ;;test.increase()\n
86  ;;;\n
87  test.increase()))); // trailing newline is optional
88  BOOST_CHECK_EQUAL( i, 1);
89 
90  // test variable decls:
91  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
92  var int i = 0;
93  var int y, z = 10;
94  test.i = z;
95  )));
96  BOOST_CHECK_EQUAL( i, 10);
97 
98  // test if statement:
99  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
100  var int x = 1, y = 2;
101  if 3 == 8 then
102  test.i = x;
103  else
104  test.i = y;
105  )));
106  BOOST_CHECK_EQUAL( i, 2);
107 
108  // test while statement:
109  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
110  var int x = 1, y = 2;
111  while x != y {
112  test.i = 3;
113  x = y;
114  })));
115  BOOST_CHECK_EQUAL( i, 3);
116 
117  // test while name clash:
118  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
119  var int whilex, whiley\n
120  whilex = 1;
121  whiley = 2\n
122  while whilex != whiley {
123  test.i = 3;
124  whilex = whiley;
125  })));
126  BOOST_CHECK_EQUAL( i, 3);
127 
128  // test for statement:
129  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
130  var int x = 10, y = 20;
131  for( x = 0; x != y; x = x + 1) {
132  test.i = x;
133  })));
134  BOOST_CHECK_EQUAL( i, 19);
135 
136  // test for name clash:
137  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
138  var int forx, fory\n
139  forx = 10; fory = 20;
140  for( forx = 0; forx != fory; forx = forx + 1) {
141  test.i = forx;
142  })));
143  BOOST_CHECK_EQUAL( i, 19);
144 
145  // test function + a statement that uses that function:
146  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
147  export function adder(int a, int b) {
148  test.i = a + b;
149  }\n
150  adder(5,6)\n
151  )));
152  BOOST_CHECK_EQUAL( i, 11);
153  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
154  export void adder2(int a, int b) {
155  test.i = a + b;
156  }\n
157  adder2(7,8)\n
158  )));
159  BOOST_CHECK_EQUAL( i, 15);
160  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
161  export int adder3(int a, int b) {
162  return a + b;
163  }\n
164  test.i = adder3(6,10)\n
165  )));
166  BOOST_CHECK_EQUAL( i, 16);
167 
168  // test program + a statement that starts that program and waits for the result.
169  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
170  program rt_script {
171  test.i = 3-9;
172  }\n
173  rt_script.start();;;;
174  while( rt_script.isRunning() ) {
175  trigger();
176  yield;
177  })));
178  BOOST_CHECK_EQUAL( sc->getProgramStatus("rt_script"), ProgramInterface::Status::stopped );
179  BOOST_CHECK_EQUAL( i, -6);
180 
181  // test state machine + a statement that starts that SM and waits for the result.
182  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
183  StateMachine RTState {
184  initial state init {
185  entry {
186  test.i = 0;
187  }
188  transitions {
189  select fini;
190  }
191  }
192 
193  final state fini {
194  entry {
195  test.i = test.i - 2;
196  }
197  }
198  }
199  RootMachine RTState rt_state;
200  rt_state.activate();
201  rt_state.start();
202  while( !rt_state.inFinalState() ) {
203  trigger();
204  yield; // ...has no effect here other than incrementing the step counter! See ScriptParser::seenstatement().
205  })));
206  BOOST_CHECK_EQUAL( sc->getStateMachineState("rt_state"), "fini" );
207  BOOST_CHECK_EQUAL( i, -2);
208 }
209 
210 BOOST_AUTO_TEST_CASE(TestScriptingFunction)
211 {
212  PluginLoader::Instance()->loadService("scripting",tc);
213 
214  boost::shared_ptr<Scripting> sc = tc->getProvider<Scripting>("scripting");
215  BOOST_REQUIRE( sc );
216  BOOST_CHECK ( sc->ready() );
217 
218  // set test counter to zero:
219  i = 0;
220 
221  // define a function (added to scripting interface):
222  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
223  void func1(void) {
224  test.increase();
225  })));
226  BOOST_CHECK_EQUAL( i, 0);
227  BOOST_CHECK( tc->provides("scripting")->hasMember("func1"));
228 
229  // export a function:
230  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
231  export void efunc1(void) {
232  test.increase();
233  })));
234  BOOST_CHECK_EQUAL( i, 0);
235  BOOST_CHECK( tc->provides()->hasMember("efunc1"));
236 
237  // local function:
238  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
239  void lfunc1(void) {
240  test.increase();
241  })));
242  BOOST_CHECK_EQUAL( i, 0);
243  BOOST_CHECK( tc->provides("scripting")->hasMember("lfunc1"));
244 
245  // global function:
246  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
247  global void gfunc1(void) {
248  test.increase();
249  })));
250  BOOST_CHECK_EQUAL( i, 0);
251  BOOST_CHECK( GlobalService::Instance()->provides()->hasMember("gfunc1"));
252 
253  // nested function call:
254  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
255  void func2(void) {
256  func1();
257  })));
258  BOOST_CHECK_EQUAL( i, 0);
259  BOOST_CHECK( tc->provides("scripting")->hasMember("func2"));
260 
261  // nested exported function call:
262  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
263  void efunc2(void) {
264  efunc1();
265  })));
266  BOOST_CHECK_EQUAL( i, 0);
267  BOOST_CHECK( tc->provides("scripting")->hasMember("efunc2"));
268 
269  // nested global function call:
270  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
271  void gfunc2(void) {
272  gfunc1();
273  })));
274  BOOST_CHECK_EQUAL( i, 0);
275  BOOST_CHECK( tc->provides("scripting")->hasMember("gfunc2"));
276 
277  // nested local function call:
278  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
279  void lfunc2(void) {
280  lfunc1();
281  })));
282  BOOST_CHECK_EQUAL( i, 0);
283  BOOST_CHECK( tc->provides("scripting")->hasMember("lfunc2"));
284 
285  // invoke a function:
286  BOOST_REQUIRE( sc->eval("func1()") );
287  BOOST_CHECK_EQUAL( i, 1);
288 
289  // invoke an exported function:
290  BOOST_REQUIRE( sc->eval("efunc1()") );
291  BOOST_CHECK_EQUAL( i, 2);
292 
293  // invoke a global function:
294  BOOST_REQUIRE( sc->eval("gfunc1()") );
295  BOOST_CHECK_EQUAL( i, 3);
296 
297  // invoke a local function:
298  BOOST_REQUIRE( sc->eval("lfunc1()") );
299  BOOST_CHECK_EQUAL( i, 4);
300 
301  // invoke a function with a nested function call:
302  BOOST_REQUIRE( sc->eval("func2()") );
303  BOOST_CHECK_EQUAL( i, 5);
304 
305  // invoke a function with a nested exported function call:
306  BOOST_REQUIRE( sc->eval("efunc2()") );
307  BOOST_CHECK_EQUAL( i, 6);
308 
309  // invoke a function with a nested global function call:
310  BOOST_REQUIRE( sc->eval("gfunc2()") );
311  BOOST_CHECK_EQUAL( i, 7);
312 
313  // invoke a function with a nested local function call:
314  BOOST_REQUIRE( sc->eval("lfunc2()") );
315  BOOST_CHECK_EQUAL( i, 8);
316 
317  // call a function:
318  BOOST_CHECK( !sc->eval("call func1()") );
319  BOOST_CHECK_EQUAL( i, 8);
320 
321  // call an exported function:
322  BOOST_CHECK( !sc->eval("call efunc1()") );
323  BOOST_CHECK_EQUAL( i, 8);
324 
325  // RE-define a function (added to scripting interface):
326  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
327  void func1(void) {
328  test.increase();
329  test.increase();
330  })));
331  BOOST_CHECK_EQUAL( i, 8);
332  BOOST_CHECK( tc->provides("scripting")->hasMember("func1"));
333 
334  BOOST_REQUIRE( sc->eval("func1()") );
335  BOOST_CHECK_EQUAL( i, 10);
336 
337  // RE-export a function:
338  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
339  export void efunc1(void) {
340  test.increase();
341  test.increase();
342  })));
343  BOOST_CHECK_EQUAL( i, 10);
344  BOOST_CHECK( tc->provides()->hasMember("efunc1"));
345 
346  BOOST_REQUIRE( sc->eval("efunc1()") );
347  BOOST_CHECK_EQUAL( i, 12);
348 
349  // RE-global a function:
350  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
351  global void gfunc1(void) {
352  test.increase();
353  test.increase();
354  })));
355  BOOST_CHECK_EQUAL( i, 12);
356  BOOST_CHECK( GlobalService::Instance()->provides()->hasMember("gfunc1"));
357 
358  BOOST_REQUIRE( sc->eval("gfunc1()") );
359  BOOST_CHECK_EQUAL( i, 14);
360 }
361 
362 BOOST_AUTO_TEST_CASE(TestScriptingFunctionWithYield)
363 {
364  PluginLoader::Instance()->loadService("scripting",tc);
365 
366  // We need a periodic activity for this test case so that yielded functions
367  // will be executed again while we are waiting.
368  tc->setPeriod(0.1);
369 
370  boost::shared_ptr<Scripting> sc = tc->getProvider<Scripting>("scripting");
371  BOOST_REQUIRE( sc );
372  BOOST_CHECK ( sc->ready() );
373 
374  // set test counter to zero:
375  i = 0;
376 
377  // define a function that yields:
378  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
379  void func1(void) {
380  test.printNumber("[ENTER func1()] CycleCounter = ", CycleCounter);
381  test.increase();
382  yield;
383  test.increase();
384  test.printNumber("[EXIT func1()] CycleCounter = ", CycleCounter);
385  })));
386  BOOST_CHECK_EQUAL( i, 0);
387  BOOST_CHECK( tc->provides("scripting")->hasMember("func1"));
388 
389  // define a function that calls func1, yields and calls func1 again:
390  BOOST_REQUIRE( sc->eval( MULTILINE_STRING(
391  void func2(void) {
392  test.printNumber("[ENTER func2()] CycleCounter = ", CycleCounter);
393  func1();
394  yield;
395  func1();
396  test.printNumber("[EXIT func2()] CycleCounter = ", CycleCounter);
397  })));
398  BOOST_CHECK_EQUAL( i, 0);
399  BOOST_CHECK( tc->provides("scripting")->hasMember("func2"));
400 
401  // invoke func1()
402  BOOST_REQUIRE( sc->eval("func1()") );
403  BOOST_CHECK_EQUAL( i, 2);
404 
405  // invoke func2()
406  BOOST_REQUIRE( sc->eval("func2()") );
407  BOOST_CHECK_EQUAL( i, 6);
408 }
409 
A hierarchical StateMachine which is loaded in the Program Processor.
#define BOOST_FIXTURE_TEST_SUITE(suite_name, F)
BOOST_AUTO_TEST_CASE(TestGetProvider)
Tests the scripting service&#39;s functions.
#define MULTILINE_STRING(...)
#define BOOST_AUTO_TEST_SUITE_END()
Definition: mystd.hpp:163
int usleep(unsigned int us)
Definition: fosi.cpp:58
static void yield(TaskContext *tc)
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:53
static bool trigger(TaskContext *tc)


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