program_test.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   tag: Peter Soetens  Mon Jan 10 15:59:51 CET 2005  program_test.cpp
00003 
00004                         program_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 
00022 #include <iostream>
00023 #include <sstream>
00024 #include <string>
00025 
00026 #include <scripting/Parser.hpp>
00027 #include <scripting/FunctionGraph.hpp>
00028 #include <scripting/ScriptingService.hpp>
00029 #include <extras/SimulationThread.hpp>
00030 #include <extras/SimulationActivity.hpp>
00031 #include <Service.hpp>
00032 
00033 #include <TaskContext.hpp>
00034 #include <OperationCaller.hpp>
00035 #include "operations_fixture.hpp"
00036 
00037 using namespace RTT;
00038 using namespace RTT::detail;
00039 using namespace std;
00040 
00041 
00042 
00043 class ProgramTest : public OperationsFixture
00044 {
00045 public:
00046     Parser parser;
00047     ScriptingService::shared_ptr sa;
00048     int var_i;
00049     int const_i;
00050 
00051     void doProgram( const std::string& prog, TaskContext*, bool test=true );
00052     void finishProgram( TaskContext* , std::string );
00053     void loopProgram( ProgramInterfacePtr );
00054 
00055     ProgramTest()
00056         : sa( ScriptingService::Create(tc) )
00057     {
00058         tc->stop();
00059         BOOST_REQUIRE( tc->setActivity(new SimulationActivity(0.01)) );
00060         BOOST_REQUIRE( tc->start() );
00061         tc->provides()->addService( sa );
00062         tc->provides()->addAttribute("tvar_i", var_i);
00063         tc->provides()->addConstant("tconst_i", const_i);
00064         // ltc has a test object
00065 
00066         const_i = -1;
00067         var_i = -1;
00068         i = 0;
00069         SimulationThread::Instance()->stop();
00070     }
00071 
00072     ~ProgramTest()
00073     {
00074     }
00075 
00076 };
00077 
00078 BOOST_FIXTURE_TEST_SUITE( ProgramTestSuite, ProgramTest )
00079 // Registers the fixture into the 'registry'
00080 
00081 BOOST_AUTO_TEST_CASE(testEmptyProgram)
00082 {
00083     string prog = "";
00084     Parser::ParsedPrograms pg_list;
00085     try {
00086         pg_list = parser.parseProgram( prog, tc );
00087     }
00088     catch( const file_parse_exception& /*exc*/ )
00089         {
00090             BOOST_CHECK( false );
00091         }
00092     if ( !pg_list.empty() )
00093         {
00094             BOOST_CHECK( false );
00095         }
00096 }
00097 
00098 BOOST_AUTO_TEST_CASE(testReturnProgram)
00099 {
00100     string prog = "program x { return \n }";
00101     this->doProgram( prog, tc );
00102     this->finishProgram( tc, "x");
00103 }
00104 
00105 // check that loading a faulty program causes an exception
00106 // and that the program is not present as a service in tc
00107 BOOST_AUTO_TEST_CASE(testProgramError)
00108 {
00109     string prog = "program x { not_exist = 10\n }";
00110     Parser::ParsedPrograms pg_list;
00111     BOOST_CHECK_THROW(pg_list = parser.parseProgram( prog, tc ),file_parse_exception);
00112     BOOST_CHECK( pg_list.empty() );
00113     BOOST_REQUIRE( tc->provides()->hasService("x") == false);
00114 
00115     BOOST_CHECK( sa->runScript(prog) == false);
00116     BOOST_REQUIRE( tc->provides()->hasService("x") == false);
00117 }
00118 
00119 // same as above, but with runScript
00120 BOOST_AUTO_TEST_CASE(testrunScriptError)
00121 {
00122     string prog = "tvar_i = 33\n program x { not_exist = 10\n } \n tvar_i = 66\n";
00123     BOOST_CHECK( sa->eval(prog) == false);
00124     BOOST_CHECK_EQUAL( var_i, 33 );
00125     BOOST_REQUIRE( tc->provides()->hasService("x") == false);
00126 }
00127 
00128 // tests if the text is properly saved
00129 BOOST_AUTO_TEST_CASE(test_getProgramText)
00130 {
00131     // a program which should never fail
00132     // test this methods.
00133     string prog = string("/** This is the test_getProgramText to parse */\nprogram x { \n")
00134         + " true\n"
00135         + "}";
00136 
00137     this->doProgram( prog, tc );
00138     BOOST_CHECK_EQUAL( sa->getProgramText("x"), prog );
00139     this->finishProgram( tc, "x");
00140 }
00141 
00142 // tests if the text is properly saved in runScript
00143 BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(test_getProgramText_runScript, 1)
00144 BOOST_AUTO_TEST_CASE(test_getProgramText_runScript)
00145 {
00146     // a program which should never fail
00147     // test this methods.
00148     string prog = string("/** This is the test_getProgramText_runScript to parse */\nprogram x { \n")
00149         + " true\n"
00150         + "}\n";
00151 
00152     string evaled = string("tvar_i = 33\n") + prog + "tvar_i = 66\n";
00153 
00154     BOOST_CHECK( sa->eval(evaled) == true);
00155     BOOST_CHECK_EQUAL( sa->getProgramText("x"), evaled + "\n" );
00156 }
00157 
00158 BOOST_AUTO_TEST_CASE(testParseProgram)
00159 {
00160     // a program which should never fail
00161     // test this methods.
00162     string prog = string("program x { \n")
00163         + " do true\n"
00164         + " do test.assert( true )\n"
00165         + " do test.increase()\n"
00166         + " do test.resetI()\n"
00167         + " do test.assert( test.isTrue( true ) )\n"
00168         + " do test.assert( test.i == 0 )\n"
00169         + " do test.increase()\n"
00170         + " do test.assert( test.i == 1 )\n"
00171         + " do test.resetI()\n"
00172         + " do test.assert( test.i == 0 )\n"
00173         + " if test.increase() + test.increase() + test.increase() != 6  then \n "
00174         + "    do test.assert( false )\n"
00175         + " do test.assert( test.isTrue( true ) )\n"
00176         + " do test.resetI()\n"
00177         + " do test.assert( test.i == 0 )\n"
00178         + " if test.increase() + test.increase() + test.increase() != 6  then \n "
00179         + "    do test.assert( false )\n"
00180         + " if true then\n"
00181         + "    return\n"
00182         + " do test.assert(false)"  // do not reach
00183         + "}";
00184 
00185     this->doProgram( prog, tc );
00186     this->finishProgram( tc, "x");
00187 }
00188 
00189 BOOST_AUTO_TEST_CASE(testProgramFailure)
00190 {
00191     //also small test for program without newlines
00192     string prog = string("program x { do test.fail();}");
00193 
00194     this->doProgram( prog, tc, false );
00195 
00196     BOOST_CHECK( sa->getProgramStatus("x") == ProgramInterface::Status::error );
00197 
00198     this->finishProgram( tc, "x");
00199 }
00200 BOOST_AUTO_TEST_CASE(testProgramCondition)
00201 {
00202     // see if checking a remote condition works
00203     string prog = string("program x { \n")
00204         + "if test.isTrue(true) then \n"
00205         + "  do test.good() \n"
00206         + "else \n"
00207         + "  do test.fail() \n"
00208         + "if test.isTrue(false) then \n"
00209         + "  do test.fail() \n"
00210         + "else \n"
00211         + "  do test.good() \n"
00212         + "if test.isTrue(true) then \n" //10
00213         + "   if test.isTrue(true) then \n"
00214         + "      if test.isTrue(false) then \n"
00215         + "         do test.fail() \n"
00216         + "      else \n"
00217         + "         if test.isTrue(false) then \n"
00218         + "            do test.fail() \n"
00219         + "         else \n"
00220         + "            do test.good() \n"
00221         + "   else \n"
00222         + "      do test.fail() \n" //20
00223         + "else \n"
00224         + "   do test.fail() \n"
00225         + "var bool trig = false \n"
00226         + "do test.resetI()\n"
00227         + "while test.increase() != 100 && !trig \n"
00228         + "   if test.i == 50 then \n"
00229         + "       set trig = true \n"
00230         + "if test.i != 51 then \n" // the test.increase() will first increment i to 51, and then we detect trig.
00231         + "    do test.fail() \n"
00232         + "do test.resetI()\n" //30
00233         + "set trig = false\n"
00234         + "for (var int j = 0; j != 100 && !trig ; set j = test.increase() )\n"
00235         + "   if j == 50 then \n"
00236         + "       set trig = true \n"
00237 //         + "if test.i != 51 then \n" // require same result as with ISO C
00238 //         + "    do test.fail() \n"
00239         + "return "
00240         + "}";
00241     this->doProgram( prog, tc );
00242     this->finishProgram( tc, "x");
00243 }
00244 
00245 BOOST_AUTO_TEST_CASE(testProgramBreak)
00246 {
00247     // see if  break statement works
00248     string prog = string("program x { \n")
00249         + "do test.resetI()\n"
00250         + "while (test.increase() != 100)\n"
00251         + "   if test.i == 50 then {\n"
00252         + "       break\n"
00253         + "       do test.fail() \n" // do not reach.
00254         + "   }\n"
00255         + "if test.i != 50 then \n" // break on 50
00256         + "    do test.fail() \n"
00257         + "do test.resetI()\n"
00258         + "for (var int j = 0; j != 100  ; set j = test.increase() )\n"
00259         + "   if j != 50 then \n"
00260         + "       do nothing \n"
00261         + "   else {\n"
00262         + "       break \n"
00263         + "       do test.fail() \n" // do not reach.
00264         + "     }\n"
00265         + "if test.i != 50 then \n" // break on 50
00266         + "    do test.fail() \n"
00267         + "do test.resetI()\n"
00268         + "while test.increase() != 100 {\n"
00269         + "   while test.increase() != 100 \n"
00270         + "     if test.i == 50 then {\n"
00271         + "         break \n"
00272         + "         do test.fail() \n" // do not reach.
00273         + "     }\n"
00274         + "   if test.i != 50 then \n" // break on 50
00275         + "      do test.fail() \n"
00276         + "   if test.i == 50 then \n"
00277         + "      break \n"
00278         + "   do test.fail() \n" // do not reach.
00279         + "   }\n"
00280         + "if test.i != 50 then \n" // break on 50
00281         + "    do test.fail() \n"
00282         + "return \n"
00283         + "}";
00284     this->doProgram( prog, tc );
00285     this->finishProgram( tc, "x");
00286 }
00287 
00288 BOOST_AUTO_TEST_CASE(testProgramLoops)
00289 {
00290     // see if (nested) loop statements work
00291     string prog = string("program x { \n")
00292         + "do test.resetI()\n"
00293         // single while loop
00294         + "while (test.increase() != 100) {\n"
00295         + "}\n"
00296         + "if test.i != 100 then \n"
00297         + "    do test.fail() \n"
00298         + "do test.resetI()\n"
00299         // double while loop
00300         + "while (test.increase() != 200) {\n"
00301         + "   while (test.i < 100) {\n"
00302         + "       test.increase()\n"
00303         + "   }\n"
00304         + "   if test.i < 100 then \n"
00305         + "      do test.fail() \n"
00306         + "}\n"
00307         + "if test.i != 200 then \n"
00308         + "    do test.fail() \n"
00309         + "do test.resetI()\n"
00310         // single for loop
00311         + "for (var int j = 0; j != 100  ; j = test.increase() ) {\n"
00312         + "}\n"
00313         + "if test.i != 100 then \n" // 20
00314         + "    do test.fail() \n"
00315         + "if j != 100 then \n"
00316         + "    do test.fail() \n"
00317         + "do test.resetI()\n"
00318         // double for loop
00319         + "for ( j = 0; j != 100  ; j = test.increase() ) {\n"
00320         + "   for (var int j2 = 0; j2 != 100  ; j2 = j2 + 1 ) {\n"
00321         + "   }\n"
00322         + "   if j2 != 100 then \n"
00323         + "      do test.fail() \n"
00324         + "}\n"
00325         + "if test.i != 100 then \n"
00326         + "    do test.fail() \n"
00327         + "if j != 100 then \n"
00328         + "    do test.fail() \n"
00329         + "if j2 != 100 then \n"
00330         + "    do test.fail() \n"
00331         + "do test.resetI()\n"
00332         // for loop in while loop
00333         + "while (test.increase() != 200) {\n"
00334         + "   for (var int j3 = 0; j3 != 100  ; j3 = j3 + 1 ) {\n"
00335         + "   }\n"   // 40
00336         + "}\n"
00337         + "if test.i != 200 then \n"
00338         + "    do test.fail() \n"
00339         + "if j3 != 100 then \n"
00340         + "    do test.fail() \n"
00341         + "do test.resetI()\n"
00342         // for loop in while loop + break in for
00343         + "while (test.increase() != 200) {\n"
00344         + "   for (var int j3b = 0; j3b != 100  ; j3b = j3b + 1 ) {\n"
00345         + "      if j3b == 50 then break \n"
00346         + "   }\n"
00347         + "   if j3b != 50 then \n"
00348         + "      do test.fail() \n"
00349         + "}\n"
00350         + "if test.i != 200 then \n"
00351         + "    do test.fail() \n"
00352         + "if j3b != 50 then \n"
00353         + "    do test.fail() \n"
00354         + "do test.resetI()\n"
00355         // while loop in for loop
00356         + "for (var int j4 = 0; j4 != 100  ; j4 = j4 + 1 ) {\n"
00357         + "   test.resetI()\n" // 60
00358         + "   while (test.increase() != 200) {\n"
00359         + "   }\n"
00360         + "}\n"
00361         + "if test.i != 200 then \n"
00362         + "    do test.fail() \n"
00363         + "if j4 != 100 then \n"
00364         + "    do test.fail() \n"
00365         + "do test.resetI()\n"
00366         // while loop in for loop + break in while
00367         + "for (var int j5 = 0; j5 != 100  ; j5 = j5 + 1 ) {\n"
00368         + "   test.resetI()\n"
00369         + "   while (test.increase() != 200) {\n"
00370         + "      if test.i == 50 then break \n"
00371         + "   }\n"
00372         + "   if test.i != 50 then test.fail() \n"
00373         + "}\n"
00374         + "if test.i != 50 then \n"
00375         + "    do test.fail() \n"
00376         + "if j5 != 100 then  {\n"
00377         + "    do test.print(\" j5 is:\" + j5 ) \n"
00378         + "    do test.fail() \n" // 80
00379         + " }\n"
00380         + "do test.resetI()\n"
00381         + "}";
00382     this->doProgram( prog, tc );
00383     this->finishProgram( tc, "x");
00384 }
00385 
00386 BOOST_AUTO_TEST_CASE(testProgramAnd)
00387 {
00388     // see if checking a remote condition works
00389     string prog = string("program x { do test.good()\n")
00390         + " && test.good() \n"
00391         + " && test.good() \n"
00392         + " }";
00393     this->doProgram( prog, tc );
00394     this->finishProgram( tc, "x");
00395 }
00396 
00397 BOOST_AUTO_TEST_CASE(testProgramTry)
00398 {
00399     // see if checking a remote condition works
00400     string prog = string("program progtry { try test.fail()\n")
00401         + "try test.good() \n"
00402         + " && test.fail() \n"
00403         + " && test.good() \n"
00404         + "try test.good() \n"
00405         + " && test.fail() \n"
00406         + "try test.good() \n"
00407         + " && test.fail() \n"
00408         + " && test.fail() catch { \n"
00409         + "  try test.good() \n"
00410         + "   && test.good() \n"
00411         + "   && test.good() catch {\n"
00412         + "      do test.fail()\n"
00413         + "  }\n"
00414         + "}\n"
00415         + "do test.resetI() \n"
00416         + "try test.good() \n"
00417         + " && test.fail() \n"
00418         + " && test.good() catch { \n"
00419         + "  do test.increase()\n"
00420         + "}\n"
00421         + "if test.i == 0 then\n" // check if catch was reached
00422         + "  do test.fail()\n"
00423         + "}";
00424     this->doProgram( prog, tc );
00425     this->finishProgram( tc, "progtry");
00426 }
00427 
00428 BOOST_AUTO_TEST_CASE(testProgramToProgram)
00429 {
00430     // test a program which starts/stops another program.
00431     string prog = string("program y { do test.good() \n")
00432         + " do test.resetI()\n"
00433         + " do test.assert( test.i == 0 )\n"
00434         + "}";
00435 
00436     string prog2 = string("program x {\n")
00437         + " do test.assert( test.i == 0 )\n"
00438         + " do test.increase()\n"
00439         + " do test.assert( test.i == 1 )\n"
00440         + " do y.start()\n"         // test start-stop
00441         + " do yield\n"
00442         + " do test.assert( test.i == 0 )\n"
00443         + " do y.stop()\n"
00444         + " do test.increase()\n"
00445         + " do y.pause()\n"        // test pause-step // 10
00446         + " do yield\n"
00447         + " do test.assert( y.isPaused() )\n"
00448         + " do test.assert( test.i == 1 )\n"
00449         + " do y.step()\n"
00450         + " do yield\n"
00451         + " do test.assert( test.i == 1 )\n"
00452         + " do y.step()\n"
00453         + " do yield\n"
00454         + " do test.assertEqual( test.i, 0 )\n" // if this fails, stepping is broken
00455         + " do y.step()\n"
00456         + " do yield\n"
00457         + " do y.step()\n"         // 20
00458         + " do yield\n"
00459         + " do test.assert( !y.isRunning() )\n"
00460         + "}";
00461 
00462     this->doProgram( prog, tc );
00463     this->doProgram( prog2, tc );
00464     this->finishProgram( tc, "x");
00465     this->finishProgram( tc, "y");
00466 }
00467 
00468 BOOST_AUTO_TEST_CASE(testProgramCallFoo)
00469 {
00470     // see if modifying an attribute works.
00471     string prog = string("export function foo {\n")
00472         + "  do test.assert( tvar_i == +2 ) \n"
00473         + "  do test.assert( tvar_i != tconst_i ) \n"
00474         + "  set tvar_i = +4\n"
00475         + "  do test.assert( tvar_i == +4 ) \n"
00476         + "}\n"
00477         + "program x { \n"
00478         + "do test.assert( tvar_i == -1 ) \n"
00479         + "do test.assert( tvar_i == tconst_i ) \n"
00480         + "set tvar_i = +2\n"
00481         + "do test.assert( tvar_i == +2 )\n"
00482         + "call foo()\n"
00483         + "}";
00484     this->doProgram( prog, tc );
00485     Attribute<int> i = tc->provides()->getAttribute("tvar_i");
00486     BOOST_REQUIRE_EQUAL( 4, i.get() );
00487     this->finishProgram( tc, "x");
00488 }
00489 
00490 BOOST_AUTO_TEST_CASE(testProgramDoFoo)
00491 {
00492     // see if modifying an attribute works.
00493     string prog = string("export function foo {\n")
00494         + "  do test.assert( tvar_i == +2 ) \n"
00495         + "  do test.assert( tvar_i != tconst_i ) \n"
00496         + "  set tvar_i = +4\n"
00497         + "  do test.assert( tvar_i == +4 ) \n"
00498         + "}\n"
00499         + "program x { \n"
00500         + "do test.assert( tvar_i == -1 ) \n"
00501         + "do test.assert( tvar_i == tconst_i ) \n"
00502         + "set tvar_i = +2\n"
00503         + "do test.assert( tvar_i == +2 )\n"
00504         + "do foo()\n"
00505         + "}";
00506     this->doProgram( prog, tc );
00507     Attribute<int> i = tc->provides()->getAttribute("tvar_i");
00508     BOOST_REQUIRE_EQUAL( 4, i.get() );
00509     this->finishProgram( tc, "x");
00510 }
00511 
00512 BOOST_AUTO_TEST_CASE(testSend)
00513 {
00514     // see if modifying an attribute works.
00515     string prog = string("")
00516         + "program x { \n"
00517         + "test.assertEqual( test.i, 0 )\n"
00518         + "test.increaseCmd.send() \n"
00519         + "yield \n"
00520         + "test.assertEqual( test.i, 1 )\n"
00521         + "var SendHandle sh\n"
00522         + "set sh = test.increaseCmd.send()\n"
00523         + "var int r = 0\n"
00524         //+ "sh.collect(r)\n" // hangs
00525         + "while (sh.collectIfDone(r) != SendSuccess)\n"
00526         + "yield \n"
00527         + "test.assertEqual( r , 2 )\n"
00528         + "set sh = test.increaseCmd.send()\n"
00529         //+ "sh.collect(tvar_i)\n" // hangs
00530         + "while (sh.collectIfDone(tvar_i) != SendSuccess)\n"
00531         + "yield \n"
00532         + "test.assertEqual( tvar_i, 3 )\n" // i is 3 but r isn't.
00533         + "}";
00534     this->doProgram( prog, tc );
00535     BOOST_REQUIRE_EQUAL( i, 3 );
00536     BOOST_REQUIRE_EQUAL( var_i, 3 );
00537     this->finishProgram( tc, "x");
00538 }
00539 
00540 BOOST_AUTO_TEST_SUITE_END()
00541 
00542 void ProgramTest::doProgram( const std::string& prog, TaskContext* tc, bool test )
00543 {
00544     BOOST_CHECK( tc->engine() );
00545 
00546     Parser::ParsedPrograms pg_list;
00547     try {
00548         pg_list = parser.parseProgram( prog, tc );
00549     }
00550     catch( const file_parse_exception& exc )
00551         {
00552             BOOST_REQUIRE_MESSAGE( false, exc.what() );
00553         }
00554     if ( pg_list.empty() )
00555         {
00556             BOOST_REQUIRE_MESSAGE( false, "No program could be found by the parser." );
00557         }
00558     ProgramInterfacePtr pi = *pg_list.begin();
00559 
00560     sa->loadProgram( pi );
00561     BOOST_CHECK( pi->start() );
00562     BOOST_CHECK( SimulationThread::Instance()->run(1000) );
00563 
00564     if (test ) {
00565         stringstream errormsg;
00566         errormsg << " on line " << pi->getLineNumber() <<"."<<endl;
00567         BOOST_REQUIRE_MESSAGE( pi->getStatus() != ProgramInterface::Status::error , "Runtime error encountered" + errormsg.str());
00568         BOOST_CHECK_MESSAGE( pi->getStatus() == ProgramInterface::Status::stopped , "Program stalled " + errormsg.str());
00569 
00570         // Xtra test, only do it if all previous went ok :
00571         loopProgram( pi );
00572     }
00573 }
00574 
00575 void ProgramTest::loopProgram( ProgramInterfacePtr f)
00576 {
00577     //std::cerr <<std::endl<< "Looping " << f->getName();
00578     // especially handy for performance testing :
00579     // This bypasses the processor however, does not
00580     // measure its performance.
00581     int loops = 100;
00582     f->reset();
00583     while ( loops-- != 0 ) {
00584         while ( !f->isStopped() && !f->inError() )
00585             f->execute();
00586         f->reset();
00587         //std::cerr << ".";
00588     }
00589 }
00590 
00591 
00592 void ProgramTest::finishProgram(TaskContext* tc, std::string prog_name)
00593 {
00594     BOOST_REQUIRE( sa->getProgram(prog_name) );
00595     BOOST_CHECK( sa->getProgram( prog_name )->stop() );
00596     BOOST_CHECK( sa->unloadProgram( prog_name ) );
00597 
00598 }


rtt
Author(s): RTT Developers
autogenerated on Sat Jun 8 2019 18:46:17