function_test.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Mon Jan 10 15:59:51 CET 2005 function_test.cpp
3 
4  function_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 
20 #include "unit.hpp"
21 #include "operations_fixture.hpp"
22 
23 
24 #include <scripting/Parser.hpp>
27 #include <Service.hpp>
28 #include <OperationCaller.hpp>
29 
31 {
32 public:
34  : sa( ScriptingService::Create(tc) )
35  {
36  tc->stop();
37  tc->setActivity(new SimulationActivity(0.01));
38  SimulationThread::Instance()->stop();
39  tc->start();
40  }
42  ScriptingService::shared_ptr sa;
43 
44  void doFunction( const std::string& prog, TaskContext*, bool test=true );
45  void finishFunction( TaskContext* , std::string );
47 };
48 
49 BOOST_FIXTURE_TEST_SUITE( FunctionsFixtureSuite, FunctionsFixture )
50 // Registers the fixture into the 'registry'
51 
52 BOOST_AUTO_TEST_CASE( testSimpleFunction)
53 {
54  string prog = string("function foo { \n")
55  + " do test.assert( test.isTrue( true ) )\n"
56  + "}\n"
57  + "program x { \n"
58  + " call foo\n"
59  + "}";
60 
61  this->doFunction( prog, tc );
62  this->finishFunction( tc, "x");
63 }
64 
65 BOOST_AUTO_TEST_CASE( testSimpleReturnFunction)
66 {
67  string prog = string("int foo { \n")
68  + " test.assert( test.isTrue( true ) )\n"
69  + " return 3\n"
70  + "}\n"
71  + "\n"
72  + "program x { \n"
73  + " test.assert(true);\n"
74  + " call foo\n"
75  + " test.assert(true);\n"
76  + "}";
77 
78  this->doFunction( prog, tc );
79  this->finishFunction( tc, "x");
80 }
81 
82 BOOST_AUTO_TEST_CASE( testExportFunction)
83 {
84  string prog = string("export function foo { \n")
85  + " do test.assert( test.isTrue( true ) )\n"
86  + "}\n"
87  + "export function foo_args() { \n"
88  + " do test.assert( test.isTrue( true ) )\n"
89  + "}\n"
90  + "program x { \n"
91  + " do this.foo()\n"
92  + " do this.foo_args()\n"
93  + "}";
94 
95  this->doFunction( prog, tc );
96  BOOST_CHECK( tc->getOperation("foo") );
97  this->finishFunction( tc, "x");
98 }
99 
100 #ifdef ORO_REMOTING
101 
107 BOOST_AUTO_TEST_CASE( testOnlyExportFunction)
108 {
109  string prog = string("export function foo { \n")
110 // + " test.print(\"foo()\")\n"
111  + " do test.assert( test.isTrue( true ) )\n"
112  + "}\n"
113  + "export int foo_ret(double d) { \n"
114 // + " test.printNumber(\"foo_ret(double d), d is: \", d)\n"
115  + " if (true) then\n"
116  + " return 3\n"
117  + " else\n"
118  + " return 5\n"
119  + "}\n"
120  + "export int foo_args(double d, int v) { \n"
121 // + " test.printNumber(\"foo_args(double d, int v) v is: \", v)\n"
122  + " var double r = 10\n"
123  + " if ( d == 3.0 && v == 6) then\n"
124  + " set r = +1\n"
125  + " else\n"
126  + " set r = -1\n"
127  + " return r;\n"
128  + "}\n";
129 
130  this->doFunction( prog, tc );
131  BOOST_CHECK( tc->getOperation("foo") );
132 
133  // Test call:
134  {
136  BOOST_CHECK( foo.ready() );
137 
138  foo();
139  }
140 #if 0
141  // Test pure send:
142  {
144  BOOST_CHECK( foo.ready() );
145 
146  foo.send();
147  }
148 
149  // Test send + collect:
150  {
152  BOOST_CHECK( foo.ready() );
153 
154  SendHandle<void(void)> sh = foo.send();
155  BOOST_CHECK_EQUAL( sh.collect(), SendSuccess);
156  }
157 #endif
158  // Test call:
159  {
160  OperationCaller<int(double)> foo_ret( tc->getOperation("foo_ret"), caller->engine());
161  BOOST_CHECK( foo_ret.ready() );
162 
163  int i = 0;
164  i = foo_ret(3.0);
165  BOOST_CHECK_EQUAL( i, 3 );
166  }
167 #if 0
168  // Test pure send:
169  {
170  OperationCaller<int(double)> foo_ret( tc->getOperation("foo_ret"), caller->engine());
171  BOOST_CHECK( foo_ret.ready() );
172 
173  int i = 0;
174  foo_ret.send(3.0);
175  }
176 
177  // Test send + collect:
178  {
179  OperationCaller<int(double)> foo_ret( tc->getOperation("foo_ret"), caller->engine());
180  BOOST_CHECK( foo_ret.ready() );
181 
182  int i = 0;
183  SendHandle<int(double)> sh = foo_ret.send(3.0);
184  BOOST_CHECK_EQUAL( sh.collect(i), SendSuccess);
185  BOOST_CHECK_EQUAL( i, 3 );
186  }
187 #endif
188  // Test call:
189  {
190  BOOST_CHECK( tc->getOperation("foo_args") );
191  OperationCaller<int(double,int)> foo_args( tc->getOperation("foo_args"), caller->engine());
192  BOOST_CHECK( foo_args.ready() );
193 
194  int i = 0;
195  i = foo_args(-3.0, -6);
196  BOOST_CHECK_EQUAL( i, -1);
197 
198  i = 0;
199  i = foo_args(3.0, 6);
200  BOOST_CHECK_EQUAL( i, +1);
201  }
202 #if 0
203  // Test pure send:
204  {
205  BOOST_CHECK( tc->getOperation("foo_args") );
206  OperationCaller<int(double,int)> foo_args( tc->getOperation("foo_args"), caller->engine());
207  BOOST_CHECK( foo_args.ready() );
208 
209  foo_args.send(-3.0, -6);
210  foo_args.send(3.0, 6);
211  }
212 
213  // Test send + collect:
214  {
215  BOOST_CHECK( tc->getOperation("foo_args") );
216  OperationCaller<int(double,int)> foo_args( tc->getOperation("foo_args"), caller->engine());
217  BOOST_CHECK( foo_args.ready() );
218 
219  int i = 0;
220  SendHandle<int(double,int)> sh = foo_args.send(-3.0, -6);
221  BOOST_CHECK_EQUAL( sh.collect(i), SendSuccess);
222  BOOST_CHECK_EQUAL( i, -1);
223 
224  i = 0;
225  sh = foo_args.send(3.0, 6);
226  BOOST_CHECK_EQUAL( sh.collect(i), SendSuccess);
227  BOOST_CHECK_EQUAL( i, +1);
228  }
229 #endif
230 }
231 #endif
232 
236 BOOST_AUTO_TEST_CASE( testReturnExportFunction)
237 {
238  string prog = string("export function foo { \n")
239  + " do test.assert( test.isTrue( true ) )\n"
240  + "}\n"
241  + "export int foo_ret() { \n"
242  + " if (true) then\n"
243  + " return 3\n"
244  + " else\n"
245  + " return 5\n"
246  + "}\n"
247  + "export int foo_args(double d, int v) { \n"
248  + " do test.assert( test.isTrue( true ) )\n"
249  + " if ( d == 3.0 && v == 6) then\n"
250  + " return +1\n" // 10
251  + " else\n"
252  + " return -1\n"
253  + " return 4\n"
254  + "}\n"
255  + "program x { \n"
256  + " this.foo()\n" // a void function
257  + " this.foo_ret()\n"
258  + " this.foo_args(3.0,6)\n"
259  + " test.assertEqual(this.foo_ret(), 3 )\n"
260  + " test.assertEqual(this.foo_args(3.0,6), 1)\n" // 20
261  + " test.assertEqual(this.foo_args(0.0,0), -1)\n"
262  + "}";
263 
264  this->doFunction( prog, tc );
265  BOOST_CHECK( tc->getOperation("foo") );
266  this->finishFunction( tc, "x");
267 }
268 
269 #if 0
270 // Test removing exported function in infinite loop.
271 BOOST_AUTO_TEST_CASE( testRemoveFunction)
272 {
273  string prog = string("export function foo { \n")
274  + " while (true) { do nothing }\n" // this one yiels politely
275  + "}\n"
276  + "program x { \n"
277  + " this.foo()\n" // this will hang the program's execution being blocked in waitForMessages for foo() to return... should we use a yield point ? Was so before because it were commands...
278  //+ " this.foo.send()\n" // send/collect not yet supported.
279  + "}";
280 
281  this->doFunction( prog, tc, false );
282  BOOST_CHECK( tc->getOperation("foo") );
283  // removing the program should lead to removal of the function from the PP.
284  this->finishFunction( tc, "x");
285 }
286 #endif
287 BOOST_AUTO_TEST_CASE( testRecFunction)
288 {
289  string prog = string("export function foo { \n")
290  + " do this.foo()\n" // recursive is forbidden.
291  + "}\n"
292  + "program x { \n"
293  + " do foo\n"
294  + "}";
295 
296  try {
297  parser.parseProgram( prog, tc );
298  }
299  catch( ... )
300  {
301  prog = string("function foo { \n")
302  + " call foo\n" // recursive is forbidden.
303  + "}\n"
304  + "program x { \n"
305  + " call foo\n"
306  + "}";
307  //progs = prog;
308  try {
309  parser.parseProgram( prog, tc );
310  }
311  catch( ... )
312  {
313  return;
314  }
315  BOOST_CHECK_MESSAGE( false, "Recursive 'call' function was accepted, while it is illegal." );
316  }
317  BOOST_CHECK_MESSAGE( false , "Recursive 'do' function was accepted, while it is illegal.");
318 }
319 
320 BOOST_AUTO_TEST_CASE( testCallFunction)
321 {
322  string prog = string("function foo(int a, string b, bool c) { \n")
323  + " do test.assert( test.isTrue( true ) )\n"
324  + " if true then\n"
325  + " return\n"
326  + " do test.assert(false)\n" // do not reach
327  + "}\n"
328  + "program x { \n"
329  + " call foo( 1, \"hello\", true)\n"
330  + "}";
331 
332  this->doFunction( prog, tc );
333  this->finishFunction( tc, "x");
334 }
335 
336 BOOST_AUTO_TEST_CASE( testFunctionStack)
337 {
338  string prog = string("export function foo { \n")
339  +" var double a = 1.234\n"
340  +" var double b = 4.321\n"
341  +" do test.assert( a == 1.234 )\n"
342  +" do test.assert( b == 4.321 )\n"
343  +" set a = 2.134\n"
344  +" set b = 3.421\n"
345  +" do test.assert( a == 2.134 )\n"
346  +" do test.assert( b == 3.421 )\n"
347  + "}\n"
348  + "program x { \n"
349  +" var double b = 1.234\n" // we switch val's of a and b here
350  +" var double a = 4.321\n"
351  + " do foo()\n"
352  +" do test.assert( b == 1.234 )\n"
353  +" do test.assert( a == 4.321 )\n"
354  + " do foo()\n"
355  + " set a = 0.0\n"
356  + " set b = 1.0\n"
357  +" do test.assert( b == 1.0 )\n"
358  +" do test.assert( a == 0.0 )\n"
359  + "}";
360 
361  this->doFunction( prog, tc );
362  this->finishFunction( tc, "x");
363 }
364 
365 
366 BOOST_AUTO_TEST_CASE( testFunctionExportArgs)
367 {
368  // Test if the foo args are init'ed correctly.
369  string prog =
370  string("export function fooA(int a, string b, bool c) { \n")
371  + " do test.assertMsg( c, \"c not true\" )\n"
372  + " do test.assertMsg( a == 1, \"a not 1\" )\n"
373  + " do test.assertMsg( b == \"A\", \"b not A\" )\n"
374  + "}\n"
375  + "export function fooB(int a, string b, bool c) { \n"
376  + " do test.assertMsg( !c, \"c not false\" )\n"
377  + " do test.assertMsg( a == -1, \"a not -1\" )\n"
378  + " do test.assertMsg( b == \"B\", \"b not B\" )\n"
379  + " do fooA(1, \"A\", true)\n"
380  + "}\n"
381  + "program x { \n"
382  + " do fooA(1, \"A\", true)\n"
383  + " do fooB(-1, \"B\", false)\n"
384 // + " call fooA(1.0, \"A\", true)\n"
385 // + " call fooB(-1, \"B\", false)\n"
386  + "}";
387 
388  this->doFunction( prog, tc );
389  this->finishFunction( tc, "x");
390 }
391 
392 BOOST_AUTO_TEST_CASE( testFunctionCallArgs)
393 {
394  // Test if the foo args are init'ed correctly.
395  string prog =
396  string("function fooA(int a, string b, bool c) { \n")
397  + " do test.assert( c )\n"
398  + " do test.assert( a == 1 )\n"
399  + " do test.assert( b == \"A\" )\n"
400  + "}\n"
401  + "function fooB(int a, string b, bool c) { \n"
402  + " do test.assert( !c )\n"
403  + " var int i = 1\n"
404  + " var string s = \"A\"\n"
405  + " var bool tf = true\n"
406  + " call fooA(i, s, tf)\n"
407  + " do test.assert( a == -1 )\n"
408  + " do test.assert( b == \"B\" )\n"
409  + "}\n"
410  + "program x { \n"
411  + " call fooA(1, \"A\", true)\n"
412  + " call fooB(-1, \"B\", false)\n"
413 // + " call fooA(1.0, \"A\", true)\n"
414 // + " call fooB(-1, \"B\", false)\n"
415  + "}";
416 
417  this->doFunction( prog, tc );
418  this->finishFunction( tc, "x");
419 }
420 
421 BOOST_AUTO_TEST_CASE( testFunctionFail)
422 {
423  // Test if obj-function error is propagated correctly to
424  // calling program or function
425  string prog =
426  string("export function fooA { \n")
427  + " do test.assert( false )\n" // throws error
428  + "}\n"
429  + "export function fooB { \n"
430  + " do fooA()\n"
431  + "}\n"
432  + "program x { \n"
433  + " var bool success = false\n"
434  + " try fooA()\n"
435  + " catch \n"
436  + " set success = true\n" // error caught.
437  + " do test.assertMsg(success,\"Program script did not detect exported function failure.\")\n"
438  + " set success = false\n"
439  + " try fooB()\n"
440  + " catch\n"
441  + " set success = true\n" // error caught.
442  + " do test.assertMsg(success,\"Program script did not detect exported function failure.\")\n"
443  + "}";
444 
445  this->doFunction( prog, tc );
446  this->finishFunction( tc, "x");
447 }
448 
450 
451 void FunctionsFixture::doFunction( const std::string& prog, TaskContext* tc, bool test )
452 {
453  BOOST_REQUIRE( tc->engine() );
454  Parser::ParsedPrograms pg_list;
455  try {
456  pg_list = parser.parseProgram( prog, tc );
457  }
458  catch( const file_parse_exception& exc )
459  {
460  BOOST_REQUIRE_MESSAGE( false , exc.what() );
461  }
462  catch( ... ) {
463  BOOST_REQUIRE_MESSAGE( false, "Unknown exception thrown by Parser.");
464  }
465  if ( pg_list.empty() )
466  {
467  // no program necessary here.
468  //BOOST_REQUIRE_MESSAGE(false , "No program parsed in test.");
469  return;
470  }
471 
472  BOOST_REQUIRE( sa->loadProgram( *pg_list.begin() ) );
473  BOOST_CHECK( sa->getProgram( (*pg_list.begin())->getName() )->start() );
474 
475  BOOST_CHECK( SimulationThread::Instance()->run(1000) );
476 
477  if (test ) {
478  stringstream errormsg;
479  errormsg << " on line " << sa->getProgram("x")->getLineNumber() <<" of program 'x' (or of a function 'called' by x)."<<endl;
480  BOOST_REQUIRE_MESSAGE( sa->getProgramStatus("x") != ProgramInterface::Status::error , "Runtime Error Status encountered" + errormsg.str());
481  BOOST_REQUIRE_MESSAGE( sa->getProgramStatus("x") == ProgramInterface::Status::stopped, "Program stalled" + errormsg.str() );
482  }
483 }
484 
485 void FunctionsFixture::finishFunction(TaskContext* tc, std::string prog_name)
486 {
487  BOOST_REQUIRE( sa->getProgram(prog_name) );
488  sa->getProgram( prog_name )->stop();
489  sa->unloadProgram( prog_name );
490 }
491 
492 
const std::string what() const
#define BOOST_FIXTURE_TEST_SUITE(suite_name, F)
virtual bool stop()
#define BOOST_AUTO_TEST_SUITE_END()
Definition: mystd.hpp:163
boost::shared_ptr< ProgramInterface > ProgramInterfacePtr
bool setActivity(base::ActivityInterface *new_act)
void doFunction(const std::string &prog, TaskContext *, bool test=true)
The SendHandle is used to collect the result values of an asynchronous invocation. The template argument Signature must have the same type as the method being invoked.
Definition: rtt-fwd.hpp:79
std::vector< ProgramInterfacePtr > ParsedPrograms
Definition: Parser.hpp:101
BOOST_AUTO_TEST_CASE(testSimpleFunction)
ScriptingService::shared_ptr sa
This class is the public interface to the Orocos Program Parser Framework. It parsers Orocos program ...
Definition: Parser.hpp:65
basic_ostreams & endl(basic_ostreams &s)
Definition: rtstreams.cpp:110
OperationInterfacePart * getOperation(std::string name)
ParsedPrograms parseProgram(const std::string &s, TaskContext *, const std::string &filename="stream")
Reads out the string, parses it, and returns a new ProgramGraph.
Definition: Parser.cpp:103
void finishFunction(TaskContext *, std::string)
SendStatus collect() const
Definition: SendHandle.hpp:124
A SimulationActivity is a PeriodicActivity which is used for simulation.
void loopProgram(ProgramInterfacePtr)
const ExecutionEngine * engine() const
Definition: TaskCore.hpp:306
virtual bool start()
void foo(double d)


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