remote_method_test.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: The SourceWorks Tue Sep 7 00:54:57 CEST 2010 remote_method_test.cpp
3 
4  remote_method_test.cpp - description
5  -------------------
6  begin : Tue September 07 2010
7  copyright : (C) 2010 The SourceWorks
8  email : peter@thesourceworks.com
9 
10  ***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 
20 
21 #define ORO_TEST_OPERATION_CALLER
22 
23 #include <iostream>
24 #include <TaskContext.hpp>
25 #include <OperationCaller.hpp>
26 #include <Operation.hpp>
28 #include <Service.hpp>
29 
30 #include "unit.hpp"
31 #include "operations_fixture.hpp"
32 
33 #define wait_for_equal( a, b, times ) do { \
34  bool wait_for_helper; \
35  int wait = 0; \
36  while( (wait_for_helper = ((a) != (b))) && wait++ != times ) \
37  usleep(100000); \
38  if (wait_for_helper) BOOST_CHECK_EQUAL( a, b ); \
39 } while(0)
40 
45 BOOST_FIXTURE_TEST_SUITE( RemoteOperationCallerTestSuite, OperationsFixture )
46 
47 BOOST_AUTO_TEST_CASE(testRemoteOperationCaller)
48 {
50  boost::shared_ptr<DisposableInterface> implementation( new RemoteOperationCaller<double(void)>(tc->provides("methods")->getPart("m0"),"m0", 0 ) );
51  m0 = implementation;
52  BOOST_CHECK( m0.ready() );
53 
55  implementation.reset( new RemoteOperationCaller<double(int)>(tc->provides("methods")->getPart("m1"),"m1", 0) );
56  m1 = implementation;
57  BOOST_CHECK( m1.ready() );
58 
60  implementation.reset( new RemoteOperationCaller<void(void)>(tc->provides("methods")->getPart("m0except"),"m0except", 0) );
61  m0e = implementation;
62  BOOST_CHECK( m0e.ready() );
63 
64  BOOST_CHECK_EQUAL( 2.0, m1(0) );
65  BOOST_CHECK_EQUAL( -2.0, m1(1) );
66  BOOST_CHECK_EQUAL( -1.0, m0() );
67  BOOST_CHECK_THROW( m0e(), std::runtime_error);
68  BOOST_REQUIRE( tc->inException() );
69 }
70 
71 BOOST_AUTO_TEST_CASE(testOperationCallerC_Call)
72 {
74  double r = 0.0;
75  mc = tc->provides("methods")->create("m0", caller->engine()).ret( r );
76  BOOST_CHECK( mc.call() );
77  BOOST_CHECK_EQUAL( r, -1.0 );
78 
79  mc = tc->provides("methods")->create("m2", caller->engine()).argC(1).argC(2.0).ret( r );
80  BOOST_CHECK( mc.call() );
81  BOOST_CHECK_EQUAL( r, -3.0 );
82 
83  mc = tc->provides("methods")->create("m3", caller->engine()).ret( r ).argC(1).argC(2.0).argC(true);
84  BOOST_CHECK( mc.call() );
85  BOOST_CHECK( r == -4.0 );
86 
87  mc = tc->provides("methods")->create("m4", caller->engine()).ret( r ).argC(1).argC(2.0).argC(true).argC(string("hello"));
88  BOOST_CHECK( mc.call() );
89  BOOST_CHECK( r == -5.0 );
90 
91  mc = tc->provides("methods")->create("m5", caller->engine()).argC(1).argC(2.0).argC(true).argC(string("hello")).argC(5.0f).ret( r );
92  BOOST_CHECK( mc.call() );
93  BOOST_CHECK( r == -6.0 );
94 
95  mc = tc->provides("methods")->create("m6", caller->engine()).ret( r ).argC(1).argC(2.0).argC(true).argC(string("hello")).argC(5.0f).argC('a');
96  BOOST_CHECK( mc.call() );
97  BOOST_CHECK( r == -7.0 );
98 
99  mc = tc->provides("methods")->create("m7", caller->engine()).ret( r ).argC(1).argC(2.0).argC(true).argC(string("hello")).argC(5.0f).argC('a').argC((unsigned int)7);
100  BOOST_CHECK( mc.call() );
101  BOOST_CHECK( r == -8.0 );
102 
103  mc = tc->provides("methods")->create("m0except", caller->engine());
104  BOOST_CHECK_THROW( mc.call(), std::runtime_error);
105 
106  mc = tc->provides("methods")->create("o0except", caller->engine());
107  BOOST_CHECK_THROW( mc.call(), std::runtime_error);
108  BOOST_REQUIRE( tc->inException() );
109 }
110 
111 BOOST_AUTO_TEST_CASE(testOperationCallerC_Send)
112 {
113  OperationCallerC mc;
114  SendHandleC shc;
115  double r = 0.0;
116  double cr = 0.0;
117  mc = tc->provides("methods")->create("m0", caller->engine()).ret( r );
118  BOOST_CHECK_NO_THROW( mc.check() );
119  shc = mc.send();
120  shc.arg(cr);
121  BOOST_CHECK( shc.ready() ); // 1 argument to collect.
122  BOOST_CHECK_NO_THROW( shc.check() );
123  // now collect:
124  BOOST_CHECK_EQUAL( shc.collect(), SendSuccess);
125  BOOST_CHECK_EQUAL( r, 0.0 );
126  BOOST_CHECK_EQUAL( cr, -1.0 );
127 
128  mc = tc->provides("methods")->create("m2", caller->engine()).argC(1).argC(2.0).ret( r );
129  BOOST_CHECK_NO_THROW( mc.check() );
130  shc = mc.send();
131  shc.arg(cr);
132  BOOST_CHECK( shc.ready() ); // 1 argument to collect.
133  BOOST_CHECK_NO_THROW( shc.check() );
134  // now collect:
135  BOOST_CHECK_EQUAL( shc.collect(), SendSuccess);
136  BOOST_CHECK_EQUAL( r, 0.0 );
137  BOOST_CHECK_EQUAL( cr, -3.0 );
138 
139  mc = tc->provides("methods")->create("m3", caller->engine()).ret( r ).argC(1).argC(2.0).argC(true);
140  BOOST_CHECK_NO_THROW( mc.check() );
141  shc = mc.send();
142  shc.arg(cr);
143  BOOST_CHECK( shc.ready() ); // 1 argument to collect.
144  BOOST_CHECK_NO_THROW( shc.check() );
145  // now collect:
146  BOOST_CHECK_EQUAL( shc.collect(), SendSuccess);
147  BOOST_CHECK_EQUAL( r, 0.0 );
148  BOOST_CHECK_EQUAL( cr, -4.0 );
149 
150  mc = tc->provides("methods")->create("m4", caller->engine()).ret( r ).argC(1).argC(2.0).argC(true).argC(string("hello"));
151  BOOST_CHECK_NO_THROW( mc.check() );
152  shc = mc.send();
153  shc.arg(cr);
154  BOOST_CHECK( shc.ready() ); // 1 argument to collect.
155  BOOST_CHECK_NO_THROW( shc.check() );
156  // now collect:
157  BOOST_CHECK_EQUAL( shc.collect(), SendSuccess);
158  BOOST_CHECK_EQUAL( r, 0.0 );
159  BOOST_CHECK_EQUAL( cr, -5.0 );
160 
161  mc = tc->provides("methods")->create("m5", caller->engine()).ret( r ).argC(1).argC(2.0).argC(true).argC(string("hello")).argC(5.0f);
162  BOOST_CHECK_NO_THROW( mc.check() );
163  shc = mc.send();
164  shc.arg(cr);
165  BOOST_CHECK( shc.ready() ); // 1 argument to collect.
166  BOOST_CHECK_NO_THROW( shc.check() );
167  // now collect:
168  BOOST_CHECK_EQUAL( shc.collect(), SendSuccess);
169  BOOST_CHECK_EQUAL( r, 0.0 );
170  BOOST_CHECK_EQUAL( cr, -6.0 );
171 
172  mc = tc->provides("methods")->create("m6", caller->engine()).ret( r ).argC(1).argC(2.0).argC(true).argC(string("hello")).argC(5.0f).argC('a');
173  BOOST_CHECK_NO_THROW( mc.check() );
174  shc = mc.send();
175  shc.arg(cr);
176  BOOST_CHECK( shc.ready() ); // 1 argument to collect.
177  BOOST_CHECK_NO_THROW( shc.check() );
178  // now collect:
179  BOOST_CHECK_EQUAL( shc.collect(), SendSuccess);
180  BOOST_CHECK_EQUAL( r, 0.0 );
181  BOOST_CHECK_EQUAL( cr, -7.0 );
182 
183  mc = tc->provides("methods")->create("m7", caller->engine()).ret( r ).argC(1).argC(2.0).argC(true).argC(string("hello")).argC(5.0f).argC('a').argC((unsigned int)7);
184  BOOST_CHECK_NO_THROW( mc.check() );
185  shc = mc.send();
186  shc.arg(cr);
187  BOOST_CHECK( shc.ready() ); // 1 argument to collect.
188  BOOST_CHECK_NO_THROW( shc.check() );
189  // now collect:
190  BOOST_CHECK_EQUAL( shc.collect(), SendSuccess);
191  BOOST_CHECK_EQUAL( r, 0.0 );
192  BOOST_CHECK_EQUAL( cr, -8.0 );
193 
194  mc = tc->provides("methods")->create("m0except", caller->engine());
195  BOOST_CHECK_NO_THROW( mc.check() );
196  shc = mc.send();
197  BOOST_CHECK( shc.ready() );
198  BOOST_CHECK_NO_THROW( shc.check() );
199  // now collect:
200  BOOST_CHECK_THROW( shc.collect(), std::runtime_error );
201  BOOST_REQUIRE(tc->inException() );
202 }
203 
204 BOOST_AUTO_TEST_CASE(testOperationCallerFromDS)
205 {
206  ServicePtr sp = tc->provides("methods");
207 
208  double ret;
209  OperationCallerC mc0 = sp->create("m0", caller->engine() );
210  mc0.ret(ret);
211  OperationCallerC mc1 = sp->create("m1", caller->engine() );
212  mc1.argC(1).ret(ret);
213  OperationCallerC mc2 = sp->create("m2", caller->engine() );
214  mc2.argC(1).argC(2.0).ret(ret);
215  OperationCallerC mc3 = sp->create("m3", caller->engine() );
216  mc3.argC(1).argC(2.0).argC(true).ret(ret);
217  OperationCallerC mc4 = sp->create("m4", caller->engine() );
218  mc4.argC(1).argC(2.0).argC(true).argC(std::string("hello")).ret(ret);
219  OperationCallerC mc5 = sp->create("m5", caller->engine() );
220  mc5.argC(1).argC(2.0).argC(true).argC(std::string("hello")).argC(5.0f).ret(ret);
221  OperationCallerC mc6 = sp->create("m6", caller->engine() );
222  mc6.argC(1).argC(2.0).argC(true).argC(std::string("hello")).argC(5.0f).argC('a').ret(ret);
223  OperationCallerC mc7 = sp->create("m7", caller->engine() );
224  mc7.argC(1).argC(2.0).argC(true).argC(std::string("hello")).argC(5.0f).argC('a').argC((unsigned int)7).ret(ret);
225 
226  OperationCallerC mc0e = sp->create("m0except", caller->engine() );
227 
228  BOOST_CHECK( mc0.call() );
229  BOOST_CHECK_EQUAL(-1.0, ret);
230  BOOST_CHECK( mc1.call() );
231  BOOST_CHECK_EQUAL(-2.0, ret);
232  BOOST_CHECK( mc2.call() );
233  BOOST_CHECK_EQUAL(-3.0, ret);
234  BOOST_CHECK( mc3.call() );
235  BOOST_CHECK_EQUAL(-4.0, ret);
236  BOOST_CHECK( mc4.call() );
237  BOOST_CHECK_EQUAL(-5.0, ret);
238  BOOST_CHECK( mc5.call() );
239  BOOST_CHECK_EQUAL(-6.0, ret);
240  BOOST_CHECK( mc6.call() );
241  BOOST_CHECK_EQUAL(-7.0, ret);
242  BOOST_CHECK( mc7.call() );
243  BOOST_CHECK_EQUAL(-8.0, ret);
244 
245  BOOST_CHECK_THROW( mc0e.call(), std::runtime_error );
246  BOOST_REQUIRE(tc->inException() );
247 }
248 
249 BOOST_AUTO_TEST_CASE(testRemoteOperationCallerFactory)
250 {
251  // Test the addition of methods to the operation interface,
252  // and retrieving it back in a new OperationCaller object.
253  // these operations may use the remoting facility to adapt
254 
255  Operation<double(void)> m0("m0");
256  m0.calls(&OperationsFixture::m0, this);
257  Operation<double(int)> m1("m1");
258  m1.calls(&OperationsFixture::m1, this);
260  m2.calls(&OperationsFixture::m2, this);
261  Operation<void(void)> m0e("m0e");
263 
264  Service to("task");
265 
266  BOOST_CHECK( !to.addOperation(m0).ready() );
267  to.setOwner(tc);
268  BOOST_CHECK( to.addOperation(m0).ready() );
269  BOOST_CHECK( to.addOperation(m0).ready() );
270  BOOST_CHECK( to.addOperation(m1).ready() );
271  BOOST_CHECK( to.addOperation(m2).ready() );
272  BOOST_CHECK( to.addOperation(m0e).ready() );
273 
274  // test constructor
276  BOOST_CHECK( mm0.getOperationCallerImpl() );
277  BOOST_CHECK( mm0.ready() );
278 
279  OperationCaller<void(void)> mm0e = to.getOperation("m0e");
280  BOOST_CHECK( mm0e.getOperationCallerImpl() );
281  BOOST_CHECK( mm0e.ready() );
282 
283  // test operator=()
285  mm1 = to.getOperation("m1");
286  BOOST_CHECK( mm1.getOperationCallerImpl() );
287  BOOST_CHECK( mm1.ready() );
288 
290  BOOST_CHECK( mm2.getOperationCallerImpl() );
291  BOOST_CHECK( mm2.ready() );
292 
293  // execute methods and check status:
294  BOOST_CHECK_EQUAL( -1.0, mm0() );
295 
296  BOOST_CHECK_EQUAL( -2.0, mm1(1) );
297  BOOST_CHECK_EQUAL( -3.0, mm2(1, 2.0) );
298 
299  BOOST_CHECK_THROW( mm0e(), std::runtime_error );
300 
301  // Add uninitialised op:
302  Operation<void(void)> ovoid("ovoid");
303  BOOST_CHECK(to.addOperation( ovoid ).ready() == true);
304  ovoid = Operation<void(void)>("ovoid");
305  BOOST_CHECK(to.addOperation( ovoid ).ready() == true);
306 
307  // wrong type 1:
309  mvoid = to.getOperation("m1");
310  BOOST_CHECK( mvoid.ready() == false );
311  // wrong type 2:
312  mvoid = to.getOperation("m2");
313  BOOST_CHECK( mvoid.ready() == false );
314  // auto-converts double to void:
315  mvoid = to.getOperation("m0");
316  BOOST_CHECK( mvoid.ready() == true );
317  // non existing
318  mvoid = to.getOperation("voidm");
319  BOOST_CHECK( mvoid.ready() == false );
320 
321  // this line may not crash:
322  mvoid();
323 }
324 
325 BOOST_AUTO_TEST_CASE(testRemoteOperationCallerSleep)
326 {
327  OperationCaller<int(int)> sleepAndIncOwnThread("sleepAndIncOwnThread", caller->engine());
328 
329  boost::shared_ptr<DisposableInterface> implementation( new RemoteOperationCaller<int(int)>(tc->provides("methods")->getPart("sleepAndIncOwnThread"), "sleepAndIncOwnThread", 0) );
330  sleepAndIncOwnThread = implementation;
331  BOOST_CHECK( sleepAndIncOwnThread.ready() );
332 
333  i = 0;
334  sleepAndIncOwnThread.call(1);
335  sleepAndIncOwnThread.call(1);
336  sleepAndIncOwnThread.call(1);
337  BOOST_CHECK_EQUAL( 3, i );
338 
339  i = 0;
340  sleepAndIncOwnThread.send(1);
341  sleepAndIncOwnThread.send(1);
342  sleepAndIncOwnThread.send(1);
343  wait_for_equal(3, i, 50 /* * 100ms */ );
344 }
345 
346 BOOST_AUTO_TEST_CASE(testRemoteOperationCallerReferences)
347 {
348  OperationCaller<const void *(const int&)> returnAddressOfConst("returnAddressOfConst", caller->engine());
349  OperationCaller<void *(int&)> returnAddressOf("returnAddressOf", caller->engine());
350 
351  boost::shared_ptr<DisposableInterface> implementation( new RemoteOperationCaller<const void *(const int&)>(tc->provides("methods")->getPart("returnAddressOfConst"), "returnAddressOfConst", 0) );
352  returnAddressOfConst = implementation;
353  BOOST_CHECK( returnAddressOfConst.ready() );
354 
355  implementation.reset( new RemoteOperationCaller<void *(int&)>(tc->provides("methods")->getPart("returnAddressOf"), "returnAddressOf", 0) );
356  returnAddressOf = implementation;
357  BOOST_CHECK( returnAddressOf.ready() );
358 
359  int var = 0;
360 
361  // call
362  BOOST_CHECK_EQUAL(&var, returnAddressOf(var));
363  BOOST_CHECK_EQUAL(&var, returnAddressOfConst(var));
364 
365  // send
366  // Collecting from a RemoteOperationCaller returning void * segfaults!
367  if (false) {
368  SendHandle<void *(int&)> sh = returnAddressOf.send(var);
369  BOOST_CHECK_EQUAL(SendSuccess, sh.collect());
370  BOOST_CHECK_EQUAL(&var, sh.ret());
371  }
372 
373  // compare with LocalOperationCaller...
374  // call
375  returnAddressOfConst = tc->provides("methods")->getPart("returnAddressOfConst");
376  returnAddressOf = tc->provides("methods")->getPart("returnAddressOf");
377  BOOST_CHECK_EQUAL(&var, returnAddressOf(var));
378  BOOST_CHECK_EQUAL(&var, returnAddressOfConst(var));
379 
380  // send
381  {
382  SendHandle<void *(int&)> sh = returnAddressOf.send(var);
383  BOOST_CHECK_EQUAL(SendSuccess, sh.collect());
384  BOOST_CHECK_EQUAL(&var, sh.ret());
385  }
386 
387  // call by value
388  OperationCaller<const void *(int)> returnAddressOfByValue("returnAddressOfByValue", caller->engine());
389  returnAddressOfByValue = tc->provides("methods")->getPart("returnAddressOfConst");
390  BOOST_CHECK(returnAddressOfByValue.ready());
391 
392  BOOST_CHECK_NE(&var, returnAddressOfByValue(var));
393 }
394 
#define BOOST_FIXTURE_TEST_SUITE(suite_name, F)
#define BOOST_AUTO_TEST_SUITE_END()
Operation< Signature > & addOperation(Operation< Signature > &op)
Definition: Service.hpp:341
#define wait_for_equal(a, b, times)
SendHandleC & arg(base::DataSourceBase::shared_ptr a)
The SendHandle is used to collect the result values of an asynchronous invocation. The template argument Signature must have the same type as the method being invoked.
Definition: rtt-fwd.hpp:79
boost::shared_ptr< Service > ServicePtr
Definition: rtt-fwd.hpp:86
OperationCallerC & ret(base::AttributeBase *r)
BOOST_AUTO_TEST_CASE(testRemoteOperationCaller)
Operation & calls(boost::function< Signature > func, ExecutionThread et=ClientThread, ExecutionEngine *ownerEngine=NULL)
Definition: Operation.hpp:147
OperationCallerC & argC(const ArgT a)
OperationInterfacePart * getOperation(std::string name)
Definition: Service.cpp:142
SendStatus collect() const
Definition: SendHandle.hpp:124
void setOwner(TaskContext *new_owner)
Definition: Service.cpp:254
double m2(int i, double d)


rtt
Author(s): RTT Developers
autogenerated on Tue Jun 25 2019 19:33:27