// // Copyright (c) ZeroC, Inc. All rights reserved. // #include #include #include // For 'Ice::Communicator::addObjectFactory()' deprecation #if defined(_MSC_VER) # pragma warning( disable : 4996 ) #elif defined(__GNUC__) # pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif using namespace std; using namespace Test; namespace { class AbstractBaseI : public AbstractBase { public: virtual void op(const Ice::Current&) { } }; void testUOE(const Ice::CommunicatorPtr& communicator) { string ref = "uoet:" + TestHelper::getTestEndpoint(communicator->getProperties()); Ice::ObjectPrxPtr base = communicator->stringToProxy(ref); test(base); UnexpectedObjectExceptionTestPrxPtr uoet = ICE_UNCHECKED_CAST(UnexpectedObjectExceptionTestPrx, base); test(uoet); try { uoet->op(); test(false); } catch(const Ice::UnexpectedObjectException& ex) { test(ex.type == "::Test::AlsoEmpty"); test(ex.expectedType == "::Test::Empty"); } catch(const Ice::Exception& ex) { cout << ex << endl; test(false); } catch(...) { test(false); } } void clear(const CPtr&); #ifdef ICE_CPP11_MAPPING void clear(const BPtr& b) { // No GC with the C++11 mapping if(dynamic_pointer_cast(b->theA)) { auto tmp = b->theA; b->theA = nullptr; clear(dynamic_pointer_cast(tmp)); } if(b->theB) { auto tmp = b->theB; b->theB = nullptr; clear(dynamic_pointer_cast(tmp)); } b->theC = nullptr; } #else void clear(const BPtr&) { } #endif #ifdef ICE_CPP11_MAPPING void clear(const CPtr& c) { // No GC with the C++11 mapping clear(c->theB); c->theB = nullptr; } #else void clear(const CPtr&) { } #endif #ifdef ICE_CPP11_MAPPING void clear(const DPtr& d) { // No GC with the C++11 mapping if(dynamic_pointer_cast(d->theA)) { clear(dynamic_pointer_cast(d->theA)); } d->theA = nullptr; clear(d->theB); d->theB = nullptr; } #else void clear(const DPtr&) { } #endif } InitialPrxPtr allTests(Test::TestHelper* helper) { Ice::CommunicatorPtr communicator = helper->communicator(); cout << "testing stringToProxy... " << flush; string ref = "initial:" + helper->getTestEndpoint(); Ice::ObjectPrxPtr base = communicator->stringToProxy(ref); test(base); cout << "ok" << endl; cout << "testing checked cast... " << flush; InitialPrxPtr initial = ICE_CHECKED_CAST(InitialPrx, base); test(initial); #ifdef ICE_CPP11_MAPPING test(Ice::targetEqualTo(initial, base)); #else test(initial == base); #endif cout << "ok" << endl; cout << "testing constructor, copy constructor, and assignment operator... " << flush; BasePtr ba1 = ICE_MAKE_SHARED(Base); test(ba1->theS.str == ""); test(ba1->str == ""); S s; s.str = "hello"; BasePtr ba2 = ICE_MAKE_SHARED(Base, s, "hi"); test(ba2->theS.str == "hello"); test(ba2->str == "hi"); #ifdef ICE_CPP11_MAPPING test(*ba1 < *ba2); test(*ba2 > *ba1); test(*ba1 != *ba2); #endif *ba1 = *ba2; test(ba1->theS.str == "hello"); test(ba1->str == "hi"); #ifdef ICE_CPP11_MAPPING test(*ba1 == *ba2); test(*ba1 >= *ba2); test(*ba1 <= *ba2); #endif BasePtr bp1 = ICE_MAKE_SHARED(Base); *bp1 = *ba2; test(bp1->theS.str == "hello"); test(bp1->str == "hi"); cout << "ok" << endl; cout << "testing ice_clone..." << flush; BasePtr bp2 = ICE_DYNAMIC_CAST(Base, bp1->ice_clone()); test(bp1->theS.str == bp2->theS.str); test(bp1->str == bp2->str); #ifndef ICE_CPP11_MAPPING // // With C++11 mapping value classes are never abstracts. // AbstractBasePtr abp1 = new AbstractBaseI(); try { abp1->ice_clone(); test(false); } catch(const Ice::CloneNotImplementedException&) { } #endif cout << "ok" << endl; cout << "getting B1... " << flush; BPtr b1 = initial->getB1(); test(b1); cout << "ok" << endl; cout << "getting B2... " << flush; BPtr b2 = initial->getB2(); test(b2); cout << "ok" << endl; cout << "getting C... " << flush; CPtr c = initial->getC(); test(c); cout << "ok" << endl; cout << "getting D... " << flush; DPtr d = initial->getD(); test(d); cout << "ok" << endl; cout << "checking consistency... " << flush; test(b1 != b2); #ifdef ICE_CPP11_MAPPING test(b1 != dynamic_pointer_cast(c)); test(b1 != dynamic_pointer_cast(d)); test(b2 != dynamic_pointer_cast(c)); test(b2 != dynamic_pointer_cast(d)); test(c != dynamic_pointer_cast(d)); #else test(b1 != c); test(b1 != d); test(b2 != c); test(b2 != d); test(c != d); #endif test(b1->theB == b1); test(b1->theC == ICE_NULLPTR); test(ICE_DYNAMIC_CAST(B, b1->theA)); test(ICE_DYNAMIC_CAST(B, b1->theA)->theA == b1->theA); test(ICE_DYNAMIC_CAST(B, b1->theA)->theB == b1); test(ICE_DYNAMIC_CAST(C, ICE_DYNAMIC_CAST(B, b1->theA)->theC)); test(ICE_DYNAMIC_CAST(C, ICE_DYNAMIC_CAST(B, b1->theA)->theC)->theB == b1->theA); test(b1->preMarshalInvoked); test(b1->postUnmarshalInvoked); test(b1->theA->preMarshalInvoked); test(b1->theA->postUnmarshalInvoked); #ifdef ICE_CPP11_MAPPING test(dynamic_pointer_cast(b1->theA)->theC->preMarshalInvoked); test(dynamic_pointer_cast(b1->theA)->theC->postUnmarshalInvoked); #else test(BPtr::dynamicCast(b1->theA)->theC->preMarshalInvoked); test(BPtr::dynamicCast(b1->theA)->theC->postUnmarshalInvoked); #endif // More tests possible for b2 and d, but I think this is already sufficient. test(b2->theA == b2); test(d->theC == ICE_NULLPTR); clear(b1); clear(b2); clear(c); clear(d); cout << "ok" << endl; cout << "getting B1, B2, C, and D all at once... " << flush; initial->getAll(b1, b2, c, d); test(b1); test(b2); test(c); test(d); cout << "ok" << endl; cout << "checking consistency... " << flush; #ifdef ICE_CPP11_MAPPING test(b1 != b2); test(b1 != dynamic_pointer_cast(c)); test(b1 != dynamic_pointer_cast(d)); test(b2 != dynamic_pointer_cast(c)); test(b2 != dynamic_pointer_cast(d)); test(c != dynamic_pointer_cast(d)); test(b1->theA == dynamic_pointer_cast(b2)); test(b1->theB == dynamic_pointer_cast(b1)); test(b1->theC == nullptr); test(b2->theA == b2); test(b2->theB == b1); test(b2->theC == dynamic_pointer_cast(c)); test(c->theB == b2); test(d->theA == dynamic_pointer_cast(b1)); test(d->theB == dynamic_pointer_cast(b2)); test(d->theC == nullptr); #else test(b1 != b2); test(b1 != c); test(b1 != d); test(b2 != c); test(b2 != d); test(c != d); test(b1->theA == b2); test(b1->theB == b1); test(b1->theC == ICE_NULLPTR); test(b2->theA == b2); test(b2->theB == b1); test(b2->theC == c); test(c->theB == b2); test(d->theA == b1); test(d->theB == b2); test(d->theC == ICE_NULLPTR); #endif test(d->preMarshalInvoked); test(d->postUnmarshalInvoked); test(d->theA->preMarshalInvoked); test(d->theA->postUnmarshalInvoked); test(d->theB->preMarshalInvoked); test(d->theB->postUnmarshalInvoked); test(d->theB->theC->preMarshalInvoked); test(d->theB->theC->postUnmarshalInvoked); clear(b1); clear(b2); clear(c); clear(d); cout << "ok" << endl; cout << "testing protected members... " << flush; EIPtr e = ICE_DYNAMIC_CAST(EI, initial->getE()); FIPtr f = ICE_DYNAMIC_CAST(FI, initial->getF()); #ifndef ICE_CPP11_MAPPING test(e->checkValues()); test(f->checkValues()); test(ICE_DYNAMIC_CAST(EI, f->e2)->checkValues()); #endif cout << "ok" << endl; cout << "getting I, J and H... " << flush; #ifdef ICE_CPP11_MAPPING shared_ptr i = initial->getI(); test(i->ice_id() == "::Test::I"); shared_ptr j = initial->getJ(); test(j->ice_id() == "::Test::J"); shared_ptr h = initial->getH(); test(h && dynamic_pointer_cast(h)); #else IPtr i = initial->getI(); test(i); IPtr j = initial->getJ(); test(j && JPtr::dynamicCast(j)); IPtr h = initial->getH(); test(h && HPtr::dynamicCast(h)); #endif cout << "ok" << endl; cout << "getting K... " << flush; { KPtr k = initial->getK(); LPtr l = ICE_DYNAMIC_CAST(L, k->value); test(l); test(l->data == "l"); } cout << "ok" << endl; cout << "testing Value as parameter..." << flush; { LPtr v1 = ICE_MAKE_SHARED(L, "l"); Ice::ValuePtr v2; Ice::ValuePtr v3 = initial->opValue(v1, v2); test(ICE_DYNAMIC_CAST(L, v2)->data == "l"); test(ICE_DYNAMIC_CAST(L, v3)->data == "l"); } { LPtr l = ICE_MAKE_SHARED(L, "l"); Test::ValueSeq v1; v1.push_back(l); Test::ValueSeq v2; Test::ValueSeq v3 = initial->opValueSeq(v1, v2); test(ICE_DYNAMIC_CAST(L, v2[0])->data == "l"); test(ICE_DYNAMIC_CAST(L, v3[0])->data == "l"); } { LPtr l = ICE_MAKE_SHARED(L, "l"); Test::ValueMap v1; v1["l"] = l; Test::ValueMap v2; Test::ValueMap v3 = initial->opValueMap(v1, v2); test(ICE_DYNAMIC_CAST(L, v2["l"])->data == "l"); test(ICE_DYNAMIC_CAST(L, v3["l"])->data == "l"); } cout << "ok" << endl; cout << "getting D1... " << flush; D1Ptr d1 = ICE_MAKE_SHARED(D1, ICE_MAKE_SHARED(A1, "a1"), ICE_MAKE_SHARED(A1, "a2"), ICE_MAKE_SHARED(A1, "a3"), ICE_MAKE_SHARED(A1, "a4")); d1 = initial->getD1(d1); test(d1->a1->name == "a1"); test(d1->a2->name == "a2"); test(d1->a3->name == "a3"); test(d1->a4->name == "a4"); cout << "ok" << endl; cout << "throw EDerived... " << flush; try { initial->throwEDerived(); test(false); } catch(const EDerived& ederived) { test(ederived.a1->name == "a1"); test(ederived.a2->name == "a2"); test(ederived.a3->name == "a3"); test(ederived.a4->name == "a4"); } cout << "ok" << endl; cout << "setting G... " << flush; GPtr g = ICE_MAKE_SHARED(G, s, "g"); try { initial->setG(g); } catch(const Ice::OperationNotExistException&) { } cout << "ok" << endl; cout << "setting I... " << flush; initial->setI(i); initial->setI(j); initial->setI(h); cout << "ok" << endl; cout << "testing sequences... " << flush; BaseSeq inS, outS, retS; retS = initial->opBaseSeq(inS, outS); inS.resize(1); inS[0] = ICE_MAKE_SHARED(Base); retS = initial->opBaseSeq(inS, outS); test(retS.size() == 1 && outS.size() == 1); cout << "ok" << endl; cout << "testing recursive type... " << flush; RecursivePtr top = ICE_MAKE_SHARED(Recursive); int depth = 0; try { RecursivePtr p = top; #if defined(NDEBUG) || !defined(__APPLE__) const int maxDepth = 2000; #else // With debug, marshalling a graph of 2000 elements can cause a stack overflow on macOS const int maxDepth = 1500; #endif for(; depth <= maxDepth; ++depth) { p->v = ICE_MAKE_SHARED(Recursive); p = p->v; if((depth < 10 && (depth % 10) == 0) || (depth < 1000 && (depth % 100) == 0) || (depth < 10000 && (depth % 1000) == 0) || (depth % 10000) == 0) { initial->setRecursive(top); } } test(!initial->supportsClassGraphDepthMax()); } catch(const Ice::UnknownLocalException&) { // Expected marshal exception from the server (max class graph depth reached) test(depth == 100); // The default is 100. } catch(const Ice::UnknownException&) { // Expected stack overflow from the server (Java only) } initial->setRecursive(ICE_MAKE_SHARED(Recursive)); cout << "ok" << endl; cout << "testing compact ID..." << flush; try { test(initial->getCompact()); } catch(const Ice::OperationNotExistException&) { } cout << "ok" << endl; cout << "testing marshaled results..." << flush; b1 = initial->getMB(); test(b1 && b1->theB == b1); clear(b1); #ifdef ICE_CPP11_MAPPING b1 = initial->getAMDMBAsync().get(); #else b1 = initial->end_getAMDMB(initial->begin_getAMDMB()); #endif test(b1 && b1->theB == b1); clear(b1); cout << "ok" << endl; cout << "testing UnexpectedObjectException... " << flush; testUOE(communicator); cout << "ok" << endl; cout << "testing getting ObjectFactory... " << flush; test(communicator->findObjectFactory("TestOF")); cout << "ok" << endl; cout << "testing getting ObjectFactory as ValueFactory... " << flush; test(communicator->getValueFactoryManager()->find("TestOF")); cout << "ok" << endl; try { Ice::PropertiesPtr properties = communicator->getProperties(); TestIntfPrxPtr p = ICE_CHECKED_CAST(TestIntfPrx, communicator->stringToProxy("test:" + TestHelper::getTestEndpoint(properties))); cout << "testing Object factory registration... " << flush; { BasePtr basePtr = p->opDerived(); test(basePtr); test(basePtr->ice_id() == "::Test::Derived"); } cout << "ok" << endl; cout << "testing Exception factory registration... " << flush; { try { p->throwDerived(); } catch(const BaseEx& ex) { test(ex.ice_id() == "::Test::DerivedEx"); } } cout << "ok" << endl; } catch(const Ice::ObjectNotExistException&) { } cout << "testing class containing complex dictionary... " << flush; { Test::MPtr m = ICE_MAKE_SHARED(Test::M); Test::StructKey k1; k1.i = 1; k1.s = "1"; m->v[k1] = ICE_MAKE_SHARED(L, "one"); Test::StructKey k2; k2.i = 2; k2.s = "2"; m->v[k2] = ICE_MAKE_SHARED(L, "two"); Test::MPtr m1; Test::MPtr m2 = initial->opM(m, m1); test(m1->v.size() == 2); test(m2->v.size() == 2); test(m1->v[k1]->data == "one"); test(m2->v[k1]->data == "one"); test(m1->v[k2]->data == "two"); test(m2->v[k2]->data == "two"); } cout << "ok" << endl; cout << "testing forward declarations... " << flush; { F1Ptr f12; F1Ptr f11 = initial->opF1(ICE_MAKE_SHARED(F1, "F11"), f12); test(f11->name == "F11"); test(f12->name == "F12"); F2PrxPtr f22; F2PrxPtr f21 = initial->opF2(ICE_UNCHECKED_CAST(F2Prx, communicator->stringToProxy("F21:" + helper->getTestEndpoint())), f22); test(f21->ice_getIdentity().name == "F21"); f21->op(); test(f22->ice_getIdentity().name == "F22"); if(initial->hasF3()) { F3Ptr f32; F3Ptr f31 = initial->opF3(ICE_MAKE_SHARED(F3, f11, f21), f32); test(f31->f1->name == "F11"); test(f31->f2->ice_getIdentity().name == "F21"); test(f32->f1->name == "F12"); test(f32->f2->ice_getIdentity().name == "F22"); } } cout << "ok" << endl; cout << "testing sending class cycle... " << flush; { RecursivePtr rec = ICE_MAKE_SHARED(Recursive); rec->v = rec; bool acceptsCycles = initial->acceptsClassCycles(); try { initial->setCycle(rec); test(acceptsCycles); } catch(const Ice::UnknownLocalException&) { // expected when the remote server does not accept cycles // and throws a MarshalException test(!acceptsCycles); } rec->v = ICE_NULLPTR; } cout << "ok" << endl; return initial; }