diff options
author | Benoit Foucher <benoit@zeroc.com> | 2009-11-23 13:28:08 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2009-11-23 13:28:08 +0100 |
commit | 2c578015edcb36cdc0acd0227295de1dcca1b995 (patch) | |
tree | e163980b5dabb43a40089a29fdf8ff47a3e07f1c /cpp/test/Ice/operations/OnewaysNewAMI.cpp | |
parent | no longer generating inspect method for each Ruby exception (diff) | |
download | ice-2c578015edcb36cdc0acd0227295de1dcca1b995.tar.bz2 ice-2c578015edcb36cdc0acd0227295de1dcca1b995.tar.xz ice-2c578015edcb36cdc0acd0227295de1dcca1b995.zip |
New AMI mapping
Diffstat (limited to 'cpp/test/Ice/operations/OnewaysNewAMI.cpp')
-rw-r--r-- | cpp/test/Ice/operations/OnewaysNewAMI.cpp | 597 |
1 files changed, 597 insertions, 0 deletions
diff --git a/cpp/test/Ice/operations/OnewaysNewAMI.cpp b/cpp/test/Ice/operations/OnewaysNewAMI.cpp new file mode 100644 index 00000000000..88830c8c954 --- /dev/null +++ b/cpp/test/Ice/operations/OnewaysNewAMI.cpp @@ -0,0 +1,597 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Ice/Ice.h> +#include <TestCommon.h> +#include <Test.h> +#include <StateChanger.h> + +using namespace std; + +namespace +{ + +class CallbackBase : public Ice::LocalObject +{ +public: + + CallbackBase() : + _called(false) + { + } + + virtual ~CallbackBase() + { + } + + void check() + { + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_m); + while(!_called) + { + _m.wait(); + } + _called = false; + } + +protected: + + void called() + { + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_m); + assert(!_called); + _called = true; + _m.notify(); + } + +private: + + IceUtil::Monitor<IceUtil::Mutex> _m; + bool _called; +}; + +typedef IceUtil::Handle<CallbackBase> CallbackBasePtr; + +class NoEndpointCallback : public CallbackBase +{ +public: + + void unsafe(const Ice::AsyncResultPtr& r) + { + try + { + Test::MyClassPrx p = Test::MyClassPrx::uncheckedCast(r->getProxy()); + p->end_opVoid(r); + test(false); + } + catch(const Ice::NoEndpointException&) + { + called(); + } + } + + void success() + { + test(false); + } + + void exCB(const Ice::Exception& ex) + { + test(dynamic_cast<const Ice::NoEndpointException*>(&ex)); + called(); + } + + void sentCB() + { + test(false); + } +}; + +typedef IceUtil::Handle<NoEndpointCallback> NoEndpointCallbackPtr; + +struct Cookie : public Ice::LocalObject +{ + Cookie(int i) : val(i) + { + } + int val; +}; + +typedef IceUtil::Handle<Cookie> CookiePtr; + +class Callback : public CallbackBase +{ +public: + + Callback() + { + } + + void opVoid(const CookiePtr& cookie) + { + test(cookie->val == 99); + called(); + } + + void exCBNC(const Ice::Exception& ex) + { + test(false); + } + + void exCB(const Ice::Exception& ex, const CookiePtr& cookie) + { + test(cookie->val == 99); + called(); + } +}; + +typedef IceUtil::Handle<Callback> CallbackPtr; + +enum ThrowType { LocalException, UserException, StandardException, OtherException }; + +class Thrower : public CallbackBase +{ +public: + + Thrower(ThrowType t) + : _t(t) + { + } + + void exCB(const Ice::Exception& ex) + { + called(); + throwEx(); + } + +private: + + void throwEx() + { + switch(_t) + { + case LocalException: + { + throw Ice::ObjectNotExistException(__FILE__, __LINE__); + break; + } + case UserException: + { + throw Test::SomeException(); + break; + } + case StandardException: + { + throw ::std::bad_alloc(); + break; + } + case OtherException: + { + throw 99; + break; + } + default: + { + assert(false); + break; + } + } + } + + ThrowType _t; +}; + +typedef IceUtil::Handle<Thrower> ThrowerPtr; + +class SentCounter : public CallbackBase +{ +public: + + SentCounter() : _queuedCount(0) + { + } + + void exCB(const Ice::Exception&) + { + test(false); + } + + void sentCB() + { + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_m); + ++_queuedCount; + } + + int queuedCount() + { + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_m); + return _queuedCount; + } + + void check(int size) + { + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_m); + while(_queuedCount != size) + { + _m.wait(); + } + } + +private: + + int _queuedCount; + IceUtil::ThreadControl::ID _id; + IceUtil::Monitor<IceUtil::Mutex> _m; +}; + +typedef IceUtil::Handle<SentCounter> SentCounterPtr; + +} + +void +onewaysNewAMI(const Ice::CommunicatorPtr& communicator, const Test::MyClassPrx& proxy) +{ + Test::MyClassPrx p = Test::MyClassPrx::uncheckedCast(proxy->ice_oneway()); + + { + // + // Check that a call to a void operation raises NoEndpointException + // in the end_ method instead of at the point of call. + // + Test::MyClassPrx indirect = Test::MyClassPrx::uncheckedCast(p->ice_adapterId("dummy")->ice_oneway()); + Ice::AsyncResultPtr r; + + r = indirect->begin_opVoid(); + try + { + indirect->end_opVoid(r); + test(false); + } + catch(const Ice::NoEndpointException&) + { + } + + // + // Check that a second call to the end_ method throws IllegalArgumentException. + // + try + { + indirect->end_opVoid(r); + test(false); + } + catch(const IceUtil::IllegalArgumentException&) + { + } + } + + { + // + // Check that a call to a void operation raises NoEndpointException in the callback. + // Also test that the sent callback is not called in this case. + // + Test::MyClassPrx indirect = Test::MyClassPrx::uncheckedCast(p->ice_adapterId("dummy")->ice_oneway()); + + NoEndpointCallbackPtr cb = new NoEndpointCallback; + + Ice::CallbackPtr callback = Ice::newCallback(cb, &NoEndpointCallback::exCB, &NoEndpointCallback::sentCB); + indirect->begin_opVoid(callback); + cb->check(); + } + + { + // + // Check that calling the end_ method with a different proxy or for a different operation than the begin_ + // method throws IllegalArgumentException. If the test throws as expected, we never call the end_ method, + // so this also tests that it is safe to throw the AsyncResult away without calling the end_ method. + // + Test::MyClassPrx indirect1 = Test::MyClassPrx::uncheckedCast(p->ice_adapterId("dummy")->ice_oneway()); + Test::MyClassPrx indirect2 = Test::MyClassPrx::uncheckedCast(p->ice_adapterId("dummy2"))->ice_oneway(); + + Ice::AsyncResultPtr r1 = indirect1->begin_opVoid(); + Ice::AsyncResultPtr r2 = indirect2->begin_opVoid(); + + try + { + indirect1->end_opVoid(r2); // Wrong proxy + test(false); + } + catch(const IceUtil::IllegalArgumentException&) + { + } + + try + { + indirect1->end_shutdown(r1); // Wrong operation + test(false); + } + catch(const IceUtil::IllegalArgumentException&) + { + } + } + + { + // + // Check that calling the end_ method with a null result throws IllegalArgumentException. + // + try + { + p->end_opVoid(0); + test(false); + } + catch(const IceUtil::IllegalArgumentException&) + { + } + } + + { + // + // Check that passing a null callback Instance throws IllegalArgumentException. + // + CallbackPtr cb; + try + { + Test::newCallback_MyClass_opVoid(cb, &Callback::opVoid, &Callback::exCB); + test(false); + } + catch(IceUtil::IllegalArgumentException&) + { + } + } + + { + // + // Check that throwing an exception from the exception callback doesn't cause problems. + // + Test::MyClassPrx indirect = Test::MyClassPrx::uncheckedCast(p->ice_adapterId("dummy")); + + { + ThrowerPtr cb = new Thrower(LocalException); + Ice::CallbackPtr callback = Ice::newCallback(cb, &Thrower::exCB); + indirect->begin_opVoid(callback); + cb->check(); + } + + { + ThrowerPtr cb = new Thrower(UserException); + Ice::CallbackPtr callback = Ice::newCallback(cb, &Thrower::exCB); + indirect->begin_opVoid(callback); + cb->check(); + } + + { + ThrowerPtr cb = new Thrower(StandardException); + Ice::CallbackPtr callback = Ice::newCallback(cb, &Thrower::exCB); + indirect->begin_opVoid(callback); + cb->check(); + } + + { + ThrowerPtr cb = new Thrower(OtherException); + Ice::CallbackPtr callback = Ice::newCallback(cb, &Thrower::exCB); + indirect->begin_opVoid(callback); + cb->check(); + } + } + + { + // + // Check that CommunicatorDestroyedException is raised directly. + // + Ice::InitializationData initData; + initData.properties = communicator->getProperties()->clone(); + Ice::CommunicatorPtr ic = Ice::initialize(initData); + Ice::ObjectPrx obj = ic->stringToProxy(p->ice_toString())->ice_oneway(); + Test::MyClassPrx p2 = Test::MyClassPrx::uncheckedCast(obj); + + ic->destroy(); + + try + { + p2->begin_opVoid(); + test(false); + } + catch(const Ice::CommunicatorDestroyedException&) + { + // Expected. + } + } + + { + // + // Check that we can call operations on Object asynchronously. + // + { + Ice::AsyncResultPtr r = p->begin_ice_ping(); + try + { + p->end_ice_ping(r); + } + catch(...) + { + test(false); + } + } + + { + CallbackPtr cb = new Callback; + Ice::CallbackPtr callback = Ice::newCallback(cb, &Callback::exCBNC); + p->begin_ice_ping(callback); + } + } + + // + // Test that marshaling works as expected, and that the callbacks for each type of callback work. + // + { + { + Ice::AsyncResultPtr r = p->begin_opVoid(); + p->end_opVoid(r); + } + } + + // + // Test that calling a twoway operation with a oneway proxy raises TwowayOnlyException. + // + { + Ice::AsyncResultPtr r = p->begin_opByte(Ice::Byte(0xff), Ice::Byte(0x0f)); + try + { + Ice::Byte p3; + p->end_opByte(p3, r); + test(false); + } + catch(const Ice::TwowayOnlyException&) + { + } + } + + { + Ice::Double d = 1278312346.0 / 13.0; + Test::DoubleS ds(5, d); + CallbackPtr cb = new Callback; + Ice::CallbackPtr callback = Ice::newCallback(cb, &Callback::exCBNC); + p->begin_opDoubleMarshaling(d, ds, callback); + } + + { + Test::MyDerivedClassPrx derived = Test::MyDerivedClassPrx::uncheckedCast(p); + test(derived); + CallbackPtr cb = new Callback; + Ice::CallbackPtr callback = Ice::newCallback(cb, &Callback::exCBNC); + derived->begin_opDerived(callback); + } + + // + // Test that cookies work. Because the same generated template is instantiated each time, it is not necessary + // to test all possible operations. Instead, we only need to test once for each of the three begin_ methods + // that accept a cookie for a oneway and a twoway operation. + // + + { + Test::MyClassPrx indirect = Test::MyClassPrx::uncheckedCast(p->ice_adapterId("dummy")->ice_oneway()); + CallbackPtr cb = new Callback; + CookiePtr cookie = new Cookie(99); + Ice::CallbackPtr callback = Ice::newCallback(cb, &Callback::exCB); + indirect->begin_opVoid(callback, cookie); + cb->check(); + } + + { + // + // Test that not passing a cookie when one is expected throws IlllegalArgumentException. + // (The opposite, passing a cookie when none is expected, causes a compile-time error.) + // +// CallbackPtr cb = new Callback; +// Test::Callback_MyClass_opVoidPtr callback = Test::newCallback_MyClass_opVoid(cb, +// &Callback::opVoid, +// &Callback::exCB); +// try +// { +// p->begin_opVoid(callback); +// test(false); +// } +// catch(const IceUtil::IllegalArgumentException&) +// { +// } + } + + // + // Test that queuing indication works. + // + { + Ice::AsyncResultPtr r = p->begin_delay(100); + r->waitForSent(); + test(r->isCompleted() && r->isSent()); + p->end_delay(r); + test(r->isCompleted()); + } + + // + // Put the server's adapter into the holding state and pump out requests until one is queued. + // Then activate the adapter again and pump out more until one isn't queued again. + // Check that all the callbacks arrive after calling the end_ method for each request. + // We fill a context with a few kB of data to make sure we don't queue up too many requests. + // + { + const int contextSize = 10; // in Kilobytes + string s(1024, 'a'); // One kilobyte of a's + + Ice::Context ctx; + for(int i = 0; i < contextSize; ++i) + { + ostringstream ss; + ss << "i" << i; + ctx[ss.str()] = s; + } + + // + // Keep all the AsyncResults we get from the begin_ calls, so we can call end_ for each of them. + // + vector<Ice::AsyncResultPtr> results; + + int queuedCount = 0; + + SentCounterPtr cb = new SentCounter; + Ice::CallbackPtr callback = Ice::newCallback(cb, &SentCounter::exCB, &SentCounter::sentCB); + Ice::AsyncResultPtr r; + + Test::StateChangerPrx state = Test::StateChangerPrx::checkedCast( + communicator->stringToProxy("hold:default -p 12011")); + state->hold(3); + + do + { + r = p->begin_opVoid(ctx, callback); + results.push_back(r); + if(!r->sentSynchronously()) + { + ++queuedCount; + } + } + while(r->sentSynchronously()); + + vector<Ice::AsyncResultPtr>::size_type numRequests = results.size(); + test(numRequests > 1); // Something is wrong if we didn't get something out without queueing. + + // + // Re-enable the adapter. + // + state->activate(3); + + // + // Fire off a bunch more requests until we get one that wasn't queued. + // We sleep in between calls to allow the queued requests to drain. + // + do + { + r = p->begin_opVoid(callback); + results.push_back(r); + if(!r->sentSynchronously()) + { + ++queuedCount; + } + IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(1)); + } + while(!r->sentSynchronously()); + test(results.size() > numRequests); // Something is wrong if we didn't queue additional requests. + + // + // Now make all the outstanding calls to the end_ method. + // + for(vector<Ice::AsyncResultPtr>::iterator q = results.begin(); q != results.end(); ++q) + { + p->end_opVoid(*q); + } + + // + // Check that that we got a sent callback for each queued request. + // + cb->check(queuedCount); + } +} |