1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <Ice/Ice.h>
6 #include <TestHelper.h>
7 #include <ClientPrivate.h>
8 
9 using namespace std;
10 using namespace Test;
11 
12 namespace
13 {
14 
15 #ifdef ICE_CPP11_MAPPING
16 
17 void breakCycles(shared_ptr<Ice::Value>);
18 
19 template<typename T>
20 void breakCycles(const vector<shared_ptr<T>>& s)
21 {
22     for(auto e : s)
23     {
24         breakCycles(e);
25     }
26 }
27 
28 template<typename K, typename V>
29 void breakCycles(const map<K, shared_ptr<V>>& d)
30 {
31     for(auto e : d)
32     {
33         breakCycles(e.second);
34     }
35 }
36 
37 void breakCycles(shared_ptr<Ice::Value> o)
38 {
39     if(dynamic_pointer_cast<D1>(o))
40     {
41         auto d1 = dynamic_pointer_cast<D1>(o);
42         auto tmp = d1->pd1;
43         d1->pd1 = nullptr;
44         if(tmp != d1)
45         {
46             breakCycles(tmp);
47         }
48     }
49     if(dynamic_pointer_cast<D3>(o))
50     {
51         auto d3 = dynamic_pointer_cast<D3>(o);
52         d3->pd3 = nullptr;
53     }
54     if(dynamic_pointer_cast<B>(o))
55     {
56         auto b = dynamic_pointer_cast<B>(o);
57         if(b->pb != nullptr)
58         {
59             b->pb->pb = nullptr;
60         }
61         b->pb = nullptr;
62     }
63     if(dynamic_pointer_cast<PDerived>(o))
64     {
65         auto p = dynamic_pointer_cast<PDerived>(o);
66         p->pb = nullptr;
67     }
68     if(dynamic_pointer_cast<CompactPDerived>(o))
69     {
70         auto p = dynamic_pointer_cast<CompactPDerived>(o);
71         p->pb = nullptr;
72     }
73     if(dynamic_pointer_cast<PCDerived>(o))
74     {
75         auto p = dynamic_pointer_cast<PCDerived>(o);
76         auto seq(p->pbs);
77         p->pbs.clear();
78         breakCycles(seq);
79     }
80     if(dynamic_pointer_cast<CompactPCDerived>(o))
81     {
82         auto p = dynamic_pointer_cast<CompactPCDerived>(o);
83         auto seq(p->pbs);
84         p->pbs.clear();
85         breakCycles(seq);
86     }
87     if(dynamic_pointer_cast<PCDerived3>(o))
88     {
89         auto p = dynamic_pointer_cast<PCDerived3>(o);
90         p->pcd3 = nullptr;
91     }
92     if(dynamic_pointer_cast<PNode>(o))
93     {
94         auto curr = dynamic_pointer_cast<PNode>(o);
95         while(curr && o != curr->next)
96         {
97             auto next = curr->next;
98             curr->next = nullptr;
99             curr = next;
100         }
101     }
102     if(dynamic_pointer_cast<SS1>(o))
103     {
104         auto s = dynamic_pointer_cast<SS1>(o);
105         breakCycles(s->s);
106     }
107     if(dynamic_pointer_cast<SS2>(o))
108     {
109         auto s = dynamic_pointer_cast<SS2>(o);
110         breakCycles(s->s);
111     }
112     if(dynamic_pointer_cast<Forward>(o))
113     {
114         auto f = dynamic_pointer_cast<Forward>(o);
115         f->h = nullptr;
116     }
117 }
118 #else
119 
120 template<typename T>
121 void breakCycles(T)
122 {
123     // no op, we rely on C++98 collection.
124 }
125 
126 #endif
127 
128 class CallbackBase : public IceUtil::Monitor<IceUtil::Mutex>
129 {
130 public:
131 
132     CallbackBase() :
133         _called(false)
134     {
135     }
136 
137     virtual ~CallbackBase()
138     {
139     }
140 
141     void check()
142     {
143         IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
144         while(!_called)
145         {
146             wait();
147         }
148         _called = false;
149     }
150 
151 protected:
152 
153     void called()
154     {
155         IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
156         assert(!_called);
157         _called = true;
158         notify();
159     }
160 
161 private:
162 
163     bool _called;
164 };
165 
166 class Callback : public CallbackBase
167 #ifndef ICE_CPP11_MAPPING
168                , public virtual IceUtil::Shared
169 #endif
170 {
171 public:
172 
173     void
174     response_SBaseAsObject(const ::Ice::ObjectPtr& o)
175     {
176         test(o);
177         test(o->ice_id(Ice::emptyCurrent) == "::Test::SBase");
178         SBasePtr sb = ICE_DYNAMIC_CAST(SBase, o);
179         test(sb);
180         test(sb->sb == "SBase.sb");
181         called();
182     }
183 
184     void
185     response_SBaseAsSBase(const SBasePtr& sb)
186     {
187         test(sb->sb == "SBase.sb");
188         breakCycles(sb);
189         called();
190     }
191 
192     void
193     response_SBSKnownDerivedAsSBase(const SBasePtr& sb)
194     {
195         SBSKnownDerivedPtr sbskd = ICE_DYNAMIC_CAST(SBSKnownDerived, sb);
196         test(sbskd);
197         test(sbskd->sbskd == "SBSKnownDerived.sbskd");
198         breakCycles(sbskd);
199         called();
200     }
201 
202     void
203     response_SBSKnownDerivedAsSBSKnownDerived(const SBSKnownDerivedPtr& sbskd)
204     {
205         test(sbskd->sbskd == "SBSKnownDerived.sbskd");
206         breakCycles(sbskd);
207         called();
208     }
209 
210     void
211     response_SBSUnknownDerivedAsSBase(const SBasePtr& sb)
212     {
213         test(sb->sb == "SBSUnknownDerived.sb");
214         breakCycles(sb);
215         called();
216     }
217 
218     void
219     response_SBSUnknownDerivedAsSBaseCompact(const SBasePtr&)
220     {
221         test(false);
222     }
223 
224     void
225     exception_SBSUnknownDerivedAsSBaseCompact(const Ice::Exception& exc)
226     {
227         test(exc.ice_id() == "::Ice::NoValueFactoryException");
228         called();
229     }
230 
231     void
232     response_SUnknownAsObject10(const Ice::ObjectPtr&)
233     {
234         test(false);
235     }
236 
237     void
238     exception_SUnknownAsObject10(const Ice::Exception& exc)
239     {
240         test(exc.ice_id() == "::Ice::NoValueFactoryException");
241         called();
242     }
243 
244     void
245     response_SUnknownAsObject11(const Ice::ObjectPtr& o)
246     {
247         test(ICE_DYNAMIC_CAST(Ice::UnknownSlicedValue, o));
248         test(ICE_DYNAMIC_CAST(Ice::UnknownSlicedValue, o)->ice_id() == "::Test::SUnknown");
249         called();
250         ICE_DYNAMIC_CAST(Ice::UnknownSlicedValue, o)->ice_getSlicedData()->clear();
251     }
252 
253     void
254     exception_SUnknownAsObject11(const Ice::Exception&)
255     {
256         test(false);
257     }
258 
259     void
260     response_oneElementCycle(const BPtr& b)
261     {
262         test(b);
263         test(b->ice_id() == "::Test::B");
264         test(b->sb == "B1.sb");
265         test(b->pb == b);
266         breakCycles(b);
267         called();
268     }
269 
270     void
271     response_twoElementCycle(const BPtr& b1)
272     {
273         test(b1);
274         test(b1->ice_id() == "::Test::B");
275         test(b1->sb == "B1.sb");
276 
277         BPtr b2 = b1->pb;
278         test(b2);
279         test(b2->ice_id() == "::Test::B");
280         test(b2->sb == "B2.sb");
281         test(b2->pb == b1);
282         breakCycles(b1);
283         called();
284     }
285 
286     void
287     response_D1AsB(const BPtr& b1)
288     {
289         test(b1);
290         test(b1->ice_id() == "::Test::D1");
291         test(b1->sb == "D1.sb");
292         test(b1->pb);
293         test(b1->pb != b1);
294         D1Ptr d1 = ICE_DYNAMIC_CAST(D1, b1);
295         test(d1);
296         test(d1->sd1 == "D1.sd1");
297         test(d1->pd1);
298         test(d1->pd1 != b1);
299         test(b1->pb == d1->pd1);
300 
301         BPtr b2 = b1->pb;
302         test(b2);
303         test(b2->pb == b1);
304         test(b2->sb == "D2.sb");
305         test(b2->ice_id() == "::Test::B");
306         breakCycles(b1);
307         called();
308     }
309 
310     void
311     response_D1AsD1(const D1Ptr& d1)
312     {
313         test(d1);
314         test(d1->ice_id() == "::Test::D1");
315         test(d1->sb == "D1.sb");
316         test(d1->pb);
317         test(d1->pb != d1);
318 
319         BPtr b2 = d1->pb;
320         test(b2);
321         test(b2->ice_id() == "::Test::B");
322         test(b2->sb == "D2.sb");
323         test(b2->pb == d1);
324         breakCycles(d1);
325         called();
326     }
327 
328     void
329     response_D2AsB(const BPtr& b2)
330     {
331         test(b2);
332         test(b2->ice_id() == "::Test::B");
333         test(b2->sb == "D2.sb");
334         test(b2->pb);
335         test(b2->pb != b2);
336 
337         BPtr b1 = b2->pb;
338         test(b1);
339         test(b1->ice_id() == "::Test::D1");
340         test(b1->sb == "D1.sb");
341         test(b1->pb == b2);
342         D1Ptr d1 = ICE_DYNAMIC_CAST(D1, b1);
343         test(d1);
344         test(d1->sd1 == "D1.sd1");
345         test(d1->pd1 == b2);
346         breakCycles(b2);
347         called();
348     }
349 
350     void
351     response_paramTest1(const BPtr& b1, const BPtr& b2)
352     {
353         test(b1);
354         test(b1->ice_id() == "::Test::D1");
355         test(b1->sb == "D1.sb");
356         test(b1->pb == b2);
357         D1Ptr d1 = ICE_DYNAMIC_CAST(D1, b1);
358         test(d1);
359         test(d1->sd1 == "D1.sd1");
360         test(d1->pd1 == b2);
361 
362         test(b2);
363         test(b2->ice_id() == "::Test::B");      // No factory, must be sliced
364         test(b2->sb == "D2.sb");
365         test(b2->pb == b1);
366         breakCycles(b1);
367         breakCycles(b2);
368         called();
369     }
370 
371     void
372     response_returnTest1(const BPtr& r, const BPtr& p1, const BPtr&)
373     {
374         test(r == p1);
375         breakCycles(r);
376         called();
377     }
378 
379     void
380     response_returnTest2(const BPtr& r, const BPtr& p1, const BPtr&)
381     {
382         test(r == p1);
383         breakCycles(r);
384         called();
385     }
386 
387     void
388     response_returnTest3(const BPtr& b)
389     {
390         rb = b;
391         called();
392     }
393 
394     void
395     response_paramTest3(const BPtr& ret, const BPtr& p1, const BPtr& p2)
396     {
397         test(p1);
398         test(p1->sb == "D2.sb (p1 1)");
399         test(p1->pb == 0);
400         test(p1->ice_id() == "::Test::B");
401 
402         test(p2);
403         test(p2->sb == "D2.sb (p2 1)");
404         test(p2->pb == 0);
405         test(p2->ice_id() == "::Test::B");
406 
407         test(ret);
408         test(ret->sb == "D1.sb (p2 2)");
409         test(ret->pb == 0);
410         test(ret->ice_id() == "::Test::D1");
411         called();
412 
413         breakCycles(ret);
414         breakCycles(p1);
415         breakCycles(p2);
416     }
417 
418     void
419     response_paramTest4(const BPtr& ret, const BPtr& b)
420     {
421         test(b);
422         test(b->sb == "D4.sb (1)");
423         test(b->pb == 0);
424         test(b->ice_id() == "::Test::B");
425 
426         test(ret);
427         test(ret->sb == "B.sb (2)");
428         test(ret->pb == 0);
429         test(ret->ice_id() == "::Test::B");
430         called();
431 
432         breakCycles(ret);
433         breakCycles(b);
434     }
435 
436     void
437     response_sequenceTest(const SS3& ss)
438     {
439         rss3 = ss;
440         called();
441     }
442 
443     void
444     response_dictionaryTest(const BDict& r, const BDict& bout)
445     {
446         rbdict = r;
447         obdict = bout;
448         called();
449     }
450 
451     void
452     exception_throwBaseAsBase(const ::Ice::Exception& ex)
453     {
454         test(ex.ice_id() == "::Test::BaseException");
455         const BaseException& e = dynamic_cast<const BaseException&>(ex);
456         test(e.sbe == "sbe");
457         test(e.pb);
458         test(e.pb->sb == "sb");
459         test(e.pb->pb == e.pb);
460         called();
461         breakCycles(e.pb);
462     }
463 
464     void
465     exception_throwDerivedAsBase(const ::Ice::Exception& ex)
466     {
467         test(ex.ice_id() == "::Test::DerivedException");
468         const DerivedException& e = dynamic_cast<const DerivedException&>(ex);
469         test(e.sbe == "sbe");
470         test(e.pb);
471         test(e.pb->sb == "sb1");
472         test(e.pb->pb == e.pb);
473         test(e.sde == "sde1");
474         test(e.pd1);
475         test(e.pd1->sb == "sb2");
476         test(e.pd1->pb == e.pd1);
477         test(e.pd1->sd1 == "sd2");
478         test(e.pd1->pd1 == e.pd1);
479         called();
480     }
481 
482     void
483     exception_throwDerivedAsDerived(const ::Ice::Exception& ex)
484     {
485         test(ex.ice_id() == "::Test::DerivedException");
486         const DerivedException& e = dynamic_cast<const DerivedException&>(ex);
487         test(e.sbe == "sbe");
488         test(e.pb);
489         test(e.pb->sb == "sb1");
490         test(e.pb->pb == e.pb);
491         test(e.sde == "sde1");
492         test(e.pd1);
493         test(e.pd1->sb == "sb2");
494         test(e.pd1->pb == e.pd1);
495         test(e.pd1->sd1 == "sd2");
496         test(e.pd1->pd1 == e.pd1);
497         called();
498     }
499 
500     void
501     exception_throwUnknownDerivedAsBase(const ::Ice::Exception& ex)
502     {
503         test(ex.ice_id() == "::Test::BaseException");
504         const BaseException& e = dynamic_cast<const BaseException&>(ex);
505         test(e.sbe == "sbe");
506         test(e.pb);
507         test(e.pb->sb == "sb d2");
508         test(e.pb->pb == e.pb);
509         called();
510         breakCycles(e.pb);
511     }
512 
513     void
514     response_preserved1(const PBasePtr& r)
515     {
516         PDerivedPtr pd = ICE_DYNAMIC_CAST(PDerived, r);
517         test(pd);
518         test(pd->pi == 3);
519         test(pd->ps == "preserved");
520         test(pd->pb == pd);
521         called();
522 
523         breakCycles(r);
524     }
525 
526     void
527     response_preserved2(const PBasePtr& r)
528     {
529         PCUnknownPtr p2 = ICE_DYNAMIC_CAST(PCUnknown, r);
530         test(!p2);
531         test(r->pi == 3);
532         called();
533 
534         breakCycles(r);
535     }
536 
537     void
538     response_preserved3(const PBasePtr& r)
539     {
540         //
541         // Encoding 1.0
542         //
543         PCDerivedPtr p2 = ICE_DYNAMIC_CAST(PCDerived, r);
544         test(!p2);
545         test(r->pi == 3);
546         called();
547 
548         breakCycles(r);
549     }
550 
551     void
552     response_preserved4(const PBasePtr& r)
553     {
554         //
555         // Encoding > 1.0
556         //
557         PCDerivedPtr p2 = ICE_DYNAMIC_CAST(PCDerived, r);
558         test(p2);
559         test(p2->pi == 3);
560         test(p2->pbs[0] == p2);
561         called();
562 
563         breakCycles(r);
564     }
565 
566     void
567     response_preserved5(const PBasePtr& r)
568     {
569         PCDerived3Ptr p3 = ICE_DYNAMIC_CAST(PCDerived3, r);
570         test(p3);
571         test(p3->pi == 3);
572         for(int i = 0; i < 300; ++i)
573         {
574             PCDerived2Ptr p2 = ICE_DYNAMIC_CAST(PCDerived2, p3->pbs[i]);
575             test(p2->pi == i);
576             test(p2->pbs.size() == 1);
577             test(!p2->pbs[0]);
578             test(p2->pcd2 == i);
579         }
580         test(p3->pcd2 == p3->pi);
581         test(p3->pcd3 == p3->pbs[10]);
582         called();
583 
584         breakCycles(r);
585     }
586 
587     void
588     response_compactPreserved1(const PBasePtr& r)
589     {
590         //
591         // Encoding 1.0
592         //
593         CompactPCDerivedPtr p2 = ICE_DYNAMIC_CAST(CompactPCDerived, r);
594         test(!p2);
595         test(r->pi == 3);
596         called();
597 
598         breakCycles(r);
599     }
600 
601     void
602     response_compactPreserved2(const PBasePtr& r)
603     {
604         //
605         // Encoding > 1.0
606         //
607         CompactPCDerivedPtr p2 = ICE_DYNAMIC_CAST(CompactPCDerived, r);
608         test(p2);
609         test(p2->pi == 3);
610         test(p2->pbs[0] == p2);
611         called();
612 
613         breakCycles(r);
614     }
615 
616     void
617     response()
618     {
619         test(false);
620     }
621 
622     void
623     exception(const ::Ice::Exception& ex)
624     {
625         if(!dynamic_cast<const Ice::OperationNotExistException*>(&ex))
626         {
627             test(false);
628         }
629         else
630         {
631             called();
632         }
633     }
634 
635     BPtr rb;
636     SS3 rss3;
637     BDict rbdict;
638     BDict obdict;
639 };
640 ICE_DEFINE_PTR(CallbackPtr, Callback);
641 
642 class PNodeI : public virtual PNode
643 {
644 public:
645 
646     PNodeI()
647     {
648         ++counter;
649     }
650 
651     virtual ~PNodeI()
652     {
653         --counter;
654     }
655 
656     static int counter;
657 };
658 
659 int PNodeI::counter = 0;
660 
661 #ifndef ICE_CPP11_MAPPING
662 class NodeFactoryI : public Ice::ValueFactory
663 {
664 public:
665 
666     virtual Ice::ObjectPtr create(const string& id)
667     {
668         if(id == PNode::ice_staticId())
669         {
670             return new PNodeI;
671         }
672         return 0;
673     }
674 
675     virtual void destroy()
676     {
677     }
678 };
679 #endif
680 
681 class PreservedI : public virtual Preserved
682 {
683 public:
684 
685     PreservedI()
686     {
687         ++counter;
688     }
689 
690     virtual ~PreservedI()
691     {
692         --counter;
693     }
694 
695     static int counter;
696 };
697 
698 int PreservedI::counter = 0;
699 
700 #ifndef ICE_CPP11_MAPPING
701 class PreservedFactoryI : public Ice::ValueFactory
702 {
703 public:
704 
705     virtual Ice::ObjectPtr create(const string& id)
706     {
707         if(id == Preserved::ice_staticId())
708         {
709             return new PreservedI;
710         }
711         return 0;
712     }
713 
714     virtual void destroy()
715     {
716     }
717 };
718 #endif
719 
720 void
721 testUOO(const TestIntfPrxPtr& test)
722 {
723     Ice::ValuePtr o;
724     try
725     {
726         o = test->SUnknownAsObject();
727         test(test->ice_getEncodingVersion() != Ice::Encoding_1_0);
728         test(ICE_DYNAMIC_CAST(Ice::UnknownSlicedValue, o));
729         test(ICE_DYNAMIC_CAST(Ice::UnknownSlicedValue, o)->ice_id() == "::Test::SUnknown");
730         test(ICE_DYNAMIC_CAST(Ice::UnknownSlicedValue, o)->ice_getSlicedData());
731         test->checkSUnknown(o);
732         ICE_DYNAMIC_CAST(Ice::UnknownSlicedValue, o)->ice_getSlicedData()->clear();
733     }
734     catch(const Ice::NoValueFactoryException&)
735     {
736         test(test->ice_getEncodingVersion() == Ice::Encoding_1_0);
737     }
738     catch(const std::exception& ex)
739     {
740         cout << ex.what() << endl;
741         test(false);
742     }
743     catch(...)
744     {
745         test(false);
746     }
747 }
748 
749 }
750 
751 TestIntfPrxPtr
752 allTests(Test::TestHelper* helper)
753 {
754     Ice::CommunicatorPtr communicator = helper->communicator();
755     Ice::ObjectPrxPtr obj = communicator->stringToProxy("Test:" + helper->getTestEndpoint());
756     TestIntfPrxPtr test = ICE_CHECKED_CAST(TestIntfPrx, obj);
757 
758     cout << "base as Object... " << flush;
759     {
760         Ice::ValuePtr o;
761         try
762         {
763             o = test->SBaseAsObject();
764             test(o);
765             test(o->ice_id() == "::Test::SBase");
766         }
767         catch(const std::exception& ex)
768         {
769             cerr << ex.what() << endl;
770             test(false);
771         }
772         catch(...)
773         {
774             test(false);
775         }
776         SBasePtr sb = ICE_DYNAMIC_CAST(SBase, o);
777         test(sb);
778         test(sb->sb == "SBase.sb");
779     }
780     cout << "ok" << endl;
781 
782     cout << "base as Object (AMI)... " << flush;
783     {
784 #ifdef ICE_CPP11_MAPPING
785         auto f = test->SBaseAsObjectAsync();
786         try
787         {
788             auto o = f.get();
789             test(o);
790             test(o->ice_id() == "::Test::SBase");
791             auto sb = dynamic_pointer_cast<SBase>(o);
792             test(sb);
793             test(sb->sb == "SBase.sb");
794         }
795         catch(...)
796         {
797             test(false);
798         }
799 #else
800         CallbackPtr cb = new Callback();
801         test->begin_SBaseAsObject(
802             newCallback_TestIntf_SBaseAsObject(cb, &Callback::response_SBaseAsObject, &Callback::exception));
803         cb->check();
804 #endif
805     }
806     cout << "ok" << endl;
807 
808     cout << "base as base... " << flush;
809     {
810         SBasePtr sb;
811         try
812         {
813             sb = test->SBaseAsSBase();
814             test(sb->sb == "SBase.sb");
815         }
816         catch(...)
817         {
818             test(false);
819         }
820     }
821     cout << "ok" << endl;
822 
823     cout << "base as base (AMI)... " << flush;
824     {
825 #ifdef ICE_CPP11_MAPPING
826         try
827         {
828             auto sb = test->SBaseAsSBaseAsync().get();
829             test(sb->sb == "SBase.sb");
830         }
831         catch(...)
832         {
833             test(false);
834         }
835 #else
836         CallbackPtr cb = new Callback;
837         test->begin_SBaseAsSBase(
838             newCallback_TestIntf_SBaseAsSBase(cb, &Callback::response_SBaseAsSBase, &Callback::exception));
839         cb->check();
840 #endif
841     }
842     cout << "ok" << endl;
843 
844     cout << "base with known derived as base... " << flush;
845     {
846         SBasePtr sb;
847         try
848         {
849             sb = test->SBSKnownDerivedAsSBase();
850             test(sb->sb == "SBSKnownDerived.sb");
851         }
852         catch(...)
853         {
854             test(false);
855         }
856         SBSKnownDerivedPtr sbskd = ICE_DYNAMIC_CAST(SBSKnownDerived, sb);
857         test(sbskd);
858         test(sbskd->sbskd == "SBSKnownDerived.sbskd");
859     }
860     cout << "ok" << endl;
861 
862     cout << "base with known derived as base (AMI)... " << flush;
863     {
864 #ifdef ICE_CPP11_MAPPING
865         auto f = test->SBSKnownDerivedAsSBaseAsync();
866         try
867         {
868             shared_ptr<SBase> sb = f.get();
869             sb = test->SBSKnownDerivedAsSBase();
870             test(sb->sb == "SBSKnownDerived.sb");
871             SBSKnownDerivedPtr sbskd = ICE_DYNAMIC_CAST(SBSKnownDerived, sb);
872             test(sbskd);
873             test(sbskd->sbskd == "SBSKnownDerived.sbskd");
874         }
875         catch(...)
876         {
877             test(false);
878         }
879 #else
880         CallbackPtr cb = new Callback;
881         test->begin_SBSKnownDerivedAsSBase(
882             newCallback_TestIntf_SBSKnownDerivedAsSBase(
883                 cb, &Callback::response_SBSKnownDerivedAsSBase, &Callback::exception));
884         cb->check();
885 #endif
886     }
887     cout << "ok" << endl;
888 
889     cout << "base with known derived as known derived... " << flush;
890     {
891         SBSKnownDerivedPtr sbskd;
892         try
893         {
894             sbskd = test->SBSKnownDerivedAsSBSKnownDerived();
895             test(sbskd->sbskd == "SBSKnownDerived.sbskd");
896         }
897         catch(...)
898         {
899             test(false);
900         }
901     }
902     cout << "ok" << endl;
903 
904     cout << "base with known derived as known derived (AMI)... " << flush;
905     {
906 #ifdef ICE_CPP11_MAPPING
907         auto f = test->SBSKnownDerivedAsSBSKnownDerivedAsync();
908         try
909         {
910             SBSKnownDerivedPtr sbskd = test->SBSKnownDerivedAsSBSKnownDerived();
911             test(sbskd->sbskd == "SBSKnownDerived.sbskd");
912         }
913         catch(...)
914         {
915             test(false);
916         }
917 #else
918         CallbackPtr cb = new Callback;
919         test->begin_SBSKnownDerivedAsSBSKnownDerived(
920             newCallback_TestIntf_SBSKnownDerivedAsSBSKnownDerived(
921                 cb, &Callback::response_SBSKnownDerivedAsSBSKnownDerived, &Callback::exception));
922         cb->check();
923 #endif
924     }
925     cout << "ok" << endl;
926 
927     cout << "base with unknown derived as base... " << flush;
928     {
929         SBasePtr sb;
930         try
931         {
932             sb = test->SBSUnknownDerivedAsSBase();
933             test(sb->sb == "SBSUnknownDerived.sb");
934         }
935         catch(...)
936         {
937             test(false);
938         }
939     }
940     if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
941     {
942         try
943         {
944             //
945             // This test succeeds for the 1.0 encoding.
946             //
947             SBasePtr sb = test->SBSUnknownDerivedAsSBaseCompact();
948             test(sb->sb == "SBSUnknownDerived.sb");
949         }
950         catch(const Ice::OperationNotExistException&)
951         {
952         }
953         catch(...)
954         {
955             test(false);
956         }
957     }
958     else
959     {
960         try
961         {
962             //
963             // This test fails when using the compact format because the instance cannot
964             // be sliced to a known type.
965             //
966             SBasePtr sb = test->SBSUnknownDerivedAsSBaseCompact();
967             test(false);
968         }
969         catch(const Ice::OperationNotExistException&)
970         {
971         }
972         catch(const Ice::NoValueFactoryException&)
973         {
974             // Expected.
975         }
976         catch(...)
977         {
978             test(false);
979         }
980     }
981     cout << "ok" << endl;
982 
983     cout << "base with unknown derived as base (AMI)... " << flush;
984     {
985 #ifdef ICE_CPP11_MAPPING
986         auto f = test->SBSUnknownDerivedAsSBaseAsync();
987         try
988         {
989             SBasePtr sb = f.get();
990             test(sb->sb == "SBSUnknownDerived.sb");
991         }
992         catch(...)
993         {
994             test(false);
995         }
996 #else
997         CallbackPtr cb = new Callback;
998         test->begin_SBSUnknownDerivedAsSBase(
999             newCallback_TestIntf_SBSUnknownDerivedAsSBase(
1000                 cb, &Callback::response_SBSUnknownDerivedAsSBase, &Callback::exception));
1001         cb->check();
1002 #endif
1003     }
1004     if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
1005     {
1006         //
1007         // This test succeeds for the 1.0 encoding.
1008         //
1009 #ifdef ICE_CPP11_MAPPING
1010         auto f = test->SBSUnknownDerivedAsSBaseCompactAsync();
1011         try
1012         {
1013             SBasePtr sb = f.get();
1014             test(sb->sb == "SBSUnknownDerived.sb");
1015         }
1016         catch(...)
1017         {
1018             test(false);
1019         }
1020 #else
1021         CallbackPtr cb = new Callback;
1022         test->begin_SBSUnknownDerivedAsSBaseCompact(
1023             newCallback_TestIntf_SBSUnknownDerivedAsSBaseCompact(
1024                 cb, &Callback::response_SBSUnknownDerivedAsSBase, &Callback::exception));
1025         cb->check();
1026 #endif
1027     }
1028     else
1029     {
1030         //
1031         // This test fails when using the compact format because the instance cannot
1032         // be sliced to a known type.
1033         //
1034 #ifdef ICE_CPP11_MAPPING
1035         auto f = test->SBSUnknownDerivedAsSBaseCompactAsync();
1036         try
1037         {
1038             f.get();
1039             test(false);
1040         }
1041         catch(const Ice::NoValueFactoryException&)
1042         {
1043         }
1044         catch(...)
1045         {
1046             test(false);
1047         }
1048 #else
1049         CallbackPtr cb = new Callback;
1050         test->begin_SBSUnknownDerivedAsSBaseCompact(
1051             newCallback_TestIntf_SBSUnknownDerivedAsSBaseCompact(
1052                 cb, &Callback::response_SBSUnknownDerivedAsSBaseCompact,
1053                 &Callback::exception_SBSUnknownDerivedAsSBaseCompact));
1054         cb->check();
1055 #endif
1056     }
1057     cout << "ok" << endl;
1058 
1059     cout << "unknown with Object as Object... " << flush;
1060     {
1061         testUOO(test);
1062     }
1063     cout << "ok" << endl;
1064 
1065     cout << "unknown with Object as Object (AMI)... " << flush;
1066     {
1067         try
1068         {
1069 #ifdef ICE_CPP11_MAPPING
1070             if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
1071             {
1072                 auto f = test->SUnknownAsObjectAsync();
1073                 try
1074                 {
1075                     f.get();
1076                     test(false);
1077                 }
1078                 catch(const Ice::NoValueFactoryException&)
1079                 {
1080                 }
1081                 catch(...)
1082                 {
1083                     test(false);
1084                 }
1085             }
1086             else
1087             {
1088                 auto f = test->SUnknownAsObjectAsync();
1089                 try
1090                 {
1091                     shared_ptr<Ice::Value> v = f.get();
1092                     test(dynamic_pointer_cast<Ice::UnknownSlicedValue>(v));
1093                     test(dynamic_pointer_cast<Ice::UnknownSlicedValue>(v)->ice_id() == "::Test::SUnknown");
1094                     dynamic_pointer_cast<Ice::UnknownSlicedValue>(v)->ice_getSlicedData()->clear();
1095                 }
1096                 catch(...)
1097                 {
1098                     test(false);
1099                 }
1100             }
1101 #else
1102             CallbackPtr cb = new Callback;
1103             if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
1104             {
1105                 test->begin_SUnknownAsObject(
1106                     newCallback_TestIntf_SUnknownAsObject(
1107                         cb, &Callback::response_SUnknownAsObject10, &Callback::exception_SUnknownAsObject10));
1108             }
1109             else
1110             {
1111                 test->begin_SUnknownAsObject(
1112                     newCallback_TestIntf_SUnknownAsObject(
1113                         cb, &Callback::response_SUnknownAsObject11, &Callback::exception_SUnknownAsObject11));
1114             }
1115             cb->check();
1116 #endif
1117         }
1118         catch(...)
1119         {
1120             test(false);
1121         }
1122     }
1123     cout << "ok" << endl;
1124 
1125     cout << "one-element cycle... " << flush;
1126     {
1127         try
1128         {
1129             BPtr b = test->oneElementCycle();
1130             test(b);
1131             test(b->ice_id() == "::Test::B");
1132             test(b->sb == "B1.sb");
1133             test(b->pb == b);
1134 
1135             breakCycles(b);
1136         }
1137         catch(...)
1138         {
1139             test(false);
1140         }
1141     }
1142     cout << "ok" << endl;
1143 
1144     cout << "one-element cycle (AMI)... " << flush;
1145     {
1146 #ifdef ICE_CPP11_MAPPING
1147         auto f = test->oneElementCycleAsync();
1148         try
1149         {
1150             auto b = f.get();
1151             test(b);
1152             test(b->ice_id() == "::Test::B");
1153             test(b->sb == "B1.sb");
1154             test(b->pb == b);
1155 
1156             breakCycles(b);
1157         }
1158         catch(...)
1159         {
1160             test(false);
1161         }
1162 #else
1163         CallbackPtr cb = new Callback;
1164         test->begin_oneElementCycle(
1165             newCallback_TestIntf_oneElementCycle(
1166                 cb, &Callback::response_oneElementCycle, &Callback::exception));
1167         cb->check();
1168 #endif
1169     }
1170     cout << "ok" << endl;
1171 
1172     cout << "two-element cycle... " << flush;
1173     {
1174         try
1175         {
1176             BPtr b1 = test->twoElementCycle();
1177             test(b1);
1178             test(b1->ice_id() == "::Test::B");
1179             test(b1->sb == "B1.sb");
1180 
1181             BPtr b2 = b1->pb;
1182             test(b2);
1183             test(b2->ice_id() == "::Test::B");
1184             test(b2->sb == "B2.sb");
1185             test(b2->pb == b1);
1186 
1187             breakCycles(b1);
1188             breakCycles(b2);
1189         }
1190         catch(...)
1191         {
1192             test(false);
1193         }
1194     }
1195     cout << "ok" << endl;
1196 
1197     cout << "two-element cycle (AMI)... " << flush;
1198     {
1199 #ifdef ICE_CPP11_MAPPING
1200         auto f = test->twoElementCycleAsync();
1201         try
1202         {
1203             auto b1 = f.get();
1204             test(b1);
1205             test(b1->ice_id() == "::Test::B");
1206             test(b1->sb == "B1.sb");
1207 
1208             auto b2 = b1->pb;
1209             test(b2);
1210             test(b2->ice_id() == "::Test::B");
1211             test(b2->sb == "B2.sb");
1212             test(b2->pb == b1);
1213 
1214             breakCycles(b1);
1215             breakCycles(b2);
1216         }
1217         catch(...)
1218         {
1219             test(false);
1220         }
1221 #else
1222         CallbackPtr cb = new Callback;
1223         test->begin_twoElementCycle(
1224             newCallback_TestIntf_twoElementCycle(
1225                 cb, &Callback::response_twoElementCycle, &Callback::exception));
1226         cb->check();
1227 #endif
1228     }
1229     cout << "ok" << endl;
1230 
1231     cout << "known derived pointer slicing as base... " << flush;
1232     {
1233         try
1234         {
1235             BPtr b1;
1236             b1 = test->D1AsB();
1237             test(b1);
1238             test(b1->ice_id() == "::Test::D1");
1239             test(b1->sb == "D1.sb");
1240             test(b1->pb);
1241             test(b1->pb != b1);
1242             D1Ptr d1 = ICE_DYNAMIC_CAST(D1, b1);
1243             test(d1);
1244             test(d1->sd1 == "D1.sd1");
1245             test(d1->pd1);
1246             test(d1->pd1 != b1);
1247             test(b1->pb == d1->pd1);
1248 
1249             BPtr b2 = b1->pb;
1250             test(b2);
1251             test(b2->pb == b1);
1252             test(b2->sb == "D2.sb");
1253             test(b2->ice_id() == "::Test::B");
1254 
1255             breakCycles(b1);
1256         }
1257         catch(...)
1258         {
1259             test(false);
1260         }
1261     }
1262     cout << "ok" << endl;
1263 
1264     cout << "known derived pointer slicing as base (AMI)... " << flush;
1265     {
1266 #ifdef ICE_CPP11_MAPPING
1267         auto f = test->D1AsBAsync();
1268         try
1269         {
1270             auto b1 = f.get();
1271             test(b1);
1272             test(b1->ice_id() == "::Test::D1");
1273             test(b1->sb == "D1.sb");
1274             test(b1->pb);
1275             test(b1->pb != b1);
1276             auto d1 = dynamic_pointer_cast<D1>(b1);
1277             test(d1);
1278             test(d1->sd1 == "D1.sd1");
1279             test(d1->pd1);
1280             test(d1->pd1 != b1);
1281             test(b1->pb == d1->pd1);
1282 
1283             auto b2 = b1->pb;
1284             test(b2);
1285             test(b2->pb == b1);
1286             test(b2->sb == "D2.sb");
1287             test(b2->ice_id() == "::Test::B");
1288 
1289             breakCycles(b1);
1290         }
1291         catch(...)
1292         {
1293             test(false);
1294         }
1295 #else
1296         CallbackPtr cb = new Callback;
1297         test->begin_D1AsB(newCallback_TestIntf_D1AsB(cb, &Callback::response_D1AsB, &Callback::exception));
1298         cb->check();
1299 #endif
1300     }
1301     cout << "ok" << endl;
1302 
1303     cout << "known derived pointer slicing as derived... " << flush;
1304     {
1305         try
1306         {
1307             D1Ptr d1;
1308             d1 = test->D1AsD1();
1309             test(d1);
1310             test(d1->ice_id() == "::Test::D1");
1311             test(d1->sb == "D1.sb");
1312             test(d1->pb);
1313             test(d1->pb != d1);
1314 
1315             BPtr b2 = d1->pb;
1316             test(b2);
1317             test(b2->ice_id() == "::Test::B");
1318             test(b2->sb == "D2.sb");
1319             test(b2->pb == d1);
1320 
1321             breakCycles(d1);
1322         }
1323         catch(...)
1324         {
1325             test(false);
1326         }
1327     }
1328     cout << "ok" << endl;
1329 
1330     cout << "known derived pointer slicing as derived (AMI)... " << flush;
1331     {
1332 #ifdef ICE_CPP11_MAPPING
1333         auto f = test->D1AsD1Async();
1334         try
1335         {
1336             auto d1 = f.get();
1337             test(d1);
1338             test(d1->ice_id() == "::Test::D1");
1339             test(d1->sb == "D1.sb");
1340             test(d1->pb);
1341             test(d1->pb != d1);
1342 
1343             auto b2 = d1->pb;
1344             test(b2);
1345             test(b2->ice_id() == "::Test::B");
1346             test(b2->sb == "D2.sb");
1347             test(b2->pb == d1);
1348 
1349             breakCycles(d1);
1350         }
1351         catch(...)
1352         {
1353             test(false);
1354         }
1355 #else
1356         CallbackPtr cb = new Callback;
1357         test->begin_D1AsD1(newCallback_TestIntf_D1AsD1(cb, &Callback::response_D1AsD1, &Callback::exception));
1358         cb->check();
1359 #endif
1360     }
1361     cout << "ok" << endl;
1362 
1363     cout << "unknown derived pointer slicing as base... " << flush;
1364     {
1365         try
1366         {
1367             BPtr b2;
1368             b2 = test->D2AsB();
1369             test(b2);
1370             test(b2->ice_id() == "::Test::B");
1371             test(b2->sb == "D2.sb");
1372             test(b2->pb);
1373             test(b2->pb != b2);
1374 
1375             BPtr b1 = b2->pb;
1376             test(b1);
1377             test(b1->ice_id() == "::Test::D1");
1378             test(b1->sb == "D1.sb");
1379             test(b1->pb == b2);
1380             D1Ptr d1 = ICE_DYNAMIC_CAST(D1, b1);
1381             test(d1);
1382             test(d1->sd1 == "D1.sd1");
1383             test(d1->pd1 == b2);
1384 
1385             breakCycles(b2);
1386         }
1387         catch(...)
1388         {
1389             test(false);
1390         }
1391     }
1392     cout << "ok" << endl;
1393 
1394     cout << "unknown derived pointer slicing as base (AMI)... " << flush;
1395     {
1396 #ifdef ICE_CPP11_MAPPING
1397         auto f = test->D2AsBAsync();
1398         try
1399         {
1400             auto b2 = f.get();
1401             test(b2);
1402             test(b2->ice_id() == "::Test::B");
1403             test(b2->sb == "D2.sb");
1404             test(b2->pb);
1405             test(b2->pb != b2);
1406 
1407             auto b1 = b2->pb;
1408             test(b1);
1409             test(b1->ice_id() == "::Test::D1");
1410             test(b1->sb == "D1.sb");
1411             test(b1->pb == b2);
1412             auto d1 = dynamic_pointer_cast<D1>(b1);
1413             test(d1);
1414             test(d1->sd1 == "D1.sd1");
1415             test(d1->pd1 == b2);
1416 
1417             breakCycles(b2);
1418         }
1419         catch(...)
1420         {
1421             test(false);
1422         }
1423 #else
1424         CallbackPtr cb = new Callback;
1425         test->begin_D2AsB(newCallback_TestIntf_D2AsB(cb, &Callback::response_D2AsB, &Callback::exception));
1426         cb->check();
1427 #endif
1428     }
1429     cout << "ok" << endl;
1430 
1431     cout << "param ptr slicing with known first... " << flush;
1432     {
1433         try
1434         {
1435             BPtr b1;
1436             BPtr b2;
1437             test->paramTest1(b1, b2);
1438 
1439             test(b1);
1440             test(b1->ice_id() == "::Test::D1");
1441             test(b1->sb == "D1.sb");
1442             test(b1->pb == b2);
1443             D1Ptr d1 = ICE_DYNAMIC_CAST(D1, b1);
1444             test(d1);
1445             test(d1->sd1 == "D1.sd1");
1446             test(d1->pd1 == b2);
1447 
1448             test(b2);
1449             test(b2->ice_id() == "::Test::B");  // No factory, must be sliced
1450             test(b2->sb == "D2.sb");
1451             test(b2->pb == b1);
1452 
1453             breakCycles(b1);
1454             breakCycles(b2);
1455         }
1456         catch(...)
1457         {
1458             test(false);
1459         }
1460     }
1461     cout << "ok" << endl;
1462 
1463     cout << "param ptr slicing with known first (AMI)... " << flush;
1464     {
1465 #ifdef ICE_CPP11_MAPPING
1466         auto f = test->paramTest1Async();
1467         try
1468         {
1469             auto result = f.get();
1470             auto b1 = move(result.p1);
1471             auto b2 = move(result.p2);
1472 
1473             test(b1);
1474             test(b1->ice_id() == "::Test::D1");
1475             test(b1->sb == "D1.sb");
1476             test(b1->pb == b2);
1477             D1Ptr d1 = ICE_DYNAMIC_CAST(D1, b1);
1478             test(d1);
1479             test(d1->sd1 == "D1.sd1");
1480             test(d1->pd1 == b2);
1481 
1482             test(b2);
1483             test(b2->ice_id() == "::Test::B");  // No factory, must be sliced
1484             test(b2->sb == "D2.sb");
1485             test(b2->pb == b1);
1486 
1487             breakCycles(b1);
1488             breakCycles(b2);
1489         }
1490         catch(...)
1491         {
1492             test(false);
1493         }
1494 #else
1495         CallbackPtr cb = new Callback;
1496         test->begin_paramTest1(
1497             newCallback_TestIntf_paramTest1(cb, &Callback::response_paramTest1, &Callback::exception));
1498         cb->check();
1499 #endif
1500     }
1501     cout << "ok" << endl;
1502 
1503     cout << "param ptr slicing with unknown first... " << flush;
1504     {
1505         try
1506         {
1507             BPtr b2;
1508             BPtr b1;
1509             test->paramTest2(b2, b1);
1510 
1511             test(b1);
1512             test(b1->ice_id() == "::Test::D1");
1513             test(b1->sb == "D1.sb");
1514             test(b1->pb == b2);
1515             D1Ptr d1 = ICE_DYNAMIC_CAST(D1, b1);
1516             test(d1);
1517             test(d1->sd1 == "D1.sd1");
1518             test(d1->pd1 == b2);
1519 
1520             test(b2);
1521             test(b2->ice_id() == "::Test::B");  // No factory, must be sliced
1522             test(b2->sb == "D2.sb");
1523             test(b2->pb == b1);
1524 
1525             breakCycles(b1);
1526             breakCycles(b2);
1527         }
1528         catch(...)
1529         {
1530             test(false);
1531         }
1532     }
1533     cout << "ok" << endl;
1534 
1535     cout << "return value identity with known first... " << flush;
1536     {
1537         try
1538         {
1539             BPtr p1;
1540             BPtr p2;
1541             BPtr r = test->returnTest1(p1, p2);
1542             test(r == p1);
1543 
1544             breakCycles(r);
1545             breakCycles(p1);
1546             breakCycles(p2);
1547         }
1548         catch(...)
1549         {
1550             test(false);
1551         }
1552     }
1553     cout << "ok" << endl;
1554 
1555     cout << "return value identity with known first (AMI)... " << flush;
1556     {
1557 #ifdef ICE_CPP11_MAPPING
1558         auto f = test->returnTest1Async();
1559         try
1560         {
1561             auto result = f.get();
1562             test(result.returnValue == result.p1);
1563 
1564             breakCycles(result.returnValue);
1565             breakCycles(result.p1);
1566         }
1567         catch(...)
1568         {
1569             test(false);
1570         }
1571 #else
1572         CallbackPtr cb = new Callback;
1573         test->begin_returnTest1(
1574             newCallback_TestIntf_returnTest1(cb, &Callback::response_returnTest1, &Callback::exception));
1575         cb->check();
1576 #endif
1577     }
1578     cout << "ok" << endl;
1579 
1580     cout << "return value identity with unknown first... " << flush;
1581     {
1582         try
1583         {
1584             BPtr p1;
1585             BPtr p2;
1586             BPtr r = test->returnTest2(p1, p2);
1587             test(r == p1);
1588 
1589             breakCycles(r);
1590             breakCycles(p1);
1591             breakCycles(p2);
1592         }
1593         catch(...)
1594         {
1595             test(false);
1596         }
1597     }
1598     cout << "ok" << endl;
1599 
1600     cout << "return value identity with unknown first (AMI)... " << flush;
1601     {
1602 #ifdef ICE_CPP11_MAPPING
1603         auto f = test->returnTest2Async();
1604         try
1605         {
1606             auto result = f.get();
1607             test(result.returnValue == result.p2);
1608 
1609             breakCycles(result.returnValue);
1610             breakCycles(result.p2);
1611         }
1612         catch(...)
1613         {
1614             test(false);
1615         }
1616 #else
1617         CallbackPtr cb = new Callback;
1618         test->begin_returnTest2(
1619             newCallback_TestIntf_returnTest2(cb, &Callback::response_returnTest2, &Callback::exception));
1620         cb->check();
1621 #endif
1622     }
1623     cout << "ok" << endl;
1624 
1625     cout << "return value identity for input params known first... " << flush;
1626     {
1627         try
1628         {
1629             D1Ptr d1 = ICE_MAKE_SHARED(D1);
1630             d1->sb = "D1.sb";
1631             d1->sd1 = "D1.sd1";
1632             D3Ptr d3 = ICE_MAKE_SHARED(D3);
1633             d3->pb = d1;
1634             d3->sb = "D3.sb";
1635             d3->sd3 = "D3.sd3";
1636             d3->pd3 = d1;
1637             d1->pb = d3;
1638             d1->pd1 = d3;
1639 #ifndef ICE_CPP11_MAPPING
1640             d1->ice_collectable(true);
1641 #endif
1642 
1643             BPtr b1 = test->returnTest3(d1, d3);
1644 
1645             test(b1);
1646             test(b1->sb == "D1.sb");
1647             test(b1->ice_id() == "::Test::D1");
1648             D1Ptr p1 = ICE_DYNAMIC_CAST(D1, b1);
1649             test(p1);
1650             test(p1->sd1 == "D1.sd1");
1651             test(p1->pd1 == b1->pb);
1652 
1653             BPtr b2 = b1->pb;
1654             test(b2);
1655             test(b2->sb == "D3.sb");
1656             test(b2->ice_id() == "::Test::B");  // Sliced by server
1657             test(b2->pb == b1);
1658             D3Ptr p3 = ICE_DYNAMIC_CAST(D3, b2);
1659             test(!p3);
1660 
1661             test(b1 != d1);
1662             test(b1 != d3);
1663             test(b2 != d1);
1664             test(b2 != d3);
1665 
1666             breakCycles(b1);
1667             breakCycles(d1);
1668             breakCycles(d3);
1669         }
1670         catch(...)
1671         {
1672             test(false);
1673         }
1674     }
1675     cout << "ok" << endl;
1676 
1677     cout << "return value identity for input params known first (AMI)... " << flush;
1678     {
1679         try
1680         {
1681             D1Ptr d1 = ICE_MAKE_SHARED(D1);
1682             d1->sb = "D1.sb";
1683             d1->sd1 = "D1.sd1";
1684             D3Ptr d3 = ICE_MAKE_SHARED(D3);
1685             d3->pb = d1;
1686             d3->sb = "D3.sb";
1687             d3->sd3 = "D3.sd3";
1688             d3->pd3 = d1;
1689             d1->pb = d3;
1690             d1->pd1 = d3;
1691 #ifndef ICE_CPP11_MAPPING
1692             d1->ice_collectable(true);
1693 #endif
1694 
1695 #ifdef ICE_CPP11_MAPPING
1696             auto f = test->returnTest3Async(d1, d3);
1697             auto b1 = f.get();
1698 #else
1699             CallbackPtr cb = new Callback;
1700             test->begin_returnTest3(d1, d3,
1701                 newCallback_TestIntf_returnTest3(cb, &Callback::response_returnTest3, &Callback::exception));
1702             cb->check();
1703             BPtr b1 = cb->rb;
1704 #endif
1705 
1706             test(b1);
1707             test(b1->sb == "D1.sb");
1708             test(b1->ice_id() == "::Test::D1");
1709             D1Ptr p1 = ICE_DYNAMIC_CAST(D1, b1);
1710             test(p1);
1711             test(p1->sd1 == "D1.sd1");
1712             test(p1->pd1 == b1->pb);
1713 
1714             BPtr b2 = b1->pb;
1715             test(b2);
1716             test(b2->sb == "D3.sb");
1717             test(b2->ice_id() == "::Test::B");  // Sliced by server
1718             test(b2->pb == b1);
1719             D3Ptr p3 = ICE_DYNAMIC_CAST(D3, b2);
1720             test(!p3);
1721 
1722             test(b1 != d1);
1723             test(b1 != d3);
1724             test(b2 != d1);
1725             test(b2 != d3);
1726 
1727             breakCycles(b1);
1728             breakCycles(d1);
1729             breakCycles(d3);
1730         }
1731         catch(...)
1732         {
1733             test(false);
1734         }
1735     }
1736     cout << "ok" << endl;
1737 
1738     cout << "return value identity for input params unknown first... " << flush;
1739     {
1740         try
1741         {
1742             D1Ptr d1 = ICE_MAKE_SHARED(D1);
1743             d1->sb = "D1.sb";
1744             d1->sd1 = "D1.sd1";
1745             D3Ptr d3 = ICE_MAKE_SHARED(D3);
1746             d3->pb = d1;
1747             d3->sb = "D3.sb";
1748             d3->sd3 = "D3.sd3";
1749             d3->pd3 = d1;
1750             d1->pb = d3;
1751             d1->pd1 = d3;
1752 #ifndef ICE_CPP11_MAPPING
1753             d1->ice_collectable(true);
1754 #endif
1755             BPtr b1 = test->returnTest3(d3, d1);
1756 
1757             test(b1);
1758             test(b1->sb == "D3.sb");
1759             test(b1->ice_id() == "::Test::B");  // Sliced by server
1760 
1761             D3Ptr p1 = ICE_DYNAMIC_CAST(D3, b1);
1762             test(!p1);
1763 
1764             BPtr b2 = b1->pb;
1765             test(b2);
1766             test(b2->sb == "D1.sb");
1767             test(b2->ice_id() == "::Test::D1");
1768             test(b2->pb == b1);
1769 
1770             D1Ptr p3 = ICE_DYNAMIC_CAST(D1, b2);
1771             test(p3);
1772             test(p3->sd1 == "D1.sd1");
1773             test(p3->pd1 == b1);
1774 
1775             test(b1 != d1);
1776             test(b1 != d3);
1777             test(b2 != d1);
1778             test(b2 != d3);
1779 
1780             breakCycles(b1);
1781             breakCycles(d1);
1782             breakCycles(d3);
1783         }
1784         catch(...)
1785         {
1786             test(false);
1787         }
1788     }
1789     cout << "ok" << endl;
1790 
1791     cout << "return value identity for input params unknown first (AMI)... " << flush;
1792     {
1793         try
1794         {
1795             D1Ptr d1 = ICE_MAKE_SHARED(D1);
1796             d1->sb = "D1.sb";
1797             d1->sd1 = "D1.sd1";
1798             D3Ptr d3 = ICE_MAKE_SHARED(D3);
1799             d3->pb = d1;
1800             d3->sb = "D3.sb";
1801             d3->sd3 = "D3.sd3";
1802             d3->pd3 = d1;
1803             d1->pb = d3;
1804             d1->pd1 = d3;
1805 #ifndef ICE_CPP11_MAPPING
1806             d1->ice_collectable(true);
1807 #endif
1808 
1809 #ifdef ICE_CPP11_MAPPING
1810             auto f = test->returnTest3Async(d3, d1);
1811             auto b1 = f.get();
1812 #else
1813             CallbackPtr cb = new Callback;
1814             test->begin_returnTest3(d3, d1,
1815                 newCallback_TestIntf_returnTest3(cb, &Callback::response_returnTest3, &Callback::exception));
1816             cb->check();
1817             BPtr b1 = cb->rb;
1818 #endif
1819 
1820             test(b1);
1821             test(b1->sb == "D3.sb");
1822             test(b1->ice_id() == "::Test::B");  // Sliced by server
1823             D3Ptr p1 = ICE_DYNAMIC_CAST(D3, b1);
1824             test(!p1);
1825 
1826             BPtr b2 = b1->pb;
1827             test(b2);
1828             test(b2->sb == "D1.sb");
1829             test(b2->ice_id() == "::Test::D1");
1830             test(b2->pb == b1);
1831             D1Ptr p3 = ICE_DYNAMIC_CAST(D1, b2);
1832             test(p3);
1833             test(p3->sd1 == "D1.sd1");
1834             test(p3->pd1 == b1);
1835 
1836             test(b1 != d1);
1837             test(b1 != d3);
1838             test(b2 != d1);
1839             test(b2 != d3);
1840 
1841             breakCycles(b1);
1842             breakCycles(d1);
1843             breakCycles(d3);
1844         }
1845         catch(...)
1846         {
1847             test(false);
1848         }
1849     }
1850     cout << "ok" << endl;
1851 
1852     cout << "remainder unmarshaling (3 instances)... " << flush;
1853     {
1854         try
1855         {
1856             BPtr p1;
1857             BPtr p2;
1858             BPtr ret = test->paramTest3(p1, p2);
1859 
1860             test(p1);
1861             test(p1->sb == "D2.sb (p1 1)");
1862             test(p1->pb == 0);
1863             test(p1->ice_id() == "::Test::B");
1864 
1865             test(p2);
1866             test(p2->sb == "D2.sb (p2 1)");
1867             test(p2->pb == 0);
1868             test(p2->ice_id() == "::Test::B");
1869 
1870             test(ret);
1871             test(ret->sb == "D1.sb (p2 2)");
1872             test(ret->pb == 0);
1873             test(ret->ice_id() == "::Test::D1");
1874 
1875             breakCycles(ret);
1876             breakCycles(p1);
1877             breakCycles(p2);
1878         }
1879         catch(...)
1880         {
1881             test(false);
1882         }
1883     }
1884     cout << "ok" << endl;
1885 
1886     cout << "remainder unmarshaling (3 instances) (AMI)... " << flush;
1887     {
1888 #ifdef ICE_CPP11_MAPPING
1889         auto f = test->paramTest3Async();
1890         try
1891         {
1892             auto result = f.get();
1893             auto ret = result.returnValue;
1894             auto p1 = result.p1;
1895             auto p2 = result.p2;
1896 
1897             test(p1);
1898             test(p1->sb == "D2.sb (p1 1)");
1899             test(p1->pb == 0);
1900             test(p1->ice_id() == "::Test::B");
1901 
1902             test(p2);
1903             test(p2->sb == "D2.sb (p2 1)");
1904             test(p2->pb == 0);
1905             test(p2->ice_id() == "::Test::B");
1906 
1907             test(ret);
1908             test(ret->sb == "D1.sb (p2 2)");
1909             test(ret->pb == 0);
1910             test(ret->ice_id() == "::Test::D1");
1911 
1912             breakCycles(ret);
1913             breakCycles(p1);
1914             breakCycles(p2);
1915         }
1916         catch(...)
1917         {
1918             test(false);
1919         }
1920 #else
1921         CallbackPtr cb = new Callback;
1922         test->begin_paramTest3(
1923             newCallback_TestIntf_paramTest3(cb, &Callback::response_paramTest3, &Callback::exception));
1924         cb->check();
1925 #endif
1926     }
1927     cout << "ok" << endl;
1928 
1929     cout << "remainder unmarshaling (4 instances)... " << flush;
1930     {
1931         try
1932         {
1933             BPtr b;
1934             BPtr ret = test->paramTest4(b);
1935 
1936             test(b);
1937             test(b->sb == "D4.sb (1)");
1938             test(b->pb == 0);
1939             test(b->ice_id() == "::Test::B");
1940 
1941             test(ret);
1942             test(ret->sb == "B.sb (2)");
1943             test(ret->pb == 0);
1944             test(ret->ice_id() == "::Test::B");
1945 
1946             breakCycles(ret);
1947             breakCycles(b);
1948         }
1949         catch(...)
1950         {
1951             test(false);
1952         }
1953     }
1954     cout << "ok" << endl;
1955 
1956     cout << "remainder unmarshaling (4 instances) (AMI)... " << flush;
1957     {
1958 #ifdef ICE_CPP11_MAPPING
1959         auto f = test->paramTest4Async();
1960         try
1961         {
1962             auto result = f.get();
1963             auto ret = move(result.returnValue);
1964             auto b = move(result.p);
1965 
1966             test(b);
1967             test(b->sb == "D4.sb (1)");
1968             test(b->pb == nullptr);
1969             test(b->ice_id() == "::Test::B");
1970 
1971             test(ret);
1972             test(ret->sb == "B.sb (2)");
1973             test(ret->pb == nullptr);
1974             test(ret->ice_id() == "::Test::B");
1975 
1976             breakCycles(ret);
1977             breakCycles(b);
1978         }
1979         catch(...)
1980         {
1981             test(false);
1982         }
1983 #else
1984         CallbackPtr cb = new Callback;
1985         test->begin_paramTest4(
1986             newCallback_TestIntf_paramTest4(cb, &Callback::response_paramTest4, &Callback::exception));
1987         cb->check();
1988 #endif
1989     }
1990     cout << "ok" << endl;
1991 
1992     cout << "param ptr slicing, instance marshaled in unknown derived as base... " << flush;
1993     {
1994         try
1995         {
1996             BPtr b1 = ICE_MAKE_SHARED(B);
1997             b1->sb = "B.sb(1)";
1998             b1->pb = b1;
1999 
2000             D3Ptr d3 = ICE_MAKE_SHARED(D3);
2001             d3->sb = "D3.sb";
2002             d3->pb = d3;
2003             d3->sd3 = "D3.sd3";
2004             d3->pd3 = b1;
2005 #ifndef ICE_CPP11_MAPPING
2006             d3->ice_collectable(true);
2007 #endif
2008 
2009             BPtr b2 = ICE_MAKE_SHARED(B);
2010             b2->sb = "B.sb(2)";
2011             b2->pb = b1;
2012 
2013             BPtr r = test->returnTest3(d3, b2);
2014 
2015             test(r);
2016             test(r->ice_id() == "::Test::B");
2017             test(r->sb == "D3.sb");
2018             test(r->pb == r);
2019 
2020             breakCycles(r);
2021             breakCycles(b1);
2022             breakCycles(d3);
2023         }
2024         catch(...)
2025         {
2026             test(false);
2027         }
2028     }
2029     cout << "ok" << endl;
2030 
2031     cout << "param ptr slicing, instance marshaled in unknown derived as base (AMI)... " << flush;
2032     {
2033         try
2034         {
2035             BPtr b1 = ICE_MAKE_SHARED(B);
2036             b1->sb = "B.sb(1)";
2037             b1->pb = b1;
2038 
2039             D3Ptr d3 = ICE_MAKE_SHARED(D3);
2040             d3->sb = "D3.sb";
2041             d3->pb = d3;
2042             d3->sd3 = "D3.sd3";
2043             d3->pd3 = b1;
2044 #ifndef ICE_CPP11_MAPPING
2045             d3->ice_collectable(true);
2046 #endif
2047 
2048             BPtr b2 = ICE_MAKE_SHARED(B);
2049             b2->sb = "B.sb(2)";
2050             b2->pb = b1;
2051 
2052 #ifdef ICE_CPP11_MAPPING
2053             auto r = test->returnTest3Async(d3, b2).get();
2054 #else
2055             CallbackPtr cb = new Callback;
2056             test->begin_returnTest3(d3, b2,
2057                 newCallback_TestIntf_returnTest3(cb, &Callback::response_returnTest3, &Callback::exception));
2058             cb->check();
2059             BPtr r = cb->rb;
2060 #endif
2061             test(r);
2062             test(r->ice_id() == "::Test::B");
2063             test(r->sb == "D3.sb");
2064             test(r->pb == r);
2065 
2066             breakCycles(b1);
2067             breakCycles(d3);
2068             breakCycles(r);
2069         }
2070         catch(...)
2071         {
2072             test(false);
2073         }
2074     }
2075     cout << "ok" << endl;
2076 
2077     cout << "param ptr slicing, instance marshaled in unknown derived as derived... "
2078          << flush;
2079     {
2080         try
2081         {
2082             D1Ptr d11 = ICE_MAKE_SHARED(D1);
2083             d11->sb = "D1.sb(1)";
2084             d11->pb = d11;
2085             d11->sd1 = "D1.sd1(1)";
2086 
2087             D3Ptr d3 = ICE_MAKE_SHARED(D3);
2088             d3->sb = "D3.sb";
2089             d3->pb = d3;
2090             d3->sd3 = "D3.sd3";
2091             d3->pd3 = d11;
2092 #ifndef ICE_CPP11_MAPPING
2093             d3->ice_collectable(true);
2094 #endif
2095             D1Ptr d12 = ICE_MAKE_SHARED(D1);
2096             d12->sb = "D1.sb(2)";
2097             d12->pb = d12;
2098             d12->sd1 = "D1.sd1(2)";
2099             d12->pd1 = d11;
2100 #ifndef ICE_CPP11_MAPPING
2101             d12->ice_collectable(true);
2102 #endif
2103             BPtr r = test->returnTest3(d3, d12);
2104             test(r);
2105             test(r->ice_id() == "::Test::B");
2106             test(r->sb == "D3.sb");
2107             test(r->pb == r);
2108 
2109             breakCycles(d3);
2110             breakCycles(d11);
2111             breakCycles(d12);
2112             breakCycles(r);
2113         }
2114         catch(...)
2115         {
2116             test(false);
2117         }
2118     }
2119     cout << "ok" << endl;
2120 
2121     cout << "param ptr slicing, instance marshaled in unknown derived as derived (AMI)... "
2122          << flush;
2123     {
2124         try
2125         {
2126             D1Ptr d11 = ICE_MAKE_SHARED(D1);
2127             d11->sb = "D1.sb(1)";
2128             d11->pb = d11;
2129             d11->sd1 = "D1.sd1(1)";
2130 
2131             D3Ptr d3 = ICE_MAKE_SHARED(D3);
2132             d3->sb = "D3.sb";
2133             d3->pb = d3;
2134             d3->sd3 = "D3.sd3";
2135             d3->pd3 = d11;
2136 #ifndef ICE_CPP11_MAPPING
2137             d3->ice_collectable(true);
2138 #endif
2139             D1Ptr d12 = ICE_MAKE_SHARED(D1);
2140             d12->sb = "D1.sb(2)";
2141             d12->pb = d12;
2142             d12->sd1 = "D1.sd1(2)";
2143             d12->pd1 = d11;
2144 #ifndef ICE_CPP11_MAPPING
2145             d12->ice_collectable(true);
2146 #endif
2147 
2148 #ifdef ICE_CPP11_MAPPING
2149             auto r = test->returnTest3Async(d3, d12).get();
2150 #else
2151             CallbackPtr cb = new Callback;
2152             test->begin_returnTest3(d3, d12,
2153                 newCallback_TestIntf_returnTest3(cb, &Callback::response_returnTest3, &Callback::exception));
2154             cb->check();
2155             BPtr r = cb->rb;
2156 #endif
2157             test(r);
2158             test(r->ice_id() == "::Test::B");
2159             test(r->sb == "D3.sb");
2160             test(r->pb == r);
2161 
2162             breakCycles(d3);
2163             breakCycles(d11);
2164             breakCycles(d12);
2165             breakCycles(r);
2166         }
2167         catch(...)
2168         {
2169             test(false);
2170         }
2171     }
2172     cout << "ok" << endl;
2173 
2174     cout << "sequence slicing... " << flush;
2175     {
2176         try
2177         {
2178             SS3 ss;
2179             {
2180                 BPtr ss1b = ICE_MAKE_SHARED(B);
2181                 ss1b->sb = "B.sb";
2182                 ss1b->pb = ss1b;
2183 
2184                 D1Ptr ss1d1 = ICE_MAKE_SHARED(D1);
2185                 ss1d1->sb = "D1.sb";
2186                 ss1d1->sd1 = "D1.sd1";
2187                 ss1d1->pb = ss1b;
2188 
2189                 D3Ptr ss1d3 = ICE_MAKE_SHARED(D3);
2190                 ss1d3->sb = "D3.sb";
2191                 ss1d3->sd3 = "D3.sd3";
2192                 ss1d3->pb = ss1b;
2193 #ifndef ICE_CPP11_MAPPING
2194                 ss1d3->ice_collectable(true);
2195 #endif
2196                 BPtr ss2b = ICE_MAKE_SHARED(B);
2197                 ss2b->sb = "B.sb";
2198                 ss2b->pb = ss1b;
2199 
2200                 D1Ptr ss2d1 = ICE_MAKE_SHARED(D1);
2201                 ss2d1->sb = "D1.sb";
2202                 ss2d1->sd1 = "D1.sd1";
2203                 ss2d1->pb = ss2b;
2204 
2205                 D3Ptr ss2d3 = ICE_MAKE_SHARED(D3);
2206                 ss2d3->sb = "D3.sb";
2207                 ss2d3->sd3 = "D3.sd3";
2208                 ss2d3->pb = ss2b;
2209 
2210                 ss1d1->pd1 = ss2b;
2211                 ss1d3->pd3 = ss2d1;
2212 
2213                 ss2d1->pd1 = ss1d3;
2214                 ss2d3->pd3 = ss1d1;
2215 
2216                 SS1Ptr ss1 = ICE_MAKE_SHARED(SS1);
2217                 ss1->s.push_back(ss1b);
2218                 ss1->s.push_back(ss1d1);
2219                 ss1->s.push_back(ss1d3);
2220 
2221                 SS2Ptr ss2 = ICE_MAKE_SHARED(SS2);
2222                 ss2->s.push_back(ss2b);
2223                 ss2->s.push_back(ss2d1);
2224                 ss2->s.push_back(ss2d3);
2225 
2226 #ifndef ICE_CPP11_MAPPING
2227                 ss1->ice_collectable(true);
2228                 ss2->ice_collectable(true);
2229 #endif
2230                 ss = test->sequenceTest(ss1, ss2);
2231 
2232                 breakCycles(ss1);
2233                 breakCycles(ss2);
2234             }
2235 
2236             test(ss.c1);
2237             BPtr ss1b = ss.c1->s[0];
2238             BPtr ss1d1 = ss.c1->s[1];
2239             test(ss.c2);
2240             BPtr ss1d3 = ss.c1->s[2];
2241 
2242             test(ss.c2);
2243             BPtr ss2b = ss.c2->s[0];
2244             BPtr ss2d1 = ss.c2->s[1];
2245             BPtr ss2d3 = ss.c2->s[2];
2246 
2247             test(ss1b->pb == ss1b);
2248             test(ss1d1->pb == ss1b);
2249             test(ss1d3->pb == ss1b);
2250 
2251             test(ss2b->pb == ss1b);
2252             test(ss2d1->pb == ss2b);
2253             test(ss2d3->pb == ss2b);
2254 
2255             test(ss1b->ice_id() == "::Test::B");
2256             test(ss1d1->ice_id() == "::Test::D1");
2257             test(ss1d3->ice_id() == "::Test::B");
2258 
2259             test(ss2b->ice_id() == "::Test::B");
2260             test(ss2d1->ice_id() == "::Test::D1");
2261             test(ss2d3->ice_id() == "::Test::B");
2262 
2263             breakCycles(ss.c1);
2264             breakCycles(ss.c2);
2265         }
2266         catch(const ::Ice::Exception&)
2267         {
2268             test(false);
2269         }
2270     }
2271     cout << "ok" << endl;
2272 
2273     cout << "sequence slicing (AMI)... " << flush;
2274     {
2275         try
2276         {
2277             SS3 ss;
2278             {
2279                 BPtr ss1b = ICE_MAKE_SHARED(B);
2280                 ss1b->sb = "B.sb";
2281                 ss1b->pb = ss1b;
2282 
2283                 D1Ptr ss1d1 = ICE_MAKE_SHARED(D1);
2284                 ss1d1->sb = "D1.sb";
2285                 ss1d1->sd1 = "D1.sd1";
2286                 ss1d1->pb = ss1b;
2287 
2288                 D3Ptr ss1d3 = ICE_MAKE_SHARED(D3);
2289                 ss1d3->sb = "D3.sb";
2290                 ss1d3->sd3 = "D3.sd3";
2291                 ss1d3->pb = ss1b;
2292 #ifndef ICE_CPP11_MAPPING
2293                 ss1d3->ice_collectable(true);
2294 #endif
2295 
2296                 BPtr ss2b = ICE_MAKE_SHARED(B);
2297                 ss2b->sb = "B.sb";
2298                 ss2b->pb = ss1b;
2299 
2300                 D1Ptr ss2d1 = ICE_MAKE_SHARED(D1);
2301                 ss2d1->sb = "D1.sb";
2302                 ss2d1->sd1 = "D1.sd1";
2303                 ss2d1->pb = ss2b;
2304 
2305                 D3Ptr ss2d3 = ICE_MAKE_SHARED(D3);
2306                 ss2d3->sb = "D3.sb";
2307                 ss2d3->sd3 = "D3.sd3";
2308                 ss2d3->pb = ss2b;
2309 
2310                 ss1d1->pd1 = ss2b;
2311                 ss1d3->pd3 = ss2d1;
2312 
2313                 ss2d1->pd1 = ss1d3;
2314                 ss2d3->pd3 = ss1d1;
2315 
2316                 SS1Ptr ss1 = ICE_MAKE_SHARED(SS1);
2317                 ss1->s.push_back(ss1b);
2318                 ss1->s.push_back(ss1d1);
2319                 ss1->s.push_back(ss1d3);
2320 
2321                 SS2Ptr ss2 = ICE_MAKE_SHARED(SS2);
2322                 ss2->s.push_back(ss2b);
2323                 ss2->s.push_back(ss2d1);
2324                 ss2->s.push_back(ss2d3);
2325 #ifndef ICE_CPP11_MAPPING
2326                 ss1->ice_collectable(true);
2327                 ss2->ice_collectable(true);
2328 #endif
2329 
2330 #ifdef ICE_CPP11_MAPPING
2331                 ss = test->sequenceTestAsync(ss1, ss2).get();
2332 #else
2333                 CallbackPtr cb = new Callback;
2334                 test->begin_sequenceTest(ss1, ss2,
2335                     newCallback_TestIntf_sequenceTest(cb, &Callback::response_sequenceTest, &Callback::exception));
2336                 cb->check();
2337                 ss = cb->rss3;
2338 #endif
2339 
2340                 breakCycles(ss1);
2341                 breakCycles(ss2);
2342             }
2343 
2344             test(ss.c1);
2345             BPtr ss1b = ss.c1->s[0];
2346             BPtr ss1d1 = ss.c1->s[1];
2347             test(ss.c2);
2348             BPtr ss1d3 = ss.c1->s[2];
2349 
2350             test(ss.c2);
2351             BPtr ss2b = ss.c2->s[0];
2352             BPtr ss2d1 = ss.c2->s[1];
2353             BPtr ss2d3 = ss.c2->s[2];
2354 
2355             test(ss1b->pb == ss1b);
2356             test(ss1d1->pb == ss1b);
2357             test(ss1d3->pb == ss1b);
2358 
2359             test(ss2b->pb == ss1b);
2360             test(ss2d1->pb == ss2b);
2361             test(ss2d3->pb == ss2b);
2362 
2363             test(ss1b->ice_id() == "::Test::B");
2364             test(ss1d1->ice_id() == "::Test::D1");
2365             test(ss1d3->ice_id() == "::Test::B");
2366 
2367             test(ss2b->ice_id() == "::Test::B");
2368             test(ss2d1->ice_id() == "::Test::D1");
2369             test(ss2d3->ice_id() == "::Test::B");
2370 
2371             breakCycles(ss.c1);
2372             breakCycles(ss.c2);
2373         }
2374         catch(const ::Ice::Exception&)
2375         {
2376             test(false);
2377         }
2378     }
2379     cout << "ok" << endl;
2380 
2381     cout << "dictionary slicing... " << flush;
2382     {
2383         try
2384         {
2385             BDict bin;
2386             BDict bout;
2387             BDict r;
2388             int i;
2389             for(i = 0; i < 10; ++i)
2390             {
2391                 ostringstream s;
2392                 s << "D1." << i;
2393                 D1Ptr d1 = ICE_MAKE_SHARED(D1);
2394                 d1->sb = s.str();
2395                 d1->pb = d1;
2396                 d1->sd1 = s.str();
2397                 bin[i] = d1;
2398 #ifndef ICE_CPP11_MAPPING
2399                 d1->ice_collectable(true);
2400 #endif
2401             }
2402 
2403             r = test->dictionaryTest(bin, bout);
2404 
2405             test(bout.size() == 10);
2406             for(i = 0; i < 10; ++i)
2407             {
2408                 BPtr b = bout.find(i * 10)->second;
2409                 test(b);
2410                 std::ostringstream s;
2411                 s << "D1." << i;
2412                 test(b->sb == s.str());
2413                 test(b->pb);
2414                 test(b->pb != b);
2415                 test(b->pb->sb == s.str());
2416                 test(b->pb->pb == b->pb);
2417             }
2418 
2419             test(r.size() == 10);
2420             for(i = 0; i < 10; ++i)
2421             {
2422                 BPtr b = r.find(i * 20)->second;
2423                 test(b);
2424                 std::ostringstream s;
2425                 s << "D1." << i * 20;
2426                 test(b->sb == s.str());
2427                 test(b->pb == (i == 0 ? BPtr(0) : r.find((i - 1) * 20)->second));
2428                 D1Ptr d1 = ICE_DYNAMIC_CAST(D1, b);
2429                 test(d1);
2430                 test(d1->sd1 == s.str());
2431                 test(d1->pd1 == d1);
2432             }
2433 
2434             breakCycles(bin);
2435             breakCycles(bout);
2436             breakCycles(r);
2437         }
2438         catch(const ::Ice::Exception&)
2439         {
2440             test(false);
2441         }
2442     }
2443     cout << "ok" << endl;
2444 
2445     cout << "dictionary slicing (AMI)... " << flush;
2446     {
2447         try
2448         {
2449             BDict bin;
2450             BDict bout;
2451             BDict r;
2452             int i;
2453             for(i = 0; i < 10; ++i)
2454             {
2455                 ostringstream s;
2456                 s << "D1." << i;
2457                 D1Ptr d1 = ICE_MAKE_SHARED(D1);
2458                 d1->sb = s.str();
2459                 d1->pb = d1;
2460                 d1->sd1 = s.str();
2461                 bin[i] = d1;
2462 #ifndef ICE_CPP11_MAPPING
2463                 d1->ice_collectable(true);
2464 #endif
2465             }
2466 
2467 #ifdef ICE_CPP11_MAPPING
2468             auto result = test->dictionaryTestAsync(bin).get();
2469             r = result.returnValue;
2470             bout = result.bout;
2471 #else
2472             CallbackPtr cb = new Callback;
2473             test->begin_dictionaryTest(bin,
2474                 newCallback_TestIntf_dictionaryTest(cb, &Callback::response_dictionaryTest, &Callback::exception));
2475             cb->check();
2476             bout = cb->obdict;
2477             r = cb->rbdict;
2478 #endif
2479 
2480             test(bout.size() == 10);
2481             for(i = 0; i < 10; ++i)
2482             {
2483                 BPtr b = bout.find(i * 10)->second;
2484                 test(b);
2485                 std::ostringstream s;
2486                 s << "D1." << i;
2487                 test(b->sb == s.str());
2488                 test(b->pb);
2489                 test(b->pb != b);
2490                 test(b->pb->sb == s.str());
2491                 test(b->pb->pb == b->pb);
2492             }
2493 
2494             test(r.size() == 10);
2495             for(i = 0; i < 10; ++i)
2496             {
2497                 BPtr b = r.find(i * 20)->second;
2498                 test(b);
2499                 std::ostringstream s;
2500                 s << "D1." << i * 20;
2501                 test(b->sb == s.str());
2502                 test(b->pb == (i == 0 ? BPtr(0) : r.find((i - 1) * 20)->second));
2503                 D1Ptr d1 = ICE_DYNAMIC_CAST(D1, b);
2504                 test(d1);
2505                 test(d1->sd1 == s.str());
2506                 test(d1->pd1 == d1);
2507             }
2508 
2509             breakCycles(bin);
2510             breakCycles(bout);
2511             breakCycles(r);
2512         }
2513         catch(const ::Ice::Exception&)
2514         {
2515             test(false);
2516         }
2517     }
2518     cout << "ok" << endl;
2519 
2520     cout << "base exception thrown as base exception... " << flush;
2521     {
2522         try
2523         {
2524             test->throwBaseAsBase();
2525             test(false);
2526         }
2527         catch(const BaseException& e)
2528         {
2529             test(e.ice_id() == "::Test::BaseException");
2530             test(e.sbe == "sbe");
2531             test(e.pb);
2532             test(e.pb->sb == "sb");
2533             test(e.pb->pb == e.pb);
2534             breakCycles(e.pb);
2535         }
2536         catch(...)
2537         {
2538             test(false);
2539         }
2540     }
2541     cout << "ok" << endl;
2542 
2543     cout << "base exception thrown as base exception (AMI)... " << flush;
2544     {
2545 #ifdef ICE_CPP11_MAPPING
2546         try
2547         {
2548             test->throwBaseAsBaseAsync().get();
2549             test(false);
2550         }
2551         catch(const BaseException& ex)
2552         {
2553             test(ex.ice_id() == "::Test::BaseException");
2554             test(ex.sbe == "sbe");
2555             test(ex.pb);
2556             test(ex.pb->sb == "sb");
2557             test(ex.pb->pb == ex.pb);
2558             breakCycles(ex.pb);
2559         }
2560         catch(...)
2561         {
2562             test(false);
2563         }
2564 #else
2565         CallbackPtr cb = new Callback;
2566         test->begin_throwBaseAsBase(
2567             newCallback_TestIntf_throwBaseAsBase(cb, &Callback::response, &Callback::exception_throwBaseAsBase));
2568         cb->check();
2569 #endif
2570     }
2571     cout << "ok" << endl;
2572 
2573     cout << "derived exception thrown as base exception... " << flush;
2574     {
2575         try
2576         {
2577             test->throwDerivedAsBase();
2578             test(false);
2579         }
2580         catch(const DerivedException& e)
2581         {
2582             test(e.ice_id() == "::Test::DerivedException");
2583             test(e.sbe == "sbe");
2584             test(e.pb);
2585             test(e.pb->sb == "sb1");
2586             test(e.pb->pb == e.pb);
2587             test(e.sde == "sde1");
2588             test(e.pd1);
2589             test(e.pd1->sb == "sb2");
2590             test(e.pd1->pb == e.pd1);
2591             test(e.pd1->sd1 == "sd2");
2592             test(e.pd1->pd1 == e.pd1);
2593             breakCycles(e.pb);
2594             breakCycles(e.pd1);
2595         }
2596         catch(...)
2597         {
2598             test(false);
2599         }
2600     }
2601     cout << "ok" << endl;
2602 
2603     cout << "derived exception thrown as base exception (AMI)... " << flush;
2604     {
2605 #ifdef ICE_CPP11_MAPPING
2606         try
2607         {
2608             test->throwDerivedAsBaseAsync().get();
2609             test(false);
2610         }
2611         catch(const DerivedException& ex)
2612         {
2613             test(ex.ice_id() == "::Test::DerivedException");
2614             test(ex.sbe == "sbe");
2615             test(ex.pb);
2616             test(ex.pb->sb == "sb1");
2617             test(ex.pb->pb == ex.pb);
2618             test(ex.sde == "sde1");
2619             test(ex.pd1);
2620             test(ex.pd1->sb == "sb2");
2621             test(ex.pd1->pb == ex.pd1);
2622             test(ex.pd1->sd1 == "sd2");
2623             test(ex.pd1->pd1 == ex.pd1);
2624             breakCycles(ex.pb);
2625             breakCycles(ex.pd1);
2626         }
2627         catch(...)
2628         {
2629             test(false);
2630         }
2631 #else
2632         CallbackPtr cb = new Callback;
2633         test->begin_throwDerivedAsBase(
2634             newCallback_TestIntf_throwDerivedAsBase(cb, &Callback::response, &Callback::exception_throwDerivedAsBase));
2635         cb->check();
2636 #endif
2637     }
2638     cout << "ok" << endl;
2639 
2640     cout << "derived exception thrown as derived exception... " << flush;
2641     {
2642         try
2643         {
2644             test->throwDerivedAsDerived();
2645             test(false);
2646         }
2647         catch(const DerivedException& e)
2648         {
2649             test(e.ice_id() == "::Test::DerivedException");
2650             test(e.sbe == "sbe");
2651             test(e.pb);
2652             test(e.pb->sb == "sb1");
2653             test(e.pb->pb == e.pb);
2654             test(e.sde == "sde1");
2655             test(e.pd1);
2656             test(e.pd1->sb == "sb2");
2657             test(e.pd1->pb == e.pd1);
2658             test(e.pd1->sd1 == "sd2");
2659             test(e.pd1->pd1 == e.pd1);
2660             breakCycles(e.pb);
2661             breakCycles(e.pd1);
2662         }
2663         catch(...)
2664         {
2665             test(false);
2666         }
2667     }
2668     cout << "ok" << endl;
2669 
2670     cout << "derived exception thrown as derived exception (AMI)... " << flush;
2671     {
2672 #ifdef ICE_CPP11_MAPPING
2673         try
2674         {
2675             test->throwDerivedAsDerivedAsync().get();
2676             test(false);
2677         }
2678         catch(const DerivedException& e)
2679         {
2680             test(e.ice_id() == "::Test::DerivedException");
2681             test(e.sbe == "sbe");
2682             test(e.pb);
2683             test(e.pb->sb == "sb1");
2684             test(e.pb->pb == e.pb);
2685             test(e.sde == "sde1");
2686             test(e.pd1);
2687             test(e.pd1->sb == "sb2");
2688             test(e.pd1->pb == e.pd1);
2689             test(e.pd1->sd1 == "sd2");
2690             test(e.pd1->pd1 == e.pd1);
2691             breakCycles(e.pb);
2692             breakCycles(e.pd1);
2693         }
2694         catch(...)
2695         {
2696             test(false);
2697         }
2698 #else
2699         CallbackPtr cb = new Callback;
2700         test->begin_throwDerivedAsDerived(
2701             newCallback_TestIntf_throwDerivedAsDerived(
2702                 cb, &Callback::response, &Callback::exception_throwDerivedAsDerived));
2703         cb->check();
2704 #endif
2705     }
2706     cout << "ok" << endl;
2707 
2708     cout << "unknown derived exception thrown as base exception... " << flush;
2709     {
2710         try
2711         {
2712             test->throwUnknownDerivedAsBase();
2713             test(false);
2714         }
2715         catch(const BaseException& e)
2716         {
2717             test(e.ice_id() == "::Test::BaseException");
2718             test(e.sbe == "sbe");
2719             test(e.pb);
2720             test(e.pb->sb == "sb d2");
2721             test(e.pb->pb == e.pb);
2722             breakCycles(e.pb);
2723         }
2724         catch(...)
2725         {
2726             test(false);
2727         }
2728     }
2729     cout << "ok" << endl;
2730 
2731     cout << "unknown derived exception thrown as base exception (AMI)... " << flush;
2732     {
2733 #ifdef ICE_CPP11_MAPPING
2734         try
2735         {
2736             test->throwUnknownDerivedAsBaseAsync().get();
2737             test(false);
2738         }
2739         catch(const BaseException& e)
2740         {
2741             test(e.ice_id() == "::Test::BaseException");
2742             test(e.sbe == "sbe");
2743             test(e.pb);
2744             test(e.pb->sb == "sb d2");
2745             test(e.pb->pb == e.pb);
2746             breakCycles(e.pb);
2747         }
2748         catch(...)
2749         {
2750             test(false);
2751         }
2752 #else
2753         CallbackPtr cb = new Callback;
2754         test->begin_throwUnknownDerivedAsBase(
2755             newCallback_TestIntf_throwUnknownDerivedAsBase(
2756                 cb, &Callback::response, &Callback::exception_throwUnknownDerivedAsBase));
2757         cb->check();
2758 #endif
2759     }
2760     cout << "ok" << endl;
2761 
2762     cout << "preserved classes... " << flush;
2763     try
2764     {
2765         //
2766         // Server knows the most-derived class PDerived.
2767         //
2768         PDerivedPtr pd = ICE_MAKE_SHARED(PDerived);
2769         pd->pi = 3;
2770         pd->ps = "preserved";
2771         pd->pb = pd;
2772 #ifndef ICE_CPP11_MAPPING
2773         pd->ice_collectable(true);
2774 #endif
2775         PBasePtr r = test->exchangePBase(pd);
2776         PDerivedPtr p2 = ICE_DYNAMIC_CAST(PDerived, r);
2777         test(p2);
2778         test(p2->pi == 3);
2779         test(p2->ps == "preserved");
2780         test(p2->pb == p2);
2781 
2782         breakCycles(r);
2783         breakCycles(pd);
2784     }
2785     catch(const Ice::OperationNotExistException&)
2786     {
2787     }
2788 
2789     try
2790     {
2791         //
2792         // Server only knows the base (non-preserved) type, so the object is sliced.
2793         //
2794         PCUnknownPtr pu = ICE_MAKE_SHARED(PCUnknown);
2795         pu->pi = 3;
2796         pu->pu = "preserved";
2797         PBasePtr r = test->exchangePBase(pu);
2798         PCUnknownPtr p2 = ICE_DYNAMIC_CAST(PCUnknown, r);
2799         test(!p2);
2800         test(r->pi == 3);
2801 
2802         breakCycles(r);
2803     }
2804     catch(const Ice::OperationNotExistException&)
2805     {
2806     }
2807 
2808     try
2809     {
2810         //
2811         // Server only knows the intermediate type Preserved. The object will be sliced to
2812         // Preserved for the 1.0 encoding; otherwise it should be returned intact.
2813         //
2814         PCDerivedPtr pcd = ICE_MAKE_SHARED(PCDerived);
2815         pcd->pi = 3;
2816         pcd->pbs.push_back(pcd);
2817 #ifndef ICE_CPP11_MAPPING
2818         pcd->ice_collectable(true);
2819 #endif
2820 
2821         PBasePtr r = test->exchangePBase(pcd);
2822         PCDerivedPtr p2 = ICE_DYNAMIC_CAST(PCDerived, r);
2823         if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
2824         {
2825             test(!p2);
2826             test(r->pi == 3);
2827         }
2828         else
2829         {
2830             test(p2);
2831             test(p2->pi == 3);
2832             test(p2->pbs[0] == p2);
2833         }
2834 
2835         breakCycles(r);
2836         breakCycles(pcd);
2837     }
2838     catch(const Ice::OperationNotExistException&)
2839     {
2840     }
2841 
2842     try
2843     {
2844         //
2845         // Server only knows the intermediate type CompactPDerived. The object will be sliced to
2846         // CompactPDerived for the 1.0 encoding; otherwise it should be returned intact.
2847         //
2848         CompactPCDerivedPtr pcd = ICE_MAKE_SHARED(CompactPCDerived);
2849         pcd->pi = 3;
2850         pcd->pbs.push_back(pcd);
2851 #ifndef ICE_CPP11_MAPPING
2852         pcd->ice_collectable(true);
2853 #endif
2854 
2855         PBasePtr r = test->exchangePBase(pcd);
2856         CompactPCDerivedPtr p2 = ICE_DYNAMIC_CAST(CompactPCDerived, r);
2857         if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
2858         {
2859             test(!p2);
2860             test(r->pi == 3);
2861         }
2862         else
2863         {
2864             test(p2);
2865             test(p2->pi == 3);
2866             test(p2->pbs[0] == p2);
2867         }
2868 
2869         breakCycles(r);
2870         breakCycles(pcd);
2871     }
2872     catch(const Ice::OperationNotExistException&)
2873     {
2874     }
2875 
2876     try
2877     {
2878         //
2879         // Send an object that will have multiple preserved slices in the server.
2880         // The object will be sliced to Preserved for the 1.0 encoding.
2881         //
2882         PCDerived3Ptr pcd = ICE_MAKE_SHARED(PCDerived3);
2883         pcd->pi = 3;
2884         //
2885         // Sending more than 254 objects exercises the encoding for object ids.
2886         //
2887         int i;
2888         for(i = 0; i < 300; ++i)
2889         {
2890             PCDerived2Ptr p2 = ICE_MAKE_SHARED(PCDerived2);
2891             p2->pi = i;
2892             p2->pbs.push_back(0); // Nil reference. This slice should not have an indirection table.
2893             p2->pcd2 = i;
2894             pcd->pbs.push_back(p2);
2895         }
2896         pcd->pcd2 = pcd->pi;
2897         pcd->pcd3 = pcd->pbs[10];
2898 
2899         PBasePtr r = test->exchangePBase(pcd);
2900         PCDerived3Ptr p3 = ICE_DYNAMIC_CAST(PCDerived3, r);
2901         if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
2902         {
2903             test(!p3);
2904             test(ICE_DYNAMIC_CAST(Preserved, r));
2905             test(r->pi == 3);
2906         }
2907         else
2908         {
2909             test(p3);
2910             test(p3->pi == 3);
2911             for(i = 0; i < 300; ++i)
2912             {
2913                 PCDerived2Ptr p2 = ICE_DYNAMIC_CAST(PCDerived2, p3->pbs[i]);
2914                 test(p2->pi == i);
2915                 test(p2->pbs.size() == 1);
2916                 test(!p2->pbs[0]);
2917                 test(p2->pcd2 == i);
2918             }
2919             test(p3->pcd2 == p3->pi);
2920             test(p3->pcd3 == p3->pbs[10]);
2921         }
2922 
2923         breakCycles(r);
2924         breakCycles(pcd);
2925     }
2926     catch(const Ice::OperationNotExistException&)
2927     {
2928     }
2929 
2930     try
2931     {
2932         //
2933         // Obtain an object with preserved slices and send it back to the server.
2934         // The preserved slices should be excluded for the 1.0 encoding, otherwise
2935         // they should be included.
2936         //
2937         PreservedPtr p = test->PBSUnknownAsPreserved();
2938         test->checkPBSUnknown(p);
2939         if(test->ice_getEncodingVersion() != Ice::Encoding_1_0)
2940         {
2941             Ice::SlicedDataPtr slicedData = p->ice_getSlicedData();
2942             test(slicedData);
2943             test(slicedData->slices.size() == 1);
2944             test(slicedData->slices[0]->typeId == "::Test::PSUnknown");
2945             test->ice_encodingVersion(Ice::Encoding_1_0)->checkPBSUnknown(p);
2946         }
2947         else
2948         {
2949             test(!p->ice_getSlicedData());
2950         }
2951 
2952         breakCycles(p);
2953     }
2954     catch(const Ice::OperationNotExistException&)
2955     {
2956     }
2957 
2958     cout << "ok" << endl;
2959 
2960     cout << "preserved classes (AMI)... " << flush;
2961     {
2962         //
2963         // Server knows the most-derived class PDerived.
2964         //
2965         PDerivedPtr pd = ICE_MAKE_SHARED(PDerived);
2966         pd->pi = 3;
2967         pd->ps = "preserved";
2968         pd->ps = "preserved";
2969         pd->pb = pd;
2970 
2971 #ifndef ICE_CPP11_MAPPING
2972         pd->ice_collectable(true);
2973 #endif
2974 
2975 #ifdef ICE_CPP11_MAPPING
2976         try
2977         {
2978             auto r = dynamic_pointer_cast<PDerived>(test->exchangePBaseAsync(pd).get());
2979             test(r);
2980             test(r->pi == 3);
2981             test(r->ps == "preserved");
2982             test(r->pb == r);
2983 
2984             breakCycles(r);
2985             breakCycles(pd);
2986         }
2987         catch(...)
2988         {
2989             test(false);
2990         }
2991 #else
2992         CallbackPtr cb = new Callback;
2993         test->begin_exchangePBase(
2994             pd, newCallback_TestIntf_exchangePBase(cb, &Callback::response_preserved1, &Callback::exception));
2995         cb->check();
2996 #endif
2997     }
2998 
2999     {
3000         //
3001         // Server only knows the base (non-preserved) type, so the object is sliced.
3002         //
3003         PCUnknownPtr pu = ICE_MAKE_SHARED(PCUnknown);
3004         pu->pi = 3;
3005         pu->pu = "preserved";
3006 #ifdef ICE_CPP11_MAPPING
3007         try
3008         {
3009             auto r = test->exchangePBaseAsync(pu).get();
3010             auto p2 = dynamic_pointer_cast<PCUnknown>(r);
3011             test(!p2);
3012             test(r->pi == 3);
3013 
3014             breakCycles(r);
3015         }
3016         catch(...)
3017         {
3018             test(false);
3019         }
3020 #else
3021         CallbackPtr cb = new Callback;
3022         test->begin_exchangePBase(
3023             pu, newCallback_TestIntf_exchangePBase(cb, &Callback::response_preserved2, &Callback::exception));
3024         cb->check();
3025 #endif
3026     }
3027 
3028     {
3029         //
3030         // Server only knows the intermediate type Preserved. The object will be sliced to
3031         // Preserved for the 1.0 encoding; otherwise it should be returned intact.
3032         //
3033         PCDerivedPtr pcd = ICE_MAKE_SHARED(PCDerived);
3034         pcd->pi = 3;
3035         pcd->pbs.push_back(pcd);
3036 #ifdef ICE_CPP11_MAPPING
3037         if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
3038         {
3039             auto r = test->exchangePBaseAsync(pcd).get();
3040             auto p2 = dynamic_pointer_cast<PCDerived>(r);
3041             test(!p2);
3042             test(r->pi == 3);
3043             breakCycles(r);
3044             breakCycles(p2);
3045         }
3046         else
3047         {
3048             auto r = test->exchangePBaseAsync(pcd).get();
3049             auto p2 = dynamic_pointer_cast<PCDerived>(r);
3050             test(p2);
3051             test(p2->pi == 3);
3052             test(p2->pbs[0] == p2);
3053             breakCycles(r);
3054             breakCycles(p2);
3055         }
3056         breakCycles(pcd);
3057 #else
3058         pcd->ice_collectable(true);
3059 
3060         CallbackPtr cb = new Callback;
3061         if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
3062         {
3063             test->begin_exchangePBase(
3064                 pcd, newCallback_TestIntf_exchangePBase(cb, &Callback::response_preserved3, &Callback::exception));
3065         }
3066         else
3067         {
3068             test->begin_exchangePBase(
3069                 pcd, newCallback_TestIntf_exchangePBase(cb, &Callback::response_preserved4, &Callback::exception));
3070         }
3071         cb->check();
3072 #endif
3073     }
3074 
3075     {
3076         //
3077         // Server only knows the intermediate type CompactPDerived. The object will be sliced to
3078         // CompactPDerived for the 1.0 encoding; otherwise it should be returned intact.
3079         //
3080         CompactPCDerivedPtr pcd = ICE_MAKE_SHARED(CompactPCDerived);
3081         pcd->pi = 3;
3082         pcd->pbs.push_back(pcd);
3083 
3084 #ifdef ICE_CPP11_MAPPING
3085         if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
3086         {
3087             auto r = test->exchangePBaseAsync(pcd).get();
3088             auto p2 = dynamic_pointer_cast<CompactPCDerived>(r);
3089             test(!p2);
3090             test(r->pi == 3);
3091             breakCycles(r);
3092             breakCycles(p2);
3093         }
3094         else
3095         {
3096             auto r = test->exchangePBaseAsync(pcd).get();
3097             auto p2 = dynamic_pointer_cast<CompactPCDerived>(r);
3098             test(p2);
3099             test(p2->pi == 3);
3100             test(p2->pbs[0] == p2);
3101             breakCycles(r);
3102             breakCycles(p2);
3103         }
3104         breakCycles(pcd);
3105 #else
3106         pcd->ice_collectable(true);
3107 
3108         CallbackPtr cb = new Callback;
3109         if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
3110         {
3111             test->begin_exchangePBase(pcd, newCallback_TestIntf_exchangePBase(cb,
3112                                                                               &Callback::response_compactPreserved1,
3113                                                                               &Callback::exception));
3114         }
3115         else
3116         {
3117             test->begin_exchangePBase(pcd, newCallback_TestIntf_exchangePBase(cb,
3118                                                                               &Callback::response_compactPreserved2,
3119                                                                               &Callback::exception));
3120         }
3121         cb->check();
3122 #endif
3123     }
3124 
3125     {
3126         //
3127         // Send an object that will have multiple preserved slices in the server.
3128         // The object will be sliced to Preserved for the 1.0 encoding.
3129         //
3130         PCDerived3Ptr pcd = ICE_MAKE_SHARED(PCDerived3);
3131         pcd->pi = 3;
3132         //
3133         // Sending more than 254 objects exercises the encoding for object ids.
3134         //
3135         for(int i = 0; i < 300; ++i)
3136         {
3137             PCDerived2Ptr p2 = ICE_MAKE_SHARED(PCDerived2);
3138             p2->pi = i;
3139             p2->pbs.push_back(0); // Nil reference. This slice should not have an indirection table.
3140             p2->pcd2 = i;
3141             pcd->pbs.push_back(p2);
3142         }
3143         pcd->pcd2 = pcd->pi;
3144         pcd->pcd3 = pcd->pbs[10];
3145 
3146 #ifdef ICE_CPP11_MAPPING
3147         if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
3148         {
3149             auto r = test->exchangePBaseAsync(pcd).get();
3150             auto p2 = dynamic_pointer_cast<PCDerived>(r);
3151             test(!p2);
3152             test(r->pi == 3);
3153             breakCycles(r);
3154             breakCycles(pcd);
3155         }
3156         else
3157         {
3158             auto r = test->exchangePBaseAsync(pcd).get();
3159             auto p3 = dynamic_pointer_cast<PCDerived3>(r);
3160             test(p3);
3161             test(p3->pi == 3);
3162             for(int i = 0; i < 300; ++i)
3163             {
3164                 auto p2 = dynamic_pointer_cast<PCDerived2>(p3->pbs[i]);
3165                 test(p2->pi == i);
3166                 test(p2->pbs.size() == 1);
3167                 test(!p2->pbs[0]);
3168                 test(p2->pcd2 == i);
3169             }
3170             test(p3->pcd2 == p3->pi);
3171             test(p3->pcd3 == p3->pbs[10]);
3172             breakCycles(r);
3173             breakCycles(pcd);
3174         }
3175 #else
3176         CallbackPtr cb = new Callback;
3177         if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
3178         {
3179             test->begin_exchangePBase(
3180                 pcd, newCallback_TestIntf_exchangePBase(cb, &Callback::response_preserved3, &Callback::exception));
3181         }
3182         else
3183         {
3184             test->begin_exchangePBase(
3185                 pcd, newCallback_TestIntf_exchangePBase(cb, &Callback::response_preserved5, &Callback::exception));
3186         }
3187         cb->check();
3188 #endif
3189     }
3190     cout << "ok" << endl;
3191 
3192 #ifndef ICE_CPP11_MAPPING
3193     cout << "garbage collection for preserved classes... " << flush;
3194     try
3195     {
3196         //
3197         // Register a factory in order to substitute our own subclass of PNode. This provides
3198         // an easy way to determine how many unmarshaled instances currently exist.
3199         //
3200         communicator->getValueFactoryManager()->add(new NodeFactoryI, PNode::ice_staticId());
3201 
3202         //
3203         // Relay a graph through the server. This test uses a preserved class
3204         // with a class member, so the preserved class already supports GC.
3205         //
3206         {
3207             PNodePtr c = new PNode;
3208             c->next = new PNode;
3209             c->next->next = new PNode;
3210             c->next->next->next = c;
3211 
3212             test(PNodeI::counter == 0);
3213             PNodePtr n = test->exchangePNode(c);
3214             c->next->next->next = 0; // Break the cycle.
3215 
3216             test(PNodeI::counter == 3);
3217             n = 0;                          // Release reference.
3218             test(PNodeI::counter == 0);
3219         }
3220 
3221         //
3222         // Obtain a preserved object from the server where the most-derived
3223         // type is unknown. The preserved slice refers to a graph of PNode
3224         // objects.
3225         //
3226         {
3227             test(PNodeI::counter == 0);
3228             PreservedPtr p = test->PBSUnknownAsPreservedWithGraph();
3229             test->checkPBSUnknownWithGraph(p);
3230             if(test->ice_getEncodingVersion() == Ice::Encoding_1_0)
3231             {
3232                 test(!p->ice_getSlicedData());
3233                 test(PNodeI::counter == 0);
3234             }
3235             else
3236             {
3237                 test(p->ice_getSlicedData());
3238                 test(PNodeI::counter == 3);
3239                 p->ice_getSlicedData()->clear();
3240                 p = 0;                          // Release reference.
3241                 test(PNodeI::counter == 0);
3242             }
3243         }
3244 
3245         //
3246         // Register a factory in order to substitute our own subclass of Preserved. This provides
3247         // an easy way to determine how many unmarshaled instances currently exist.
3248         //
3249         communicator->getValueFactoryManager()->add(new PreservedFactoryI, Preserved::ice_staticId());
3250 
3251         //
3252         // Obtain a preserved object from the server where the most-derived
3253         // type is unknown. A data member in the preserved slice refers to the
3254         // outer object, so the chain of references looks like this:
3255         //
3256         // outer->slicedData->outer
3257         //
3258         {
3259             test(PreservedI::counter == 0);
3260             PreservedPtr p = test->PBSUnknown2AsPreservedWithGraph();
3261             test->checkPBSUnknown2WithGraph(p);
3262             if(test->ice_getEncodingVersion() != Ice::Encoding_1_0)
3263             {
3264                 test(p->ice_getSlicedData());
3265                 p->ice_getSlicedData()->clear();
3266             }
3267             test(PreservedI::counter == 1);
3268             p = 0;                          // Release reference.
3269             test(PreservedI::counter == 0);
3270         }
3271 
3272         //
3273         // Throw a preserved exception where the most-derived type is unknown.
3274         // The preserved exception slice contains a class data member. This
3275         // object is also preserved, and its most-derived type is also unknown.
3276         // The preserved slice of the object contains a class data member that
3277         // refers to itself.
3278         //
3279         // The chain of references looks like this:
3280         //
3281         // ex->slicedData->obj->slicedData->obj
3282         //
3283         try
3284         {
3285             test(PreservedI::counter == 0);
3286 
3287             try
3288             {
3289                 test->throwPreservedException();
3290             }
3291             catch(const PreservedException&)
3292             {
3293                 //
3294                 // The class instance is only retained when the encoding is > 1.0.
3295                 //
3296                 if(test->ice_getEncodingVersion() != Ice::Encoding_1_0)
3297                 {
3298                     test(PreservedI::counter == 1);
3299                 }
3300             }
3301 
3302             //
3303             // Exception has gone out of scope.
3304             //
3305             test(PreservedI::counter == 0);
3306         }
3307         catch(const Ice::Exception&)
3308         {
3309             test(false);
3310         }
3311     }
3312     catch(const Ice::OperationNotExistException&)
3313     {
3314     }
3315     cout << "ok" << endl;
3316 #endif
3317     return test;
3318 }
3319