$search
00001 /*************************************************************************** 00002 tag: Peter Soetens Mon Jun 26 13:26:02 CEST 2006 generictask_test.cpp 00003 00004 generictask_test.cpp - description 00005 ------------------- 00006 begin : Mon June 26 2006 00007 copyright : (C) 2006 Peter Soetens 00008 email : peter.soetens@fmtc.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 "generictask_test.hpp" 00022 #include <scripting/FunctionGraph.hpp> 00023 #include <OperationCaller.hpp> 00024 #include <Service.hpp> 00025 #include <internal/RemoteOperationCaller.hpp> 00026 00027 #include <extras/SimulationActivity.hpp> 00028 #include <extras/SimulationThread.hpp> 00029 00030 #include <boost/function_types/function_type.hpp> 00031 00032 #include <rtt-config.h> 00033 #include <Service.hpp> 00034 00035 using namespace std; 00036 00037 void 00038 Generic_TaskTest::setUp() 00039 { 00040 tc = new TaskContext( "root" ); 00041 tc->addService( this->createOperationCallerFactory() ); 00042 tsim = new SimulationActivity(0.001, tc->engine() ); 00043 } 00044 00045 00046 void 00047 Generic_TaskTest::tearDown() 00048 { 00049 // if ( tc->getPeer("programs") ) 00050 // delete tc->getPeer("programs"); 00051 tsim->stop(); 00052 SimulationThread::Instance()->stop(); 00053 delete tc; 00054 delete tsim; 00055 } 00056 00057 bool Generic_TaskTest::assertBool( bool b) { 00058 return b; 00059 } 00060 00061 Service* Generic_TaskTest::createOperationCallerFactory() 00062 { 00063 Service* to = new Service("methods"); 00064 00065 to->addOperation("assert", &Generic_TaskTest::assertBool, this).doc("assert").arg("b", "bd"); 00066 00067 to->addOperation("m0", &Generic_TaskTest::m0, this).doc("M0"); 00068 to->addOperation("m1", &Generic_TaskTest::m1, this).doc("M1").arg("a", "ad"); 00069 to->addOperation("m2", &Generic_TaskTest::m2, this).doc("M2").arg("a", "ad").arg("a", "ad"); 00070 to->addOperation("m3", &Generic_TaskTest::m3, this).doc("M3").arg("a", "ad").arg("a", "ad").arg("a", "ad"); 00071 to->addOperation("m4", &Generic_TaskTest::m4, this).doc("M4").arg("a", "ad").arg("a", "ad").arg("a", "ad").arg("a", "ad"); 00072 return to; 00073 } 00074 00075 // Registers the fixture into the 'registry' 00076 BOOST_FIXTURE_TEST_SUITE( Generic_TaskTestSuite, Generic_TaskTest ) 00077 00078 00079 BOOST_AUTO_TEST_CASE(testRemoteOperationCaller) 00080 { 00081 Operation<double(void)> m0; 00082 boost::shared_ptr<ActionInterface> implementation( new detail::RemoteOperationCaller<double(void)>(tc->provides("methods"),"m0") ); 00083 m0 = implementation; 00084 BOOST_CHECK( m0.ready() ); 00085 00086 Operation<double(int)> m1; 00087 implementation.reset( new detail::RemoteOperationCaller<double(int)>(tc->provides("methods"),"m1") ); 00088 m1 = implementation; 00089 BOOST_CHECK( m1.ready() ); 00090 00091 BOOST_CHECK_EQUAL( -2.0, m1(1) ); 00092 BOOST_CHECK_EQUAL( -1.0, m0() ); 00093 } 00094 00095 BOOST_AUTO_TEST_CASE(testOperationCallersC) 00096 { 00097 OperationCallerC mc; 00098 double r = 0.0; 00099 mc = tc->provides("methods")->create("m0").ret( r ); 00100 BOOST_CHECK( mc.execute() ); 00101 BOOST_CHECK( r == -1.0 ); 00102 00103 mc = tc->provides("methods")->create("m2").argC(1).argC(1.0).ret( r ); 00104 BOOST_CHECK( mc.execute() ); 00105 BOOST_CHECK( r == -3.0 ); 00106 00107 mc = tc->provides("methods")->create("m3").ret( r ).argC(1).argC(1.0).argC(true); 00108 BOOST_CHECK( mc.execute() ); 00109 BOOST_CHECK( r == -4.0 ); 00110 00111 #if 0 00112 +" set r = methods.m0()\n" 00113 +" do methods.assert( r == -1.0 )\n" 00114 +" set r = methods.m1(1)\n" 00115 +" do methods.assert( r == -2.0 )\n" 00116 +" set r = methods.m2(1, 1.0)\n" 00117 +" do methods.assert( r == -3.0 )\n" 00118 +" set r = methods.m3(1, 1.0, true)\n" 00119 +" do methods.assert( r == -4.0 )\n" 00120 +" set r = methods.m4(1, 1.0, true, \"hello\")\n" 00121 +" do methods.assert( r == -5.0 )\n" 00122 #endif 00123 } 00124 00125 BOOST_AUTO_TEST_CASE(testOperationCaller) 00126 { 00127 Operation<double(void)> m0("m0", &Generic_TaskTest::m0, this); 00128 Operation<double(int)> m1("m1", &Generic_TaskTest::m1, this); 00129 Operation<double(int,double)> m2("m2", &Generic_TaskTest::m2, this); 00130 Operation<double(int,double,bool)> m3("m3", &Generic_TaskTest::m3, this); 00131 Operation<double(int,double,bool,std::string)> m4("m4", &Generic_TaskTest::m4, this); 00132 00133 BOOST_CHECK_EQUAL( -1.0, m0() ); 00134 BOOST_CHECK_EQUAL( -2.0, m1(1) ); 00135 BOOST_CHECK_EQUAL( -3.0, m2(1, 2.0) ); 00136 BOOST_CHECK_EQUAL( -4.0, m3(1, 2.0, false) ); 00137 BOOST_CHECK_EQUAL( -5.0, m4(1, 2.0, false,"hello") ); 00138 } 00139 00140 BOOST_AUTO_TEST_CASE(testOperationCallerFactory) 00141 { 00142 // Test the addition of 'simple' methods to the operation interface, 00143 // and retrieving it back in a new OperationCaller object. 00144 00145 Operation<double(void)> m0("m0", &Generic_TaskTest::m0, this); 00146 Operation<double(int)> m1("m1", &Generic_TaskTest::m1, this); 00147 Operation<double(int,double)> m2("m2", &Generic_TaskTest::m2, this); 00148 00149 Service to("task"); 00150 00151 BOOST_CHECK( to.addOperationCaller(&m0) ); 00152 BOOST_CHECK( ! to.addOperationCaller(&m0) ); 00153 BOOST_CHECK( to.addOperationCaller(&m1) ); 00154 BOOST_CHECK( to.addOperationCaller(&m2) ); 00155 00156 // test constructor 00157 Operation<double(void)> mm0 = to.getOperationCaller<double(void)>("m0"); 00158 BOOST_CHECK( mm0.getOperationCallerImpl() ); 00159 BOOST_CHECK( mm0.ready() ); 00160 00161 // test operator=() 00162 Operation<double(int)> mm1; 00163 mm1 = to.getOperationCaller<double(int)>("m1"); 00164 BOOST_CHECK( mm1.getOperationCallerImpl() ); 00165 BOOST_CHECK( mm1.ready() ); 00166 00167 Operation<double(int,double)> mm2 = to.getOperationCaller<double(int,double)>("m2"); 00168 BOOST_CHECK( mm2.getOperationCallerImpl() ); 00169 BOOST_CHECK( mm2.ready() ); 00170 00171 // start the activity, such that methods are accepted. 00172 BOOST_CHECK( tsim->start()) ; 00173 // execute methods and check status: 00174 BOOST_CHECK_EQUAL( -1.0, mm0() ); 00175 00176 BOOST_CHECK_EQUAL( -2.0, mm1(1) ); 00177 BOOST_CHECK_EQUAL( -3.0, mm2(1, 2.0) ); 00178 00179 // test error cases: 00180 // Add uninitialised method: 00181 Operation<void(void)> mvoid; 00182 BOOST_CHECK(to.addOperationCaller( &mvoid ) == false); 00183 mvoid = Operation<void(void)>("voidm"); 00184 BOOST_CHECK(to.addOperationCaller( &mvoid ) == false); 00185 00186 // wrong type 1: 00187 mvoid = to.getOperationCaller<void(void)>("m1"); 00188 BOOST_CHECK( mvoid.ready() == false ); 00189 // wrong type 2: 00190 mvoid = to.getOperationCaller<void(bool)>("m1"); 00191 // wrong type 3: 00192 mvoid = to.getOperationCaller<double(void)>("m0"); 00193 BOOST_CHECK( mvoid.ready() == false ); 00194 // non existing 00195 mvoid = to.getOperationCaller<void(void)>("voidm"); 00196 BOOST_CHECK( mvoid.ready() == false ); 00197 00198 // this line may not crash: 00199 mvoid(); 00200 00201 } 00202 00203 BOOST_AUTO_TEST_CASE(testCROperationCaller) 00204 { 00205 this->ret = -3.3; 00206 00207 Operation<double&(void)> m0r("m0r", &Generic_TaskTest::m0r, this); 00208 Operation<const double&(void)> m0cr("m0cr", &Generic_TaskTest::m0cr, this); 00209 00210 Operation<double(double&)> m1r("m1r", &Generic_TaskTest::m1r, this); 00211 Operation<double(const double&)> m1cr("m1cr", &Generic_TaskTest::m1cr, this); 00212 00213 BOOST_CHECK_EQUAL( -3.3, m0r() ); 00214 BOOST_CHECK_EQUAL( -3.3, m0cr() ); 00215 00216 double value = 5.3; 00217 BOOST_CHECK_EQUAL( 5.3*2, m1r(value) ); 00218 BOOST_CHECK_EQUAL( 5.3*2, value ); 00219 BOOST_CHECK_EQUAL( 5.3, m1cr(5.3) ); 00220 } 00221 00222 00223 BOOST_AUTO_TEST_CASE(testOperationCallerFromDS) 00224 { 00225 Service to("task"); 00226 00227 Operation<double(void)> m0("m0", &Generic_TaskTest::m0, this); 00228 Operation<double(int)> m1("m1", &Generic_TaskTest::m1, this); 00229 Operation<double(int,double)> m2("m2", &Generic_TaskTest::m2, this); 00230 Operation<double(int,double,bool)> m3("m3", &Generic_TaskTest::m3, this); 00231 Operation<double(int,double,bool,std::string)> m4("m4", &Generic_TaskTest::m4, this); 00232 00233 to.addOperation( &m0 ).doc("desc"); 00234 to.addOperation( &m1 ).doc("desc").arg("a1", "d1"); 00235 to.addOperation( &m2 ).doc("desc").arg("a1", "d1").arg("a2", "d2"); 00236 to.addOperation( &m3 ).doc("desc").arg("a1", "d1").arg("a2", "d2").arg("a3", "d3"); 00237 to.addOperation( &m4 ).doc("desc").arg("a1", "d1").arg("a2", "d2").arg("a3", "d3").arg("a4", "d4"); 00238 00239 double ret; 00240 OperationCallerC mc0( to.methods(), "m0"); 00241 mc0.ret(ret); 00242 OperationCallerC mc1( to.methods(), "m1"); 00243 mc1.argC(1).ret(ret); 00244 OperationCallerC mc2( to.methods(), "m2"); 00245 mc2.argC(1).argC(2.0).ret(ret); 00246 OperationCallerC mc3( to.methods(), "m3"); 00247 mc3.argC(1).argC(2.0).argC(false).ret(ret); 00248 OperationCallerC mc4( to.methods(), "m4"); 00249 mc4.argC(1).argC(2.0).argC(false).argC(std::string("hello")).ret(ret); 00250 00251 BOOST_CHECK( mc0.execute() ); 00252 BOOST_CHECK_EQUAL(-1.0, ret); 00253 BOOST_CHECK( mc1.execute() ); 00254 BOOST_CHECK_EQUAL(-2.0, ret); 00255 BOOST_CHECK( mc2.execute() ); 00256 BOOST_CHECK_EQUAL(-3.0, ret); 00257 BOOST_CHECK( mc3.execute() ); 00258 BOOST_CHECK_EQUAL(-4.0, ret); 00259 BOOST_CHECK( mc4.execute() ); 00260 BOOST_CHECK_EQUAL(-5.0, ret); 00261 } 00262 00263 BOOST_AUTO_TEST_CASE(testDSOperationCaller) 00264 { 00265 Service to("task"); 00266 00267 // A method of which the first argument type is a pointer to the object 00268 // on which it must be invoked. The pointer is internally stored as a weak_ptr, 00269 // thus the object must be stored in a shared_ptr, in a DataSource. Scripting 00270 // requires this for copying state machines. 00271 00272 Operation<double(Generic_TaskTest*)> meth0("m0", 00273 &Generic_TaskTest::m0); 00274 00275 method_ds("m0", &Generic_TaskTest::m0); 00276 00277 Operation<double(Generic_TaskTest*,int)> meth1("m1", 00278 &Generic_TaskTest::m1); 00279 00280 method_ds("m1", &Generic_TaskTest::m1); 00281 method_ds("ms",&Generic_TaskTest::comstr ); 00282 00283 boost::shared_ptr<Generic_TaskTest> ptr( new Generic_TaskTest() ); 00284 ValueDataSource<boost::weak_ptr<Generic_TaskTest> >::shared_ptr wp = new ValueDataSource<boost::weak_ptr<Generic_TaskTest> >( ptr ); 00285 BOOST_CHECK( to.addOperationCallerDS( wp.get(), meth0, "desc" ) ); 00286 BOOST_CHECK( to.addOperationCallerDS( wp.get(), meth1, "desc", "a1", "d1" ) ); 00287 00288 // this actually works ! the method will detect the deleted pointer. 00289 //ptr.reset(); 00290 00291 BOOST_CHECK( tsim->start()) ; 00292 00293 double ret; 00294 OperationCallerC c0 = to.create("m0").ret(ret); 00295 BOOST_CHECK( c0.execute() ); 00296 BOOST_CHECK_EQUAL( -1.0, ret ); 00297 OperationCallerC c1 = to.create("m1").argC(1).ret(ret); 00298 BOOST_CHECK( c1.execute() ); 00299 BOOST_CHECK_EQUAL( -2.0, ret ); 00300 00301 BOOST_CHECK( tsim->stop()) ; 00302 00303 } 00304 00305 BOOST_AUTO_TEST_CASE(testAddOperationCaller) 00306 { 00307 Operation<double(void)> m0 = method("m0", &Generic_TaskTest::m0, this); 00308 00309 Operation<double(int)> m1 = method("m1", &Generic_TaskTest::m1, this); 00310 Operation<double(int,double)> m2 = method("m2", &Generic_TaskTest::m2, this); 00311 Operation<double(int,double,bool)> m3 = method("m3", &Generic_TaskTest::m3, this); 00312 Operation<double(int,double,bool,std::string)> m4 = method("m4", &Generic_TaskTest::m4, this); 00313 00314 BOOST_CHECK_EQUAL( -1.0, m0() ); 00315 BOOST_CHECK_EQUAL( -2.0, m1(1) ); 00316 BOOST_CHECK_EQUAL( -3.0, m2(1, 2.0) ); 00317 BOOST_CHECK_EQUAL( -4.0, m3(1, 2.0, false) ); 00318 BOOST_CHECK_EQUAL( -5.0, m4(1, 2.0, false,"hello") ); 00319 } 00320 00321 BOOST_AUTO_TEST_SUITE_END()