1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <Ice/Ice.h>
6 #include <TestHelper.h>
7 #include <Test.h>
8 
9 using namespace std;
10 
11 static string testString = "This is a test string";
12 
13 #ifndef ICE_CPP11_MAPPING
14 class Cookie : public Ice::LocalObject
15 {
16 public:
17 
18     string getString()
19     {
20         return testString;
21     }
22 };
23 typedef IceUtil::Handle<Cookie> CookiePtr;
24 
25 class CallbackBase : public IceUtil::Monitor<IceUtil::Mutex>
26 {
27 public:
28 
29     CallbackBase() :
30         _called(false)
31     {
32     }
33 
34     virtual ~CallbackBase()
35     {
36     }
37 
38     void check()
39     {
40         IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
41         while(!_called)
42         {
43             wait();
44         }
45         _called = false;
46     }
47 
48 protected:
49 
50     void called()
51     {
52         IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
53         assert(!_called);
54         _called = true;
55         notify();
56     }
57 
58 private:
59 
60     bool _called;
61 };
62 
63 class Callback : public IceUtil::Shared, public CallbackBase
64 {
65 public:
66 
67     Callback(const Ice::CommunicatorPtr& communicator, bool useCookie) :
68         _communicator(communicator),
69         _useCookie(useCookie)
70     {
71     }
72 
73     void opString(const Ice::AsyncResultPtr& result)
74     {
75         string cmp = testString;
76         if(_useCookie)
77         {
78             CookiePtr cookie = CookiePtr::dynamicCast(result->getCookie());
79             cmp = cookie->getString();
80         }
81 
82         Ice::ByteSeq outParams;
83         if(result->getProxy()->end_ice_invoke(outParams, result))
84         {
85             Ice::InputStream in(_communicator, result->getProxy()->ice_getEncodingVersion(), outParams);
86             in.startEncapsulation();
87             string s;
88             in.read(s);
89             test(s == cmp);
90             in.read(s);
91             test(s == cmp);
92             in.endEncapsulation();
93             called();
94         }
95         else
96         {
97             test(false);
98         }
99     }
100 
101     void opException(const Ice::AsyncResultPtr& result)
102     {
103         if(_useCookie)
104         {
105             CookiePtr cookie = CookiePtr::dynamicCast(result->getCookie());
106             test(cookie->getString() == testString);
107         }
108 
109         Ice::ByteSeq outParams;
110         if(result->getProxy()->end_ice_invoke(outParams, result))
111         {
112             test(false);
113         }
114         else
115         {
116             Ice::InputStream in(_communicator, result->getProxy()->ice_getEncodingVersion(), outParams);
117             in.startEncapsulation();
118             try
119             {
120                 in.throwException();
121             }
122             catch(const Test::MyException&)
123             {
124                 in.endEncapsulation();
125                 called();
126             }
127             catch(...)
128             {
129                 test(false);
130             }
131         }
132     }
133 
134     void opStringNC(bool ok, const Ice::ByteSeq& outParams)
135     {
136         if(ok)
137         {
138             Ice::InputStream in(_communicator, outParams);
139             in.startEncapsulation();
140             string s;
141             in.read(s);
142             test(s == testString);
143             in.read(s);
144             test(s == testString);
145             in.endEncapsulation();
146             called();
147         }
148         else
149         {
150             test(false);
151         }
152     }
153 
154     void opStringPairNC(bool ok, const pair<const Ice::Byte*, const Ice::Byte*>& outParams)
155     {
156         if(ok)
157         {
158             Ice::InputStream in(_communicator, outParams);
159             in.startEncapsulation();
160             string s;
161             in.read(s);
162             test(s == testString);
163             in.read(s);
164             test(s == testString);
165             in.endEncapsulation();
166             called();
167         }
168         else
169         {
170             test(false);
171         }
172     }
173 
174     void opStringWC(bool ok, const Ice::ByteSeq& outParams, const CookiePtr& cookie)
175     {
176         if(ok)
177         {
178             Ice::InputStream in(_communicator, outParams);
179             in.startEncapsulation();
180             string s;
181             in.read(s);
182             test(s == cookie->getString());
183             in.read(s);
184             test(s == cookie->getString());
185             in.endEncapsulation();
186             called();
187         }
188         else
189         {
190             test(false);
191         }
192     }
193 
194     void opExceptionNC(bool ok, const Ice::ByteSeq& outParams)
195     {
196         if(ok)
197         {
198             test(false);
199         }
200         else
201         {
202             Ice::InputStream in(_communicator, outParams);
203             in.startEncapsulation();
204             try
205             {
206                 in.throwException();
207             }
208             catch(const Test::MyException&)
209             {
210                 in.endEncapsulation();
211                 called();
212             }
213             catch(...)
214             {
215                 test(false);
216             }
217         }
218     }
219 
220     void opExceptionPairNC(bool ok, const pair<const Ice::Byte*, const Ice::Byte*>& outParams)
221     {
222         if(ok)
223         {
224             test(false);
225         }
226         else
227         {
228             Ice::InputStream in(_communicator, outParams);
229             in.startEncapsulation();
230             try
231             {
232                 in.throwException();
233             }
234             catch(const Test::MyException&)
235             {
236                 in.endEncapsulation();
237                 called();
238             }
239             catch(...)
240             {
241                 test(false);
242             }
243         }
244     }
245 
246     void opExceptionWC(bool ok, const Ice::ByteSeq& outParams, const CookiePtr& cookie)
247     {
248         test(cookie->getString() == testString);
249         if(ok)
250         {
251             test(false);
252         }
253         else
254         {
255             Ice::InputStream in(_communicator, outParams);
256             in.startEncapsulation();
257             try
258             {
259                 in.throwException();
260             }
261             catch(const Test::MyException&)
262             {
263                 in.endEncapsulation();
264                 called();
265             }
266             catch(...)
267             {
268                 test(false);
269             }
270         }
271     }
272 
273 private:
274 
275     Ice::CommunicatorPtr _communicator;
276     bool _useCookie;
277 };
278 typedef IceUtil::Handle<Callback> CallbackPtr;
279 #endif
280 
281 Test::MyClassPrxPtr
282 allTests(Test::TestHelper* helper)
283 {
284     Ice::CommunicatorPtr communicator = helper->communicator();
285     string ref = "test:" + helper->getTestEndpoint();
286     Ice::ObjectPrxPtr base = communicator->stringToProxy(ref);
287     test(base);
288 
289     Test::MyClassPrxPtr cl = ICE_CHECKED_CAST(Test::MyClassPrx, base);
290     test(cl);
291 
292     Test::MyClassPrxPtr oneway = cl->ice_oneway();
293     Test::MyClassPrxPtr batchOneway = cl->ice_batchOneway();
294 
295     cout << "testing ice_invoke... " << flush;
296 
297     {
298         Ice::ByteSeq inEncaps, outEncaps;
299         if(!oneway->ice_invoke("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps, outEncaps))
300         {
301             test(false);
302         }
303 
304         test(batchOneway->ice_invoke("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps, outEncaps));
305         test(batchOneway->ice_invoke("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps, outEncaps));
306         test(batchOneway->ice_invoke("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps, outEncaps));
307         test(batchOneway->ice_invoke("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps, outEncaps));
308         batchOneway->ice_flushBatchRequests();
309 
310         Ice::OutputStream out(communicator);
311         out.startEncapsulation();
312         out.write(testString);
313         out.endEncapsulation();
314         out.finished(inEncaps);
315 
316         // ice_invoke
317         if(cl->ice_invoke("opString", Ice::ICE_ENUM(OperationMode, Normal), inEncaps, outEncaps))
318         {
319             Ice::InputStream in(communicator, out.getEncoding(), outEncaps);
320             in.startEncapsulation();
321             string s;
322             in.read(s);
323             test(s == testString);
324             in.read(s);
325             test(s == testString);
326             in.endEncapsulation();
327         }
328         else
329         {
330             test(false);
331         }
332 
333         // ice_invoke with array mapping
334         pair<const ::Ice::Byte*, const ::Ice::Byte*> inPair(&inEncaps[0], &inEncaps[0] + inEncaps.size());
335         if(cl->ice_invoke("opString", Ice::ICE_ENUM(OperationMode, Normal), inPair, outEncaps))
336         {
337             Ice::InputStream in(communicator, out.getEncoding(), outEncaps);
338             in.startEncapsulation();
339             string s;
340             in.read(s);
341             test(s == testString);
342             in.read(s);
343             test(s == testString);
344             in.endEncapsulation();
345         }
346         else
347         {
348             test(false);
349         }
350     }
351 
352     for(int i = 0; i < 2; ++i)
353     {
354         Ice::ByteSeq inEncaps, outEncaps;
355         Ice::Context ctx;
356         if(i == 1)
357         {
358             ctx["raise"] = "";
359         }
360         if(cl->ice_invoke("opException", Ice::ICE_ENUM(OperationMode, Normal), inEncaps, outEncaps, ctx))
361         {
362             test(false);
363         }
364         else
365         {
366             Ice::InputStream in(communicator, cl->ice_getEncodingVersion(), outEncaps);
367             in.startEncapsulation();
368             try
369             {
370                 in.throwException();
371             }
372             catch(const Test::MyException&)
373             {
374             }
375             catch(...)
376             {
377                 test(false);
378             }
379             in.endEncapsulation();
380         }
381     }
382 
383     cout << "ok" << endl;
384 
385     cout << "testing asynchronous ice_invoke... " << flush;
386 #ifdef ICE_CPP11_MAPPING
387 
388     {
389         Ice::ByteSeq inEncaps;
390         batchOneway->ice_invokeAsync("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps,
391             [](bool, const vector<Ice::Byte>)
392             {
393                 test(false);
394             },
395             [](exception_ptr)
396             {
397                 test(false);
398             },
399             [](bool)
400             {
401                 test(false);
402             });
403         batchOneway->ice_flushBatchRequests();
404     }
405     //
406     // repeat with the future API.
407     //
408     {
409         Ice::ByteSeq inEncaps;
410         test(batchOneway->ice_invokeAsync("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps).get().returnValue);
411         test(batchOneway->ice_invokeAsync("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps).get().returnValue);
412         test(batchOneway->ice_invokeAsync("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps).get().returnValue);
413         test(batchOneway->ice_invokeAsync("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps).get().returnValue);
414         batchOneway->ice_flushBatchRequests();
415     }
416 
417     {
418         promise<bool> completed;
419         Ice::ByteSeq inEncaps, outEncaps;
420         oneway->ice_invokeAsync(
421             "opOneway",
422             Ice::OperationMode::Normal,
423             inEncaps,
424             nullptr,
425             [&](exception_ptr ex)
426             {
427                 completed.set_exception(ex);
428             },
429             [&](bool)
430             {
431                 completed.set_value(true);
432             });
433 
434         test(completed.get_future().get());
435     }
436 
437     //
438     // repeat with the future API.
439     //
440 
441     {
442         Ice::ByteSeq inEncaps, outEncaps;
443         auto completed = oneway->ice_invokeAsync("opOneway", Ice::OperationMode::Normal, inEncaps);
444         test(completed.get().returnValue);
445     }
446 
447     {
448         promise<bool> completed;
449         Ice::ByteSeq inEncaps, outEncaps;
450         Ice::OutputStream out(communicator);
451         out.startEncapsulation();
452         out.write(testString);
453         out.endEncapsulation();
454         out.finished(inEncaps);
455 
456         cl->ice_invokeAsync("opString", Ice::OperationMode::Normal, inEncaps,
457             [&](bool ok, vector<Ice::Byte> outParams)
458             {
459                 outEncaps = move(outParams);
460                 completed.set_value(ok);
461             },
462             [&](exception_ptr ex)
463             {
464                 completed.set_exception(ex);
465             });
466         test(completed.get_future().get());
467 
468         Ice::InputStream in(communicator, outEncaps);
469         in.startEncapsulation();
470         string s;
471         in.read(s);
472         test(s == testString);
473         in.read(s);
474         test(s == testString);
475         in.endEncapsulation();
476     }
477     //
478     // repeat with the future API.
479     //
480     {
481         Ice::ByteSeq inEncaps, outEncaps;
482         Ice::OutputStream out(communicator);
483         out.startEncapsulation();
484         out.write(testString);
485         out.endEncapsulation();
486         out.finished(inEncaps);
487 
488         auto result = cl->ice_invokeAsync("opString", Ice::OperationMode::Normal, inEncaps).get();
489         test(result.returnValue);
490 
491         Ice::InputStream in(communicator, result.outParams);
492         in.startEncapsulation();
493         string s;
494         in.read(s);
495         test(s == testString);
496         in.read(s);
497         test(s == testString);
498         in.endEncapsulation();
499     }
500 
501     {
502         promise<bool> completed;
503         promise<void> sent;
504         Ice::ByteSeq inEncaps, outEncaps;
505         Ice::OutputStream out(communicator);
506         out.startEncapsulation();
507         out.write(testString);
508         out.endEncapsulation();
509         out.finished(inEncaps);
510 
511         auto inPair = make_pair(inEncaps.data(), inEncaps.data() + inEncaps.size());
512 
513         cl->ice_invokeAsync("opString", Ice::OperationMode::Normal, inPair,
514             [&](bool ok, pair<const Ice::Byte*, const Ice::Byte*> outParams)
515             {
516                 vector<Ice::Byte>(outParams.first, outParams.second).swap(outEncaps);
517                 completed.set_value(ok);
518             },
519             [&](exception_ptr ex)
520             {
521                 completed.set_exception(ex);
522             },
523             [&](bool)
524             {
525                 sent.set_value();
526             });
527         sent.get_future().get(); // Ensure sent callback was called
528         test(completed.get_future().get());
529 
530         Ice::InputStream in(communicator, outEncaps);
531         in.startEncapsulation();
532         string s;
533         in.read(s);
534         test(s == testString);
535         in.read(s);
536         test(s == testString);
537         in.endEncapsulation();
538     }
539     //
540     // repeat with the future API.
541     //
542 
543     {
544         Ice::ByteSeq inEncaps, outEncaps;
545         Ice::OutputStream out(communicator);
546         out.startEncapsulation();
547         out.write(testString);
548         out.endEncapsulation();
549         out.finished(inEncaps);
550 
551         auto inPair = make_pair(inEncaps.data(), inEncaps.data() + inEncaps.size());
552 
553         auto result = cl->ice_invokeAsync("opString", Ice::OperationMode::Normal, inPair).get();
554         test(result.returnValue);
555 
556         Ice::InputStream in(communicator, result.outParams);
557         in.startEncapsulation();
558         string s;
559         in.read(s);
560         test(s == testString);
561         in.read(s);
562         test(s == testString);
563         in.endEncapsulation();
564     }
565 
566     {
567         promise<bool> completed;
568         promise<void> sent;
569         Ice::ByteSeq inEncaps, outEncaps;
570 
571         cl->ice_invokeAsync("opException", Ice::OperationMode::Normal, inEncaps,
572             [&](bool ok, vector<Ice::Byte> outParams)
573             {
574                 outEncaps = move(outParams);
575                 completed.set_value(ok);
576             },
577             [&](exception_ptr ex)
578             {
579                 completed.set_exception(ex);
580             },
581             [&](bool)
582             {
583                 sent.set_value();
584             });
585         sent.get_future().get(); // Ensure sent callback was called
586         test(!completed.get_future().get());
587 
588         Ice::InputStream in(communicator, outEncaps);
589         in.startEncapsulation();
590         try
591         {
592             in.throwException();
593             test(false);
594         }
595         catch(const Test::MyException&)
596         {
597         }
598         catch(...)
599         {
600             test(false);
601         }
602     }
603     //
604     // repeat with the future API.
605     //
606     {
607         Ice::ByteSeq inEncaps;
608         auto result = cl->ice_invokeAsync("opException", Ice::OperationMode::Normal, inEncaps).get();
609         test(!result.returnValue);
610 
611         Ice::InputStream in(communicator, result.outParams);
612         in.startEncapsulation();
613         try
614         {
615             in.throwException();
616             test(false);
617         }
618         catch(const Test::MyException&)
619         {
620         }
621         catch(...)
622         {
623             test(false);
624         }
625     }
626 
627 #else
628     void (::Callback::*nullEx)(const Ice::Exception&) = 0;
629     void (::Callback::*nullExWC)(const Ice::Exception&, const CookiePtr&) = 0;
630 
631     {
632         Ice::ByteSeq inEncaps, outEncaps;
633         test(batchOneway->end_ice_invoke(outEncaps, batchOneway->begin_ice_invoke("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps)));
634         test(batchOneway->end_ice_invoke(outEncaps, batchOneway->begin_ice_invoke("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps)));
635         test(batchOneway->end_ice_invoke(outEncaps, batchOneway->begin_ice_invoke("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps)));
636         test(batchOneway->end_ice_invoke(outEncaps, batchOneway->begin_ice_invoke("opOneway", Ice::ICE_ENUM(OperationMode, Normal), inEncaps)));
637         batchOneway->ice_flushBatchRequests();
638     }
639 
640     {
641         CookiePtr cookie = new Cookie();
642 
643         Ice::ByteSeq inEncaps, outEncaps;
644         Ice::AsyncResultPtr result = oneway->begin_ice_invoke("opOneway", Ice::Normal, inEncaps);
645         if(!oneway->end_ice_invoke(outEncaps, result))
646         {
647             test(false);
648         }
649 
650         Ice::OutputStream out(communicator);
651         out.startEncapsulation();
652         out.write(testString);
653         out.endEncapsulation();
654         out.finished(inEncaps);
655 
656         // begin_ice_invoke with no callback
657         result = cl->begin_ice_invoke("opString", Ice::Normal, inEncaps);
658         if(cl->end_ice_invoke(outEncaps, result))
659         {
660             Ice::InputStream in(communicator, out.getEncoding(), outEncaps);
661             in.startEncapsulation();
662             string s;
663             in.read(s);
664             test(s == testString);
665             in.read(s);
666             test(s == testString);
667             in.endEncapsulation();
668         }
669         else
670         {
671             test(false);
672         }
673 
674         // begin_ice_invoke with no callback and array mapping
675         pair<const ::Ice::Byte*, const ::Ice::Byte*> inPair(&inEncaps[0], &inEncaps[0] + inEncaps.size());
676         result = cl->begin_ice_invoke("opString", Ice::Normal, inPair);
677         if(cl->end_ice_invoke(outEncaps, result))
678         {
679             Ice::InputStream in(communicator, out.getEncoding(), outEncaps);
680             in.startEncapsulation();
681             string s;
682             in.read(s);
683             test(s == testString);
684             in.read(s);
685             test(s == testString);
686             in.endEncapsulation();
687         }
688         else
689         {
690             test(false);
691         }
692 
693         // begin_ice_invoke with Callback
694         ::CallbackPtr cb = new ::Callback(communicator, false);
695         cl->begin_ice_invoke("opString", Ice::Normal, inEncaps, Ice::newCallback(cb, &Callback::opString));
696         cb->check();
697 
698         // begin_ice_invoke with Callback and Cookie
699         cb = new ::Callback(communicator, true);
700         cl->begin_ice_invoke("opString", Ice::Normal, inEncaps, Ice::newCallback(cb, &Callback::opString), cookie);
701         cb->check();
702 
703         // begin_ice_invoke with Callback_Object_ice_invoke
704         cb = new ::Callback(communicator, false);
705         Ice::Callback_Object_ice_invokePtr d = Ice::newCallback_Object_ice_invoke(cb, &Callback::opStringNC, nullEx);
706         cl->begin_ice_invoke("opString", Ice::Normal, inEncaps, d);
707         cb->check();
708 
709         // begin_ice_invoke with Callback_Object_ice_invoke with Cookie
710         cb = new ::Callback(communicator, false);
711         d = Ice::newCallback_Object_ice_invoke(cb, &Callback::opStringWC, nullExWC);
712         cl->begin_ice_invoke("opString", Ice::Normal, inEncaps, d, cookie);
713         cb->check();
714 
715         // begin_ice_invoke with Callback_Object_ice_invoke and array mapping
716         cb = new ::Callback(communicator, false);
717         d = Ice::newCallback_Object_ice_invoke(cb, &Callback::opStringNC, nullEx);
718         cl->begin_ice_invoke("opString", Ice::Normal, inPair, d);
719         cb->check();
720 
721         // begin_ice_invoke with Callback_Object_ice_invoke and array mapping with Cookie
722         cb = new ::Callback(communicator, false);
723         d = Ice::newCallback_Object_ice_invoke(cb, &Callback::opStringWC, nullExWC);
724         cl->begin_ice_invoke("opString", Ice::Normal, inPair, d, cookie);
725         cb->check();
726     }
727 
728     {
729         CookiePtr cookie = new Cookie();
730         Ice::ByteSeq inEncaps, outEncaps;
731 
732         // begin_ice_invoke with no callback
733         Ice::AsyncResultPtr result = cl->begin_ice_invoke("opException", Ice::Normal, inEncaps);
734         if(cl->end_ice_invoke(outEncaps, result))
735         {
736             test(false);
737         }
738         else
739         {
740             Ice::InputStream in(communicator, cl->ice_getEncodingVersion(), outEncaps);
741             in.startEncapsulation();
742             try
743             {
744                 in.throwException();
745             }
746             catch(const Test::MyException&)
747             {
748             }
749             catch(...)
750             {
751                 test(false);
752             }
753             in.endEncapsulation();
754         }
755 
756         // begin_ice_invoke with Callback
757         ::CallbackPtr cb = new ::Callback(communicator, false);
758         cl->begin_ice_invoke("opException", Ice::Normal, inEncaps, Ice::newCallback(cb, &Callback::opException));
759         cb->check();
760 
761         // begin_ice_invoke with Callback and Cookie
762         cb = new ::Callback(communicator, true);
763         cl->begin_ice_invoke("opException", Ice::Normal, inEncaps, Ice::newCallback(cb, &Callback::opException),
764                              cookie);
765         cb->check();
766 
767         // begin_ice_invoke with Callback_Object_ice_invoke
768         cb = new ::Callback(communicator, false);
769         Ice::Callback_Object_ice_invokePtr d = Ice::newCallback_Object_ice_invoke(cb, &Callback::opExceptionNC, nullEx);
770         cl->begin_ice_invoke("opException", Ice::Normal, inEncaps, d);
771         cb->check();
772 
773         // begin_ice_invoke with Callback_Object_ice_invoke with Cookie
774         cb = new ::Callback(communicator, false);
775         d = Ice::newCallback_Object_ice_invoke(cb, &Callback::opExceptionWC, nullExWC);
776         cl->begin_ice_invoke("opException", Ice::Normal, inEncaps, d, cookie);
777         cb->check();
778     }
779 #endif
780     cout << "ok" << endl;
781     return cl;
782 }
783