$search
00001 /*************************************************************************** 00002 tag: The SourceWorks Tue Sep 7 00:54:57 CEST 2010 scripting_test.cpp 00003 00004 scripting_test.cpp - description 00005 ------------------- 00006 begin : Tue September 07 2010 00007 copyright : (C) 2010 The SourceWorks 00008 email : peter@thesourceworks.com 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 #include "unit.hpp" 00020 00021 #include "operations_fixture.hpp" 00022 #include <scripting/Scripting.hpp> 00023 #include <scripting/ScriptingService.hpp> 00024 #include <extras/SequentialActivity.hpp> 00025 #include <plugin/PluginLoader.hpp> 00026 #include <scripting/Parser.hpp> 00027 #include <internal/GlobalService.hpp> 00028 00029 00030 using namespace std; 00031 using namespace boost; 00032 using namespace RTT; 00033 using namespace RTT::detail; 00034 00035 #include <boost/shared_ptr.hpp> 00036 00037 00038 // Registers the fixture into the 'registry' 00039 BOOST_FIXTURE_TEST_SUITE( ScriptingTestSuite, OperationsFixture ) 00040 00041 00042 BOOST_AUTO_TEST_CASE(TestGetProvider) 00043 { 00044 //ScriptingService* sa = new ScriptingService( tc ); // done by TC or plugin. 00045 00046 PluginLoader::Instance()->loadService("scripting",tc); 00047 00048 // We use a sequential activity in order to force execution on trigger(). 00049 tc->stop(); 00050 BOOST_CHECK( tc->setActivity( new SequentialActivity() ) ); 00051 tc->start(); 00052 00053 boost::shared_ptr<Scripting> sc = tc->getProvider<Scripting>("scripting"); 00054 BOOST_REQUIRE( sc ); 00055 BOOST_CHECK ( sc->ready() ); 00056 bool r; 00057 r = sc->loadProgramText("program Foo { do test.assert(true); set ret = 10.0; }"); 00058 BOOST_REQUIRE( r ); 00059 BOOST_CHECK( sc->hasProgram("Foo") ); 00060 BOOST_REQUIRE( sc->startProgram("Foo") ); 00061 BOOST_CHECK( sc->isProgramRunning("Foo") ); 00062 00063 // executes our script in the EE: 00064 tc->getActivity()->trigger(); 00065 00066 // test results: 00067 BOOST_CHECK( sc->isProgramRunning("Foo") == false ); 00068 BOOST_CHECK( sc->inProgramError("Foo") == false ); 00069 BOOST_CHECK( ret == 10.0 ); 00070 00071 } 00072 00073 BOOST_AUTO_TEST_CASE(TestScriptingParser) 00074 { 00075 PluginLoader::Instance()->loadService("scripting",tc); 00076 00077 // We use a sequential activity in order to force execution on trigger(). 00078 tc->stop(); 00079 BOOST_CHECK( tc->setActivity( new SequentialActivity() ) ); 00080 tc->start(); 00081 00082 boost::shared_ptr<Scripting> sc = tc->getProvider<Scripting>("scripting"); 00083 BOOST_REQUIRE( sc ); 00084 BOOST_CHECK ( sc->ready() ); 00085 bool r; 00086 00087 // test plain statements: 00088 string statements=";;test.increase()\n;;;\ntest.increase()"; // trailing newline is optional 00089 r = sc->eval(statements); 00090 BOOST_CHECK( r ); 00091 BOOST_CHECK_EQUAL( i, 1); 00092 00093 // test variable decls: 00094 statements="var int i = 0; var int y,z=10; test.i = z"; 00095 r = sc->eval(statements); 00096 BOOST_CHECK( r ); 00097 BOOST_CHECK_EQUAL( i, 10); 00098 00099 // test if statement: 00100 statements="var int x=1,y=2; if 3 == 8 then test.i = x else test.i = y"; 00101 r = sc->eval(statements); 00102 BOOST_CHECK( r ); 00103 BOOST_CHECK_EQUAL( i, 2); 00104 00105 // test while statement: 00106 statements="var int x=1,y=2; while x != y { test.i = 3; x = y; }"; 00107 r = sc->eval(statements); 00108 BOOST_CHECK( r ); 00109 BOOST_CHECK_EQUAL( i, 3); 00110 00111 // test while name clash: 00112 statements="var int whilex, whiley\n whilex = 1; whiley=2\n while whilex != whiley { test.i = 3; whilex = whiley; }"; 00113 r = sc->eval(statements); 00114 BOOST_CHECK( r ); 00115 BOOST_CHECK_EQUAL( i, 3); 00116 00117 // test for statement: 00118 statements="var int x=10,y=20; for( x = 0; x != y; x = x + 1) { test.i = x; }"; 00119 r = sc->eval(statements); 00120 BOOST_CHECK( r ); 00121 BOOST_CHECK_EQUAL( i, 19); 00122 00123 // test for name clash: 00124 statements="var int forx,fory\n forx=10; fory=20; for( forx = 0; forx != fory; forx = forx + 1) { test.i = forx; }"; 00125 r = sc->eval(statements); 00126 BOOST_CHECK( r ); 00127 BOOST_CHECK_EQUAL( i, 19); 00128 00129 // test function + a statement that uses that function: 00130 statements = "export function adder(int a, int b) { test.i = a + b; }\n adder(5,6)\n"; 00131 r = sc->eval(statements); 00132 BOOST_CHECK( r ); 00133 BOOST_CHECK_EQUAL( i, 11); 00134 statements = "export void adder2(int a, int b) { test.i = a + b; }\n adder2(7,8)\n"; 00135 r = sc->eval(statements); 00136 BOOST_CHECK( r ); 00137 BOOST_CHECK_EQUAL( i, 15); 00138 statements = "export int adder3(int a, int b) { return a + b; }\n test.i = adder3(6,10)\n"; 00139 r = sc->eval(statements); 00140 BOOST_CHECK( r ); 00141 BOOST_CHECK_EQUAL( i, 16); 00142 00143 // test program + a statement that starts that program and waits for the result. 00144 statements = "program rt_script { test.i = 3-9; }\n rt_script.start();;;; while( rt_script.isRunning() ) { trigger(); yield; }\n"; 00145 r = sc->eval(statements); 00146 BOOST_CHECK( r ); 00147 BOOST_CHECK_EQUAL( sc->getProgramStatus("rt_script"), ProgramInterface::Status::stopped ); 00148 BOOST_CHECK_EQUAL( i, -6); 00149 00150 // test state machine + a statement that starts that SM and waits for the result. 00151 statements = "StateMachine RTState { initial state init { entry { test.i = 0;} transitions { select fini; } } final state fini { entry { test.i = test.i - 2; } } }; RootMachine RTState rt_state; rt_state.activate(); rt_state.start(); while( !rt_state.inFinalState() ) { trigger(); yield; }\n"; 00152 r = sc->eval(statements); 00153 BOOST_CHECK( r ); 00154 BOOST_CHECK_EQUAL( sc->getStateMachineState("rt_state"), "fini" ); 00155 BOOST_CHECK_EQUAL( i, -2); 00156 } 00157 00158 BOOST_AUTO_TEST_CASE(TestScriptingFunction) 00159 { 00160 PluginLoader::Instance()->loadService("scripting",tc); 00161 00162 // We use a sequential activity in order to force execution on trigger(). 00163 tc->stop(); 00164 BOOST_CHECK( tc->setActivity( new SequentialActivity() ) ); 00165 tc->start(); 00166 00167 boost::shared_ptr<Scripting> sc = tc->getProvider<Scripting>("scripting"); 00168 BOOST_REQUIRE( sc ); 00169 BOOST_CHECK ( sc->ready() ); 00170 bool r; 00171 00172 // set test counter to zero: 00173 i = 0; 00174 00175 // define a function (added to scripting interface): 00176 string statements="void func1(void) { test.increase(); }\n"; 00177 r = sc->eval(statements); 00178 BOOST_CHECK( r ); 00179 BOOST_CHECK_EQUAL( i, 0); 00180 BOOST_CHECK( tc->provides("scripting")->hasMember("func1")); 00181 00182 // export a function: 00183 statements="export void efunc1(void) { test.increase(); }\n"; 00184 r = sc->eval(statements); 00185 BOOST_CHECK( r ); 00186 BOOST_CHECK_EQUAL( i, 0); 00187 BOOST_CHECK( tc->provides()->hasMember("efunc1")); 00188 00189 // local function: 00190 statements="void lfunc1(void) { test.increase(); }\n"; 00191 r = sc->eval(statements); 00192 BOOST_CHECK( r ); 00193 BOOST_CHECK_EQUAL( i, 0); 00194 BOOST_CHECK( tc->provides("scripting")->hasMember("lfunc1")); 00195 00196 // global function: 00197 statements="global void gfunc1(void) { test.increase(); }\n"; 00198 r = sc->eval(statements); 00199 BOOST_CHECK( r ); 00200 BOOST_CHECK_EQUAL( i, 0); 00201 BOOST_CHECK( GlobalService::Instance()->provides()->hasMember("gfunc1")); 00202 00203 // invoke a function: 00204 statements="func1()\n"; 00205 r = sc->eval(statements); 00206 BOOST_CHECK( r ); 00207 BOOST_CHECK_EQUAL( i, 1); 00208 00209 // invoke an exported function: 00210 statements="efunc1()\n"; 00211 r = sc->eval(statements); 00212 BOOST_CHECK( r ); 00213 BOOST_CHECK_EQUAL( i, 2); 00214 00215 // invoke a global function: 00216 statements="gfunc1()\n"; 00217 r = sc->eval(statements); 00218 BOOST_CHECK( r ); 00219 BOOST_CHECK_EQUAL( i, 3); 00220 00221 // invoke a local function: 00222 statements="lfunc1()\n"; 00223 r = sc->eval(statements); 00224 BOOST_CHECK( r ); 00225 BOOST_CHECK_EQUAL( i, 4); 00226 00227 // call a function: 00228 statements="call func1()\n"; 00229 r = sc->eval(statements); 00230 BOOST_CHECK( !r ); 00231 BOOST_CHECK_EQUAL( i, 4); 00232 00233 // call an exported function: 00234 statements="call efunc1()\n"; 00235 r = sc->eval(statements); 00236 BOOST_CHECK( !r ); 00237 BOOST_CHECK_EQUAL( i, 4); 00238 00239 // RE-define a function (added to scripting interface): 00240 statements="void func1(void) { test.increase(); test.increase(); }\n"; 00241 r = sc->eval(statements); 00242 BOOST_CHECK( r ); 00243 BOOST_CHECK_EQUAL( i, 4); 00244 BOOST_CHECK( tc->provides("scripting")->hasMember("func1")); 00245 00246 statements="func1()\n"; 00247 r = sc->eval(statements); 00248 BOOST_CHECK( r ); 00249 BOOST_CHECK_EQUAL( i, 6); 00250 00251 // RE-export a function: 00252 statements="export void efunc1(void) { test.increase(); test.increase();}\n"; 00253 r = sc->eval(statements); 00254 BOOST_CHECK( r ); 00255 BOOST_CHECK_EQUAL( i, 6); 00256 BOOST_CHECK( tc->provides()->hasMember("efunc1")); 00257 00258 statements="efunc1()\n"; 00259 r = sc->eval(statements); 00260 BOOST_CHECK( r ); 00261 BOOST_CHECK_EQUAL( i, 8); 00262 00263 // RE-global a function: 00264 statements="global void gfunc1(void) { test.increase(); test.increase();}\n"; 00265 r = sc->eval(statements); 00266 BOOST_CHECK( r ); 00267 BOOST_CHECK_EQUAL( i, 8); 00268 BOOST_CHECK( GlobalService::Instance()->provides()->hasMember("gfunc1")); 00269 00270 statements="gfunc1()\n"; 00271 r = sc->eval(statements); 00272 BOOST_CHECK( r ); 00273 BOOST_CHECK_EQUAL( i, 10); 00274 00275 00276 } 00277 00278 BOOST_AUTO_TEST_SUITE_END()