function_test.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   tag: Peter Soetens  Mon Jan 10 15:59:51 CET 2005  function_test.cpp
00003 
00004                         function_test.cpp -  description
00005                            -------------------
00006     begin                : Mon January 10 2005
00007     copyright            : (C) 2005 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.be
00009 
00010  ***************************************************************************
00011  *                                                                         *
00012  *   This program is free software; you can redistribute it and/or modify  *
00013  *   it under the terms of the GNU General Public License as published by  *
00014  *   the Free Software Foundation; either version 2 of the License, or     *
00015  *   (at your option) any later version.                                   *
00016  *                                                                         *
00017  ***************************************************************************/
00018 
00019 
00020 #include "unit.hpp"
00021 #include "operations_fixture.hpp"
00022 
00023 
00024 #include <scripting/Parser.hpp>
00025 #include <scripting/FunctionGraph.hpp>
00026 #include <scripting/ScriptingService.hpp>
00027 #include <Service.hpp>
00028 #include <OperationCaller.hpp>
00029 
00030 class FunctionsFixture : public OperationsFixture
00031 {
00032 public:
00033     FunctionsFixture()
00034         : sa( ScriptingService::Create(tc) )
00035     {
00036         tc->stop();
00037         tc->setActivity(new SimulationActivity(0.01));
00038         SimulationThread::Instance()->stop();
00039         tc->start();
00040     }
00041     Parser parser;
00042     ScriptingService::shared_ptr sa;
00043 
00044     void doFunction( const std::string& prog, TaskContext*, bool test=true );
00045     void finishFunction( TaskContext* , std::string );
00046     void loopProgram( ProgramInterfacePtr );
00047 };
00048 
00049 BOOST_FIXTURE_TEST_SUITE( FunctionsFixtureSuite, FunctionsFixture )
00050 // Registers the fixture into the 'registry'
00051 
00052 BOOST_AUTO_TEST_CASE( testSimpleFunction)
00053 {
00054     string prog = string("function foo { \n")
00055         + " do test.assert( test.isTrue( true ) )\n"
00056         + "}\n"
00057         + "program x { \n"
00058         + "   call foo\n"
00059         + "}";
00060 
00061     this->doFunction( prog, tc );
00062     this->finishFunction( tc, "x");
00063 }
00064 
00065 BOOST_AUTO_TEST_CASE( testSimpleReturnFunction)
00066 {
00067     string prog = string("int foo { \n")
00068         + " test.assert( test.isTrue( true ) )\n"
00069         + " return 3\n"
00070         + "}\n"
00071         + "\n"
00072         + "program x { \n"
00073         + "   test.assert(true);\n"
00074         + "   call foo\n"
00075         + "   test.assert(true);\n"
00076         + "}";
00077 
00078     this->doFunction( prog, tc );
00079     this->finishFunction( tc, "x");
00080 }
00081 
00082 BOOST_AUTO_TEST_CASE( testExportFunction)
00083 {
00084     string prog = string("export function foo { \n")
00085         + " do test.assert( test.isTrue( true ) )\n"
00086         + "}\n"
00087         + "export function foo_args() { \n"
00088         + " do test.assert( test.isTrue( true ) )\n"
00089         + "}\n"
00090         + "program x { \n"
00091         + "   do this.foo()\n"
00092         + "   do this.foo_args()\n"
00093         + "}";
00094 
00095     this->doFunction( prog, tc );
00096     BOOST_CHECK( tc->getOperation("foo") );
00097     this->finishFunction( tc, "x");
00098 }
00099 
00100 #ifdef ORO_REMOTING
00101 
00107 BOOST_AUTO_TEST_CASE( testOnlyExportFunction)
00108 {
00109     string prog = string("export function foo { \n")
00110 //                + "   test.print(\"foo()\")\n"
00111         + " do test.assert( test.isTrue( true ) )\n"
00112         + "}\n"
00113         + "export int foo_ret(double d) { \n"
00114 //        + "   test.printNumber(\"foo_ret(double d), d is: \", d)\n"
00115         + "   if (true) then\n"
00116         + "     return 3\n"
00117         + "   else\n"
00118         + "     return 5\n"
00119         + "}\n"
00120         + "export int foo_args(double d, int v) { \n"
00121 //        + " test.printNumber(\"foo_args(double d, int v) v is: \", v)\n"
00122         + " var double r = 10\n"
00123         + " if ( d == 3.0 && v == 6) then\n"
00124         + "     set r = +1\n"
00125         + " else\n"
00126         + "     set r = -1\n"
00127         + " return r;\n"
00128         + "}\n";
00129 
00130     this->doFunction( prog, tc );
00131     BOOST_CHECK( tc->getOperation("foo") );
00132 
00133     // Test call:
00134     {
00135         OperationCaller<void(void)> foo( tc->getOperation("foo"), caller->engine());
00136         BOOST_CHECK( foo.ready() );
00137 
00138         foo();
00139     }
00140 #if 0
00141     // Test pure send:
00142     {
00143         OperationCaller<void(void)> foo( tc->getOperation("foo"), caller->engine());
00144         BOOST_CHECK( foo.ready() );
00145 
00146         foo.send();
00147     }
00148 
00149     // Test send + collect:
00150     {
00151         OperationCaller<void(void)> foo( tc->getOperation("foo"), caller->engine());
00152         BOOST_CHECK( foo.ready() );
00153 
00154         SendHandle<void(void)> sh = foo.send();
00155         BOOST_CHECK_EQUAL( sh.collect(), SendSuccess);
00156     }
00157 #endif
00158     // Test call:
00159     {
00160         OperationCaller<int(double)> foo_ret( tc->getOperation("foo_ret"), caller->engine());
00161         BOOST_CHECK( foo_ret.ready() );
00162 
00163         int i = 0;
00164         i = foo_ret(3.0);
00165         BOOST_CHECK_EQUAL( i, 3 );
00166     }
00167 #if 0
00168     // Test pure send:
00169     {
00170         OperationCaller<int(double)> foo_ret( tc->getOperation("foo_ret"), caller->engine());
00171         BOOST_CHECK( foo_ret.ready() );
00172 
00173         int i = 0;
00174         foo_ret.send(3.0);
00175     }
00176 
00177     // Test send + collect:
00178     {
00179         OperationCaller<int(double)> foo_ret( tc->getOperation("foo_ret"), caller->engine());
00180         BOOST_CHECK( foo_ret.ready() );
00181 
00182         int i = 0;
00183         SendHandle<int(double)> sh = foo_ret.send(3.0);
00184         BOOST_CHECK_EQUAL( sh.collect(i), SendSuccess);
00185         BOOST_CHECK_EQUAL( i, 3 );
00186     }
00187 #endif
00188     // Test call:
00189     {
00190         BOOST_CHECK( tc->getOperation("foo_args") );
00191         OperationCaller<int(double,int)> foo_args( tc->getOperation("foo_args"), caller->engine());
00192         BOOST_CHECK( foo_args.ready() );
00193 
00194         int i = 0;
00195         i = foo_args(-3.0, -6);
00196         BOOST_CHECK_EQUAL( i, -1);
00197 
00198         i = 0;
00199         i = foo_args(3.0, 6);
00200         BOOST_CHECK_EQUAL( i, +1);
00201     }
00202 #if 0
00203     // Test pure send:
00204     {
00205         BOOST_CHECK( tc->getOperation("foo_args") );
00206         OperationCaller<int(double,int)> foo_args( tc->getOperation("foo_args"), caller->engine());
00207         BOOST_CHECK( foo_args.ready() );
00208 
00209         foo_args.send(-3.0, -6);
00210         foo_args.send(3.0, 6);
00211     }
00212 
00213     // Test send + collect:
00214     {
00215         BOOST_CHECK( tc->getOperation("foo_args") );
00216         OperationCaller<int(double,int)> foo_args( tc->getOperation("foo_args"), caller->engine());
00217         BOOST_CHECK( foo_args.ready() );
00218 
00219         int i = 0;
00220         SendHandle<int(double,int)> sh = foo_args.send(-3.0, -6);
00221         BOOST_CHECK_EQUAL( sh.collect(i), SendSuccess);
00222         BOOST_CHECK_EQUAL( i, -1);
00223 
00224         i = 0;
00225         sh = foo_args.send(3.0, 6);
00226         BOOST_CHECK_EQUAL( sh.collect(i), SendSuccess);
00227         BOOST_CHECK_EQUAL( i, +1);
00228     }
00229 #endif
00230 }
00231 #endif
00232 
00236 BOOST_AUTO_TEST_CASE( testReturnExportFunction)
00237 {
00238     string prog = string("export function foo { \n")
00239         + " do test.assert( test.isTrue( true ) )\n"
00240         + "}\n"
00241         + "export int foo_ret() { \n"
00242         + "   if (true) then\n"
00243         + "     return 3\n"
00244         + "   else\n"
00245         + "     return 5\n"
00246         + "}\n"
00247         + "export int foo_args(double d, int v) { \n"
00248         + " do test.assert( test.isTrue( true ) )\n"
00249         + " if ( d == 3.0 && v == 6) then\n"
00250         + "     return +1\n" // 10
00251         + " else\n"
00252         + "     return -1\n"
00253         + " return 4\n"
00254         + "}\n"
00255         + "program x { \n"
00256         + "   this.foo()\n" // a void function
00257         + "   this.foo_ret()\n"
00258         + "   this.foo_args(3.0,6)\n"
00259         + "   test.assertEqual(this.foo_ret(), 3 )\n"
00260         + "   test.assertEqual(this.foo_args(3.0,6), 1)\n" // 20
00261         + "   test.assertEqual(this.foo_args(0.0,0), -1)\n"
00262         + "}";
00263 
00264     this->doFunction( prog, tc );
00265     BOOST_CHECK( tc->getOperation("foo") );
00266     this->finishFunction( tc, "x");
00267 }
00268 
00269 #if 0
00270 // Test removing exported function in infinite loop.
00271 BOOST_AUTO_TEST_CASE( testRemoveFunction)
00272 {
00273     string prog = string("export function foo { \n")
00274         + " while (true) { do nothing }\n" // this one yiels politely
00275         + "}\n"
00276         + "program x { \n"
00277         + "   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...
00278         //+ "   this.foo.send()\n" // send/collect not yet supported.
00279         + "}";
00280 
00281     this->doFunction( prog, tc, false );
00282     BOOST_CHECK( tc->getOperation("foo") );
00283     // removing the program should lead to removal of the function from the PP.
00284     this->finishFunction( tc, "x");
00285 }
00286 #endif
00287 BOOST_AUTO_TEST_CASE( testRecFunction)
00288 {
00289     string prog = string("export function foo { \n")
00290         + " do this.foo()\n" // recursive is forbidden.
00291         + "}\n"
00292         + "program x { \n"
00293         + "   do foo\n"
00294         + "}";
00295 
00296     try {
00297         parser.parseProgram( prog, tc );
00298     }
00299     catch( ... )
00300         {
00301             prog = string("function foo { \n")
00302                 + " call foo\n" // recursive is forbidden.
00303                 + "}\n"
00304                 + "program x { \n"
00305                 + "   call foo\n"
00306                 + "}";
00307             //progs = prog;
00308             try {
00309                 parser.parseProgram( prog, tc );
00310             }
00311             catch( ... )
00312                 {
00313                     return;
00314                 }
00315             BOOST_CHECK_MESSAGE( false, "Recursive 'call' function was accepted, while it is illegal." );
00316         }
00317     BOOST_CHECK_MESSAGE( false , "Recursive 'do' function was accepted, while it is illegal.");
00318 }
00319 
00320 BOOST_AUTO_TEST_CASE( testCallFunction)
00321 {
00322     string prog = string("function foo(int a, string b, bool c) { \n")
00323         + " do test.assert( test.isTrue( true ) )\n"
00324         + " if true then\n"
00325         + "    return\n"
00326         + " do test.assert(false)\n"  // do not reach
00327         + "}\n"
00328         + "program x { \n"
00329         + "   call foo( 1, \"hello\", true)\n"
00330         + "}";
00331 
00332     this->doFunction( prog, tc );
00333     this->finishFunction( tc, "x");
00334 }
00335 
00336 BOOST_AUTO_TEST_CASE( testFunctionStack)
00337 {
00338     string prog = string("export function foo { \n")
00339         +"  var double a = 1.234\n"
00340         +"  var double b = 4.321\n"
00341         +"  do test.assert( a == 1.234 )\n"
00342         +"  do test.assert( b == 4.321 )\n"
00343         +"  set a = 2.134\n"
00344         +"  set b = 3.421\n"
00345         +"  do test.assert( a == 2.134 )\n"
00346         +"  do test.assert( b == 3.421 )\n"
00347         + "}\n"
00348         + "program x { \n"
00349         +"  var double b = 1.234\n" // we switch val's of a and b here
00350         +"  var double a = 4.321\n"
00351         + "   do foo()\n"
00352         +"  do test.assert( b == 1.234 )\n"
00353         +"  do test.assert( a == 4.321 )\n"
00354         + "   do foo()\n"
00355         + " set a = 0.0\n"
00356         + " set b = 1.0\n"
00357         +"  do test.assert( b == 1.0 )\n"
00358         +"  do test.assert( a == 0.0 )\n"
00359         + "}";
00360 
00361     this->doFunction( prog, tc );
00362     this->finishFunction( tc, "x");
00363 }
00364 
00365 
00366 BOOST_AUTO_TEST_CASE( testFunctionExportArgs)
00367 {
00368     // Test if the foo args are init'ed correctly.
00369     string prog =
00370         string("export function fooA(int a, string b, bool c) { \n")
00371         + " do test.assertMsg( c, \"c not true\" )\n"
00372         + " do test.assertMsg( a == 1, \"a not 1\" )\n"
00373         + " do test.assertMsg( b == \"A\", \"b not A\" )\n"
00374         + "}\n"
00375         + "export function fooB(int a, string b, bool c) { \n"
00376         + " do test.assertMsg( !c, \"c not false\" )\n"
00377         + " do test.assertMsg( a == -1, \"a not -1\" )\n"
00378         + " do test.assertMsg( b == \"B\", \"b not B\"   )\n"
00379         + " do fooA(1, \"A\", true)\n"
00380         + "}\n"
00381         + "program x { \n"
00382         + "   do fooA(1, \"A\", true)\n"
00383         + "   do fooB(-1, \"B\", false)\n"
00384 //         + "   call fooA(1.0, \"A\", true)\n"
00385 //         + "   call fooB(-1, \"B\", false)\n"
00386         + "}";
00387 
00388     this->doFunction( prog, tc );
00389     this->finishFunction( tc, "x");
00390 }
00391 
00392 BOOST_AUTO_TEST_CASE( testFunctionCallArgs)
00393 {
00394     // Test if the foo args are init'ed correctly.
00395     string prog =
00396         string("function fooA(int a, string b, bool c) { \n")
00397         + " do test.assert( c )\n"
00398         + " do test.assert( a == 1 )\n"
00399         + " do test.assert( b == \"A\" )\n"
00400         + "}\n"
00401         + "function fooB(int a, string b, bool c) { \n"
00402         + " do test.assert( !c )\n"
00403         + " var int i = 1\n"
00404         + " var string s = \"A\"\n"
00405         + " var bool tf = true\n"
00406         + " call fooA(i, s, tf)\n"
00407         + " do test.assert( a == -1 )\n"
00408         + " do test.assert( b == \"B\" )\n"
00409         + "}\n"
00410         + "program x { \n"
00411         + "   call fooA(1, \"A\", true)\n"
00412         + "   call fooB(-1, \"B\", false)\n"
00413 //         + "   call fooA(1.0, \"A\", true)\n"
00414 //         + "   call fooB(-1, \"B\", false)\n"
00415         + "}";
00416 
00417     this->doFunction( prog, tc );
00418     this->finishFunction( tc, "x");
00419 }
00420 
00421 BOOST_AUTO_TEST_CASE( testFunctionFail)
00422 {
00423     // Test if obj-function error is propagated correctly to
00424     // calling program or function
00425     string prog =
00426         string("export function fooA { \n")
00427         + " do test.assert( false )\n" // throws error
00428         + "}\n"
00429         + "export function fooB { \n"
00430         + " do fooA()\n"
00431         + "}\n"
00432         + "program x { \n"
00433         + "   var bool success = false\n"
00434         + "   try fooA()\n"
00435         + "   catch \n"
00436         + "      set success = true\n" // error caught.
00437         + "   do test.assertMsg(success,\"Program script did not detect exported function failure.\")\n"
00438         + "   set success = false\n"
00439         + "   try fooB()\n"
00440         + "   catch\n"
00441         + "      set success = true\n" // error caught.
00442         + "   do test.assertMsg(success,\"Program script did not detect exported function failure.\")\n"
00443         + "}";
00444 
00445     this->doFunction( prog, tc );
00446     this->finishFunction( tc, "x");
00447 }
00448 
00449 BOOST_AUTO_TEST_SUITE_END()
00450 
00451 void FunctionsFixture::doFunction( const std::string& prog, TaskContext* tc, bool test )
00452 {
00453     BOOST_REQUIRE( tc->engine() );
00454     Parser::ParsedPrograms pg_list;
00455     try {
00456         pg_list = parser.parseProgram( prog, tc );
00457     }
00458     catch( const file_parse_exception& exc )
00459     {
00460         BOOST_REQUIRE_MESSAGE( false , exc.what() );
00461     }
00462     catch( ... ) {
00463         BOOST_REQUIRE_MESSAGE( false, "Unknown exception thrown by Parser.");
00464     }
00465     if ( pg_list.empty() )
00466     {
00467         // no program necessary here.
00468         //BOOST_REQUIRE_MESSAGE(false , "No program parsed in test.");
00469         return;
00470     }
00471 
00472     BOOST_REQUIRE( sa->loadProgram( *pg_list.begin() ) );
00473     BOOST_CHECK( sa->getProgram( (*pg_list.begin())->getName() )->start() );
00474 
00475     BOOST_CHECK( SimulationThread::Instance()->run(1000) );
00476 
00477     if (test ) {
00478         stringstream errormsg;
00479         errormsg << " on line " << sa->getProgram("x")->getLineNumber() <<" of program 'x' (or of a function 'called' by x)."<<endl;
00480         BOOST_REQUIRE_MESSAGE( sa->getProgramStatus("x") != ProgramInterface::Status::error , "Runtime Error Status encountered" + errormsg.str());
00481         BOOST_REQUIRE_MESSAGE( sa->getProgramStatus("x") == ProgramInterface::Status::stopped, "Program stalled" + errormsg.str() );
00482     }
00483 }
00484 
00485 void FunctionsFixture::finishFunction(TaskContext* tc, std::string prog_name)
00486 {
00487     BOOST_REQUIRE( sa->getProgram(prog_name) );
00488     sa->getProgram( prog_name )->stop();
00489     sa->unloadProgram( prog_name );
00490 }
00491 
00492 


rtt
Author(s): RTT Developers
autogenerated on Thu Jan 2 2014 11:35:21