$search
00001 /*************************************************************************** 00002 tag: The SourceWorks Tue Sep 7 00:54:57 CEST 2010 operation_test.cpp 00003 00004 operation_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 00020 #include "unit.hpp" 00021 00022 #include <rtt-fwd.hpp> 00023 #include <rtt/Operation.hpp> 00024 #include <rtt/Service.hpp> 00025 #include <rtt/OperationCaller.hpp> 00026 #include <rtt/TaskContext.hpp> 00027 00028 using namespace std; 00029 using namespace RTT::detail; 00030 using namespace RTT; 00031 00037 class OperationTest 00038 { 00039 public: 00040 OperationTest() : tc("TC"), 00041 op0r("op0r"), op0cr("op0cr"), op1r("op1r"), op1cr("op1cr"), op0("op0"), op1("op1"), op2("op2"), op3("op3"), op4("op4"), op5("op5"), 00042 opc0r("op0r"), opc0cr("op0cr"), opc1r("op1r"), opc1cr("op1cr"), opc0("op0"), opc1("op1"), opc2("op2"), opc3("op3"), opc4("op4"), opc5("op5") 00043 { 00044 00045 tc.provides()->addOperation("op", &OperationTest::func, this); 00046 tc.provides()->addOperation("op0", &OperationTest::func0, this); 00047 tc.provides()->addOperation("op1", &OperationTest::func1, this); 00048 tc.provides()->addOperation("op2", &OperationTest::func2, this); 00049 tc.provides()->addOperation("op3", &OperationTest::func3, this); 00050 tc.provides()->addOperation("op4", &OperationTest::func4, this); 00051 tc.provides()->addOperation("op5", &OperationTest::func5, this); 00052 BOOST_CHECK( tc.provides()->getOperation("op0") ); 00053 BOOST_CHECK( tc.provides()->getOperation("op1") ); 00054 BOOST_CHECK( tc.provides()->getOperation("op2") ); 00055 BOOST_CHECK( tc.provides()->getOperation("op3") ); 00056 BOOST_CHECK( tc.provides()->getOperation("op4") ); 00057 BOOST_CHECK( tc.provides()->getOperation("op5") ); 00058 00059 tc.provides()->addOperation("op0r", &OperationTest::func0r, this); 00060 00061 tc.provides()->addOperation("op1r", &OperationTest::func1r, this); 00062 tc.provides()->addOperation("op1cr", &OperationTest::func1cr, this); 00063 } 00064 00065 ~OperationTest() { 00066 00067 } 00068 double ret; 00069 double& func0r(void) { return ret; } 00070 const double& func0cr(void) { return ret; } 00071 00072 double func1r(double& a) { a = 2*a; return a; } 00073 double func1cr(const double& a) { return a; } 00074 00075 // plain argument tests: 00076 void func() { return; } 00077 double func0() { return 1.0; } 00078 double func1(int i) { return 2.0; } 00079 double func2(int i, double d) { return 3.0; } 00080 double func3(int i, double d, bool c) { return 4.0; } 00081 double func4(int i, double d, bool c, std::string s) { return 5.0; } 00082 double func5(int i, double d, bool c, std::string s, float f) { return 6.0; } 00083 00084 // The return values of signals are intentionally distinct than these above. 00085 double sig0() { return sig=-1.0; } 00086 double sig1(int i) { return (sig=-2.0); } 00087 double sig2(int i, double d) { return sig=-3.0; } 00088 double sig3(int i, double d, bool c) { return (sig=-4.0); } 00089 double sig4(int i, double d, bool c, std::string s) { return sig=-5.0; } 00090 double sig5(int i, double d, bool c, std::string s, float f) { return sig=-6.0; } 00091 00092 static double freefunc0(void) { return 1.0; } 00093 static double freefunc1(int i) { return 2.0; } 00094 00095 TaskContext tc; 00096 00097 // check value for signals 00098 double sig; 00099 00100 Operation<double&(void)> op0r; 00101 Operation<const double&(void)> op0cr; 00102 Operation<double(double&)> op1r; 00103 Operation<double&(const double&)> op1cr; 00104 Operation<double(void)> op0; 00105 Operation<double(int)> op1; 00106 Operation<double(int,double)> op2; 00107 Operation<double(int,double,bool)> op3; 00108 Operation<double(int,double,bool, std::string)> op4; 00109 Operation<double(int,double,bool, std::string, float)> op5; 00110 00111 OperationCaller<double&(void)> opc0r; 00112 OperationCaller<const double&(void)> opc0cr; 00113 OperationCaller<double(double&)> opc1r; 00114 OperationCaller<double&(const double&)> opc1cr; 00115 OperationCaller<double(void)> opc0; 00116 OperationCaller<double(int)> opc1; 00117 OperationCaller<double(int,double)> opc2; 00118 OperationCaller<double(int,double,bool)> opc3; 00119 OperationCaller<double(int,double,bool, std::string)> opc4; 00120 OperationCaller<double(int,double,bool, std::string, float)> opc5; 00121 }; 00122 00123 // Registers the fixture into the 'registry' 00124 BOOST_FIXTURE_TEST_SUITE( OperationTestSuite, OperationTest ) 00125 00126 // Test default properties of an operation. 00127 BOOST_AUTO_TEST_CASE( testOperationCreate ) 00128 { 00129 // name 00130 BOOST_CHECK( op0.getName() == "op0" ); 00131 // not in interface, not ready. 00132 BOOST_CHECK( op0.ready() == false); 00133 00134 } 00135 00136 // Test adding and calling an operation (internal API) 00137 BOOST_AUTO_TEST_CASE( testOperationCall ) 00138 { 00139 Service::shared_ptr s = boost::make_shared<Service>("Service"); 00140 00141 tc.provides()->addService( s ); 00142 00143 op0.calls( &OperationTest::func0, this); 00144 op1.calls( &OperationTest::func1, this); 00145 op2.calls( &OperationTest::func2, this); 00146 op3.calls( &OperationTest::func3, this); 00147 op4.calls( &OperationTest::func4, this); 00148 op5.calls( &OperationTest::func5, this); 00149 00150 s->addOperation( op0 ); 00151 s->addOperation( op1 ); 00152 s->addOperation( op2 ); 00153 s->addOperation( op3 ); 00154 s->addOperation( op4 ); 00155 s->addOperation( op5 ); 00156 00157 // Test calling an operation using a OperationCaller. 00158 OperationCaller<double(void)> m0("op0"); 00159 BOOST_CHECK( m0.ready() == false ); 00160 m0 = op0.getImplementation(); 00161 BOOST_CHECK( m0.ready() ); 00162 BOOST_CHECK_EQUAL( 1.0, m0.call() ); 00163 } 00164 00165 // Test calling an operation (user API) 00166 BOOST_AUTO_TEST_CASE( testOperationCall2 ) 00167 { 00168 Service::shared_ptr s = boost::make_shared<Service>("Service"); 00169 00170 tc.provides()->addService( s ); 00171 00172 s->addOperation("op0", &OperationTest::func0, this); 00173 s->addOperation("op1", &OperationTest::func1, this); 00174 s->addOperation("op2", &OperationTest::func2, this); 00175 s->addOperation("op3", &OperationTest::func3, this); 00176 s->addOperation("op4", &OperationTest::func4, this); 00177 s->addOperation("op5", &OperationTest::func5, this); 00178 00179 // Test calling an operation using a OperationCaller. 00180 OperationCaller<double(void)> m0("op0"); 00181 BOOST_CHECK( m0.ready() == false ); 00182 m0 = s->getOperation("op0"); 00183 BOOST_CHECK( m0.ready() ); 00184 BOOST_CHECK_EQUAL( 1.0, m0.call() ); 00185 } 00186 00187 // Test adding a C++ function to the services. 00188 BOOST_AUTO_TEST_CASE( testOperationAddCpp ) 00189 { 00190 // Add to custom service: 00191 Service::shared_ptr s = boost::make_shared<Service>("Service"); 00192 tc.provides()->addService( s ); 00193 s->addOperation("top0", &OperationTest::func0, this); 00194 s->addOperation("top1", &OperationTest::func1, this); 00195 BOOST_CHECK( s->getOperation("top0") ); 00196 BOOST_CHECK( s->getOperation("top1") ); 00197 opc0 = s->getOperation("top0"); 00198 opc1 = s->getOperation("top1"); 00199 BOOST_CHECK( opc0.ready() ); 00200 BOOST_CHECK( opc1.ready() ); 00201 BOOST_CHECK_EQUAL(opc0(), 1.0); 00202 BOOST_CHECK_EQUAL(opc1(1), 2.0); 00203 00204 // Add to default service: 00205 tc.addOperation("tcop0", &OperationTest::func0, this); 00206 tc.addOperation("tcop1", &OperationTest::func1, this); 00207 BOOST_CHECK( tc.provides()->getOperation("tcop0") ); 00208 BOOST_CHECK( tc.provides()->getOperation("tcop1") ); 00209 opc0 = tc.provides()->getOperation("tcop0"); 00210 opc1 = tc.provides()->getOperation("tcop1"); 00211 BOOST_CHECK( opc0.ready() ); 00212 BOOST_CHECK( opc1.ready() ); 00213 BOOST_CHECK_EQUAL(opc0(), 1.0); 00214 BOOST_CHECK_EQUAL(opc1(1), 2.0); 00215 00216 // Override existing ops: 00217 // note: we add different signature with same name to check if new op was used 00218 tc.addOperation("tcop0", &OperationTest::func1, this); 00219 tc.addOperation("tcop1", &OperationTest::func2, this); 00220 BOOST_CHECK( tc.provides()->getOperation("tcop0") ); 00221 BOOST_CHECK( tc.provides()->getOperation("tcop1") ); 00222 opc1 = tc.provides()->getOperation("tcop0"); 00223 opc2 = tc.provides()->getOperation("tcop1"); 00224 BOOST_CHECK( opc1.ready() ); 00225 BOOST_CHECK( opc2.ready() ); 00226 BOOST_CHECK_EQUAL(opc1(1), 2.0); 00227 BOOST_CHECK_EQUAL(opc2(1,2.0), 3.0); 00228 } 00229 00230 // Test adding a C function to the services. 00231 BOOST_AUTO_TEST_CASE( testOperationAddC ) 00232 { 00233 // Using custom Service 00234 Service::shared_ptr s = boost::make_shared<Service>("Service"); 00235 tc.provides()->addService( s ); 00236 s->addOperation("top0", &OperationTest::freefunc0); 00237 s->addOperation("top1", &OperationTest::freefunc1); 00238 BOOST_CHECK( s->getOperation("top0") ); 00239 BOOST_CHECK( s->getOperation("top1") ); 00240 opc0 = s->getOperation("top0"); 00241 opc1 = s->getOperation("top1"); 00242 BOOST_CHECK( opc0.ready() ); 00243 BOOST_CHECK( opc1.ready() ); 00244 BOOST_CHECK_EQUAL(opc0(), 1.0); 00245 BOOST_CHECK_EQUAL(opc1(1), 2.0); 00246 00247 // Using TaskContext API 00248 tc.addOperation("top0", &OperationTest::freefunc0); 00249 tc.addOperation("top1", &OperationTest::freefunc1); 00250 BOOST_CHECK( tc.getOperation("top0") ); 00251 BOOST_CHECK( tc.getOperation("top1") ); 00252 opc0 = tc.getOperation("top0"); 00253 opc1 = tc.getOperation("top1"); 00254 BOOST_CHECK( opc0.ready() ); 00255 BOOST_CHECK( opc1.ready() ); 00256 BOOST_CHECK_EQUAL(opc0(), 1.0); 00257 BOOST_CHECK_EQUAL(opc1(1), 2.0); 00258 } 00259 00260 // Test calling an operation of the default service. 00261 BOOST_AUTO_TEST_CASE( testOperationCall0 ) 00262 { 00263 // Test calling an operation using a OperationCaller. 00264 OperationCaller<double(void)> m0("op0"); 00265 BOOST_CHECK( m0.ready() == false ); 00266 m0 = tc.getOperation("op0"); 00267 BOOST_CHECK( m0.ready() ); 00268 BOOST_CHECK_EQUAL( 1.0, m0.call() ); 00269 } 00270 00271 #ifdef ORO_SIGNALLING_OPERATIONS 00272 // Test adding and signalling an operation without an implementation 00273 BOOST_AUTO_TEST_CASE( testOperationSignal ) 00274 { 00275 // invoke sig0 according to call/thread specification. 00276 Handle h = op0.signals(&OperationTest::sig0, this); 00277 00278 BOOST_CHECK( h.connected() ); 00279 // Test signal when calling a method: 00280 OperationCaller<double(void)> m0("op0"); 00281 BOOST_CHECK( m0.ready() == false ); 00282 m0 = op0.getImplementation(); 00283 BOOST_CHECK( m0.ready() ); 00284 00285 m0.call(); // return unspecified number (no implementation!). 00286 00287 BOOST_CHECK_EQUAL( -1.0, sig ); 00288 00289 // Test direct calling of op.signal 00290 sig = 0.0; 00291 op0.signal->emit(); 00292 BOOST_CHECK_EQUAL( -1.0, sig ); 00293 } 00294 00295 BOOST_AUTO_TEST_CASE( testOperationCallAndSignal ) 00296 { 00297 // invoke sig0 according to call/thread specification. 00298 Handle h = op0.signals(&OperationTest::sig0, this); 00299 op0.calls(&OperationTest::func0, this); 00300 00301 BOOST_CHECK( h.connected() ); 00302 // Test signal when calling a method: 00303 OperationCaller<double(void)> m0("op0"); 00304 BOOST_CHECK( m0.ready() == false ); 00305 m0 = op0.getImplementation(); 00306 BOOST_CHECK( m0.ready() ); 00307 00308 BOOST_CHECK_EQUAL( 1.0, m0.call() ); // return result of func0(). 00309 00310 BOOST_CHECK_EQUAL( -1.0, sig ); 00311 00312 // Test direct calling of op.signal 00313 sig = 0.0; 00314 op0.signal->emit(); 00315 BOOST_CHECK_EQUAL( -1.0, sig ); 00316 } 00317 #endif 00318 BOOST_AUTO_TEST_SUITE_END() 00319