summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2017-03-23 15:29:25 +0100
committerBenoit Foucher <benoit@zeroc.com>2017-03-23 15:29:25 +0100
commit1597a75419cd8049252cfbca6fce6ae95ef8b2c7 (patch)
tree2b2c858df1dbe68c1d576cae06c4713fd2ad5c40
parentUse Ice\None with PHP namespace mapping (diff)
downloadice-1597a75419cd8049252cfbca6fce6ae95ef8b2c7.tar.bz2
ice-1597a75419cd8049252cfbca6fce6ae95ef8b2c7.tar.xz
ice-1597a75419cd8049252cfbca6fce6ae95ef8b2c7.zip
Fix for ICE-7125 - Added support for Ice.ClassGraphDepthMax
-rw-r--r--CHANGELOG-3.7.md13
-rw-r--r--config/PropertyNames.xml1
-rw-r--r--cpp/include/Ice/InputStream.h25
-rw-r--r--cpp/src/Ice/InputStream.cpp52
-rw-r--r--cpp/src/Ice/Instance.cpp14
-rw-r--r--cpp/src/Ice/Instance.h2
-rw-r--r--cpp/src/Ice/PropertyNames.cpp3
-rw-r--r--cpp/src/Ice/PropertyNames.h2
-rw-r--r--cpp/src/Ice/ThreadPool.cpp11
-rw-r--r--cpp/test/Ice/echo/BlobjectI.cpp41
-rw-r--r--cpp/test/Ice/echo/BlobjectI.h6
-rw-r--r--cpp/test/Ice/echo/Server.cpp5
-rw-r--r--cpp/test/Ice/echo/Test.ice1
-rw-r--r--cpp/test/Ice/echo/test.py5
-rw-r--r--cpp/test/Ice/exceptions/AllTests.cpp40
-rw-r--r--cpp/test/Ice/objects/AllTests.cpp32
-rw-r--r--cpp/test/Ice/objects/Collocated.cpp1
-rw-r--r--cpp/test/Ice/objects/Server.cpp1
-rw-r--r--cpp/test/Ice/objects/Test.ice8
-rw-r--r--cpp/test/Ice/objects/TestI.cpp11
-rw-r--r--cpp/test/Ice/objects/TestI.h3
-rw-r--r--csharp/src/Ice/InputStream.cs110
-rw-r--r--csharp/src/Ice/Instance.cs20
-rw-r--r--csharp/src/Ice/PropertyNames.cs3
-rw-r--r--csharp/test/Ice/exceptions/AllTests.cs39
-rw-r--r--csharp/test/Ice/objects/AllTests.cs32
-rw-r--r--csharp/test/Ice/objects/Collocated.cs7
-rw-r--r--csharp/test/Ice/objects/InitialI.cs13
-rw-r--r--csharp/test/Ice/objects/Server.cs7
-rw-r--r--csharp/test/Ice/objects/Test.ice8
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ConnectionI.java8
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/CollocatedRequestHandler.java14
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java3
-rw-r--r--java-compat/test/src/main/java/test/Ice/exceptions/AllTests.java39
-rw-r--r--java-compat/test/src/main/java/test/Ice/objects/AllTests.java37
-rw-r--r--java-compat/test/src/main/java/test/Ice/objects/Collocated.java1
-rw-r--r--java-compat/test/src/main/java/test/Ice/objects/InitialI.java17
-rw-r--r--java-compat/test/src/main/java/test/Ice/objects/Server.java1
-rw-r--r--java-compat/test/src/main/java/test/Ice/objects/Test.ice8
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/Ice/ConnectionI.java8
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceInternal/CollocatedRequestHandler.java14
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java3
-rw-r--r--java/test/src/main/java/test/Ice/exceptions/AllTests.java43
-rw-r--r--java/test/src/main/java/test/Ice/objects/AllTests.java37
-rw-r--r--java/test/src/main/java/test/Ice/objects/Collocated.java1
-rw-r--r--java/test/src/main/java/test/Ice/objects/InitialI.java11
-rw-r--r--java/test/src/main/java/test/Ice/objects/Server.java1
-rw-r--r--java/test/src/main/java/test/Ice/objects/Test.ice8
-rw-r--r--js/bin/HttpServer.js20
-rw-r--r--js/src/Ice/Buffer.js14
-rw-r--r--js/src/Ice/ConnectionI.js14
-rw-r--r--js/src/Ice/Exception.js15
-rw-r--r--js/src/Ice/IncomingAsync.js77
-rw-r--r--js/src/Ice/ObjectAdapterFactory.js2
-rw-r--r--js/src/Ice/PropertyNames.js3
-rw-r--r--js/src/Ice/Stream.js4
-rw-r--r--js/src/Ice/TraceUtil.js19
-rw-r--r--js/test/Common/ControllerI.js126
-rw-r--r--js/test/Common/ControllerWorker.js26
-rw-r--r--js/test/Common/TestRunner.js55
-rw-r--r--js/test/Common/TestSuites.json12
-rw-r--r--js/test/Common/controller.html8
-rwxr-xr-xjs/test/Common/run.js33
-rw-r--r--js/test/Ice/exceptions/AMDThrowerI.js1
-rw-r--r--js/test/Ice/exceptions/Client.js39
-rw-r--r--js/test/Ice/exceptions/Server.js56
-rw-r--r--js/test/Ice/exceptions/ServerAMD.js57
-rw-r--r--js/test/Ice/exceptions/Test.ice1
-rw-r--r--js/test/Ice/exceptions/ThrowerI.js2
-rw-r--r--js/test/Ice/facets/Server.js (renamed from js/test/Ice/facets/ClientBidir.js)92
-rw-r--r--js/test/Ice/facets/Test.ice1
-rw-r--r--js/test/Ice/inheritance/ClientBidir.js73
-rw-r--r--js/test/Ice/inheritance/Server.js49
-rw-r--r--js/test/Ice/inheritance/Test.ice1
-rw-r--r--js/test/Ice/objects/Client.js72
-rw-r--r--js/test/Ice/objects/InitialI.js319
-rw-r--r--js/test/Ice/objects/Server.js58
-rw-r--r--js/test/Ice/objects/Test.ice16
-rw-r--r--js/test/Ice/operations/AMDMyDerivedClassI.js10
-rw-r--r--js/test/Ice/operations/ClientBidir.js68
-rw-r--r--js/test/Ice/operations/MyDerivedClassI.js10
-rw-r--r--js/test/Ice/operations/Server.js49
-rw-r--r--js/test/Ice/operations/ServerAMD.js49
-rw-r--r--js/test/Ice/operations/Test.ice3
-rw-r--r--js/test/Ice/optional/AMDInitialI.js5
-rw-r--r--js/test/Ice/optional/Client.js9
-rw-r--r--js/test/Ice/optional/ClientBidir.js82
-rw-r--r--js/test/Ice/optional/ClientPrivate.ice16
-rw-r--r--js/test/Ice/optional/InitialI.js5
-rw-r--r--js/test/Ice/optional/Server.js48
-rw-r--r--js/test/Ice/optional/ServerAMD.js49
-rw-r--r--js/test/Ice/optional/Test.ice11
-rw-r--r--objective-c/test/Ice/exceptions/AllTests.m38
-rw-r--r--objective-c/test/Ice/objects/AllTests.m32
-rw-r--r--objective-c/test/Ice/objects/Collocated.m1
-rw-r--r--objective-c/test/Ice/objects/ObjectsTest.ice8
-rw-r--r--objective-c/test/Ice/objects/Server.m1
-rw-r--r--objective-c/test/Ice/objects/TestI.m9
-rw-r--r--php/test/Ice/exceptions/Client.php5
-rw-r--r--php/test/Ice/objects/Client.php45
-rw-r--r--php/test/Ice/objects/Test.ice8
-rw-r--r--python/test/Ice/exceptions/AllTests.py2
-rw-r--r--python/test/Ice/objects/AllTests.py25
-rwxr-xr-xpython/test/Ice/objects/Collocated.py5
-rwxr-xr-xpython/test/Ice/objects/Server.py7
-rw-r--r--python/test/Ice/objects/Test.ice8
-rw-r--r--python/test/Ice/objects/TestI.py6
-rw-r--r--ruby/test/Ice/exceptions/AllTests.rb2
-rw-r--r--ruby/test/Ice/objects/AllTests.rb26
-rw-r--r--ruby/test/Ice/objects/Test.ice8
-rwxr-xr-xscripts/Controller.py2
-rw-r--r--scripts/LocalDriver.py11
-rw-r--r--scripts/Util.py130
-rw-r--r--scripts/tests/Ice/exceptions.py8
-rw-r--r--scripts/tests/Ice/objects.py20
-rw-r--r--scripts/tests/Ice/optional.py7
116 files changed, 2147 insertions, 716 deletions
diff --git a/CHANGELOG-3.7.md b/CHANGELOG-3.7.md
index 809930f7010..35cc50ade1a 100644
--- a/CHANGELOG-3.7.md
+++ b/CHANGELOG-3.7.md
@@ -17,6 +17,19 @@ These are the changes since Ice 3.6.3.
## General Changes
+- Added support for a new Ice.ClassGraphDepthMax property to prevent stack
+ overflows in case a sender sends a very large graph.
+
+ The unmarshaling or destruction of a graph of Slice class instances is a
+ recursive operation. This property limits the amount of stack size required to
+ perform these operations. This property is supported with all the language
+ mappings except Java and JavaScript where it's not needed (the runtime
+ environment allows graceful handling or stack overflows).
+
+ The default maximum class graph depth is 100. If you increase this value, you
+ must ensure the thread pool stack size is large enough to allow reading graphs
+ without causing a stack overflow.
+
- Added support for IceStorm subscriber `locatorCacheTimeout` and
`connectionCached` QoS settings. These settings match the proxy settings and
allow configuring per-request load balancing on the subscriber proxy.
diff --git a/config/PropertyNames.xml b/config/PropertyNames.xml
index c12367fc58e..93d56730542 100644
--- a/config/PropertyNames.xml
+++ b/config/PropertyNames.xml
@@ -327,6 +327,7 @@ generated from the section label.
<property name="BatchAutoFlush" deprecated="true"/>
<property name="BatchAutoFlushSize" />
<property name="ChangeUser" />
+ <property name="ClassGraphDepthMax" />
<property name="ClientAccessPolicyProtocol" />
<property name="Compression.Level" />
<property name="CollectObjects"/>
diff --git a/cpp/include/Ice/InputStream.h b/cpp/include/Ice/InputStream.h
index 4684d0eda69..363f41767ed 100644
--- a/cpp/include/Ice/InputStream.h
+++ b/cpp/include/Ice/InputStream.h
@@ -138,6 +138,8 @@ public:
void setTraceSlicing(bool);
+ void setClassGraphDepthMax(size_t);
+
void* getClosure() const;
void* setClosure(void*);
@@ -738,8 +740,10 @@ private:
protected:
- EncapsDecoder(InputStream* stream, Encaps* encaps, bool sliceValues, const Ice::ValueFactoryManagerPtr& f) :
- _stream(stream), _encaps(encaps), _sliceValues(sliceValues), _valueFactoryManager(f), _typeIdIndex(0)
+ EncapsDecoder(InputStream* stream, Encaps* encaps, bool sliceValues, size_t classGraphDepthMax,
+ const Ice::ValueFactoryManagerPtr& f) :
+ _stream(stream), _encaps(encaps), _sliceValues(sliceValues), _classGraphDepthMax(classGraphDepthMax),
+ _classGraphDepth(0), _valueFactoryManager(f), _typeIdIndex(0)
{
}
@@ -756,6 +760,7 @@ private:
{
PatchFunc patchFunc;
void* patchAddr;
+ size_t classGraphDepth;
};
typedef std::vector<PatchEntry> PatchList;
typedef std::map<Int, PatchList> PatchMap;
@@ -763,6 +768,8 @@ private:
InputStream* _stream;
Encaps* _encaps;
const bool _sliceValues;
+ const size_t _classGraphDepthMax;
+ size_t _classGraphDepth;
Ice::ValueFactoryManagerPtr _valueFactoryManager;
// Encapsulation attributes for object un-marshalling
@@ -781,8 +788,10 @@ private:
{
public:
- EncapsDecoder10(InputStream* stream, Encaps* encaps, bool sliceValues, const Ice::ValueFactoryManagerPtr& f) :
- EncapsDecoder(stream, encaps, sliceValues, f), _sliceType(NoSlice)
+ EncapsDecoder10(InputStream* stream, Encaps* encaps, bool sliceValues, size_t classGraphDepthMax,
+ const Ice::ValueFactoryManagerPtr& f) :
+ EncapsDecoder(stream, encaps, sliceValues, classGraphDepthMax, f),
+ _sliceType(NoSlice)
{
}
@@ -814,8 +823,10 @@ private:
{
public:
- EncapsDecoder11(InputStream* stream, Encaps* encaps, bool sliceValues, const Ice::ValueFactoryManagerPtr& f) :
- EncapsDecoder(stream, encaps, sliceValues, f), _preAllocatedInstanceData(0), _current(0), _valueIdIndex(1)
+ EncapsDecoder11(InputStream* stream, Encaps* encaps, bool sliceValues, size_t classGraphDepthMax,
+ const Ice::ValueFactoryManagerPtr& f) :
+ EncapsDecoder(stream, encaps, sliceValues, classGraphDepthMax, f),
+ _preAllocatedInstanceData(0), _current(0), _valueIdIndex(1)
{
}
@@ -956,6 +967,8 @@ private:
bool _traceSlicing;
+ size_t _classGraphDepthMax;
+
void* _closure;
bool _sliceValues;
diff --git a/cpp/src/Ice/InputStream.cpp b/cpp/src/Ice/InputStream.cpp
index e10bc107df9..61f71c7b5ba 100644
--- a/cpp/src/Ice/InputStream.cpp
+++ b/cpp/src/Ice/InputStream.cpp
@@ -167,6 +167,7 @@ Ice::InputStream::initialize(Instance* instance, const EncodingVersion& encoding
_collectObjects = _instance->collectObjects();
#endif
_traceSlicing = _instance->traceLevels()->slicing > 0;
+ _classGraphDepthMax = _instance->classGraphDepthMax();
}
void
@@ -179,6 +180,7 @@ Ice::InputStream::initialize(const EncodingVersion& encoding)
_collectObjects = false;
#endif
_traceSlicing = false;
+ _classGraphDepthMax = 0x7fffffff;
_closure = 0;
_sliceValues = true;
_startSeq = -1;
@@ -241,6 +243,19 @@ Ice::InputStream::setTraceSlicing(bool b)
_traceSlicing = b;
}
+void
+Ice::InputStream::setClassGraphDepthMax(size_t classGraphDepthMax)
+{
+ if(classGraphDepthMax < 1)
+ {
+ _classGraphDepthMax = 0x7fffffff;
+ }
+ else
+ {
+ _classGraphDepthMax = classGraphDepthMax;
+ }
+}
+
void*
Ice::InputStream::getClosure() const
{
@@ -266,6 +281,7 @@ Ice::InputStream::swap(InputStream& other)
std::swap(_collectObjects, other._collectObjects);
#endif
std::swap(_traceSlicing, other._traceSlicing);
+ std::swap(_classGraphDepthMax, other._classGraphDepthMax);
std::swap(_closure, other._closure);
std::swap(_sliceValues, other._sliceValues);
@@ -1740,11 +1756,11 @@ Ice::InputStream::initEncaps()
ValueFactoryManagerPtr vfm = valueFactoryManager();
if(_currentEncaps->encoding == Encoding_1_0)
{
- _currentEncaps->decoder = new EncapsDecoder10(this, _currentEncaps, _sliceValues, vfm);
+ _currentEncaps->decoder = new EncapsDecoder10(this, _currentEncaps, _sliceValues, _classGraphDepthMax, vfm);
}
else
{
- _currentEncaps->decoder = new EncapsDecoder11(this, _currentEncaps, _sliceValues, vfm);
+ _currentEncaps->decoder = new EncapsDecoder11(this, _currentEncaps, _sliceValues, _classGraphDepthMax, vfm);
}
}
}
@@ -1884,6 +1900,7 @@ Ice::InputStream::EncapsDecoder::addPatchEntry(Int index, PatchFunc patchFunc, v
PatchEntry e;
e.patchFunc = patchFunc;
e.patchAddr = patchAddr;
+ e.classGraphDepth = _classGraphDepth;
q->second.push_back(e);
}
@@ -2233,6 +2250,30 @@ Ice::InputStream::EncapsDecoder10::readInstance()
}
//
+ // Compute the biggest class graph depth of this object. To compute this,
+ // we get the class graph depth of each ancestor from the patch map and
+ // keep the biggest one.
+ //
+ _classGraphDepth = 0;
+ PatchMap::iterator patchPos = _patchMap.find(index);
+ if(patchPos != _patchMap.end())
+ {
+ assert(patchPos->second.size() > 0);
+ for(PatchList::iterator k = patchPos->second.begin(); k != patchPos->second.end(); ++k)
+ {
+ if(k->classGraphDepth > _classGraphDepth)
+ {
+ _classGraphDepth = k->classGraphDepth;
+ }
+ }
+ }
+
+ if(++_classGraphDepth > _classGraphDepthMax)
+ {
+ throw MarshalException(__FILE__, __LINE__, "maximum class graph depth reached");
+ }
+
+ //
// Unmarshal the instance and add it to the map of unmarshaled instances.
//
unmarshal(index, v);
@@ -2668,11 +2709,18 @@ Ice::InputStream::EncapsDecoder11::readInstance(Int index, PatchFunc patchFunc,
startSlice(); // Read next Slice header for next iteration.
}
+ if(++_classGraphDepth > _classGraphDepthMax)
+ {
+ throw MarshalException(__FILE__, __LINE__, "maximum class graph depth reached");
+ }
+
//
// Unmarshal the object.
//
unmarshal(index, v);
+ --_classGraphDepth;
+
if(!_current && !_patchMap.empty())
{
//
diff --git a/cpp/src/Ice/Instance.cpp b/cpp/src/Ice/Instance.cpp
index c49e386d2e9..cba9085ba4f 100644
--- a/cpp/src/Ice/Instance.cpp
+++ b/cpp/src/Ice/Instance.cpp
@@ -948,6 +948,7 @@ IceInternal::Instance::Instance(const CommunicatorPtr& communicator, const Initi
_initData(initData),
_messageSizeMax(0),
_batchAutoFlushSize(0),
+ _classGraphDepthMax(0),
_collectObjects(false),
_toStringMode(ICE_ENUM(ToStringMode, Unicode)),
_implicitContext(0),
@@ -1189,6 +1190,19 @@ IceInternal::Instance::Instance(const CommunicatorPtr& communicator, const Initi
}
}
+ {
+ static const int defaultValue = 100;
+ Int num = _initData.properties->getPropertyAsIntWithDefault("Ice.ClassGraphDepthMax", defaultValue);
+ if(num < 1 || static_cast<size_t>(num) > static_cast<size_t>(0x7fffffff))
+ {
+ const_cast<size_t&>(_classGraphDepthMax) = static_cast<size_t>(0x7fffffff);
+ }
+ else
+ {
+ const_cast<size_t&>(_classGraphDepthMax) = static_cast<size_t>(num);
+ }
+ }
+
const_cast<bool&>(_collectObjects) = _initData.properties->getPropertyAsInt("Ice.CollectObjects") > 0;
string toStringModeStr = _initData.properties->getPropertyWithDefault("Ice.ToStringMode", "Unicode");
diff --git a/cpp/src/Ice/Instance.h b/cpp/src/Ice/Instance.h
index ba1d367b84f..9bcc78e0990 100644
--- a/cpp/src/Ice/Instance.h
+++ b/cpp/src/Ice/Instance.h
@@ -108,6 +108,7 @@ public:
Ice::PluginManagerPtr pluginManager() const;
size_t messageSizeMax() const { return _messageSizeMax; }
size_t batchAutoFlushSize() const { return _batchAutoFlushSize; }
+ size_t classGraphDepthMax() const { return _classGraphDepthMax; }
bool collectObjects() const { return _collectObjects; }
Ice::ToStringMode toStringMode() const { return _toStringMode; }
const ACMConfig& clientACM() const;
@@ -176,6 +177,7 @@ private:
const DefaultsAndOverridesPtr _defaultsAndOverrides; // Immutable, not reset by destroy().
const size_t _messageSizeMax; // Immutable, not reset by destroy().
const size_t _batchAutoFlushSize; // Immutable, not reset by destroy().
+ const size_t _classGraphDepthMax; // Immutable, not reset by destroy().
const bool _collectObjects; // Immutable, not reset by destroy().
const Ice::ToStringMode _toStringMode; // Immutable, not reset by destroy()
ACMConfig _clientACM;
diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp
index 02ee0f7ac2c..527d7e84d6d 100644
--- a/cpp/src/Ice/PropertyNames.cpp
+++ b/cpp/src/Ice/PropertyNames.cpp
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Mar 23 15:24:16 2017
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -77,6 +77,7 @@ const IceInternal::Property IcePropsData[] =
IceInternal::Property("Ice.BatchAutoFlush", true, 0),
IceInternal::Property("Ice.BatchAutoFlushSize", false, 0),
IceInternal::Property("Ice.ChangeUser", false, 0),
+ IceInternal::Property("Ice.ClassGraphDepthMax", false, 0),
IceInternal::Property("Ice.ClientAccessPolicyProtocol", false, 0),
IceInternal::Property("Ice.Compression.Level", false, 0),
IceInternal::Property("Ice.CollectObjects", false, 0),
diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h
index 171fa1bed8c..485d4afaaa1 100644
--- a/cpp/src/Ice/PropertyNames.h
+++ b/cpp/src/Ice/PropertyNames.h
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Mar 23 15:24:16 2017
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
diff --git a/cpp/src/Ice/ThreadPool.cpp b/cpp/src/Ice/ThreadPool.cpp
index 946a05e2b08..4b14a7e1ce8 100644
--- a/cpp/src/Ice/ThreadPool.cpp
+++ b/cpp/src/Ice/ThreadPool.cpp
@@ -346,7 +346,16 @@ IceInternal::ThreadPool::ThreadPool(const InstancePtr& instance, const string& p
_selector.setup(_sizeIO);
#endif
- int stackSize = properties->getPropertyAsInt(_prefix + ".StackSize");
+#if defined(__APPLE__)
+ //
+ // We use a default stack size of 1MB on macOS and the new C++11 mapping to allow transmitting
+ // class graphs with a depth of 100 (maximum default), 512KB is not enough otherwise.
+ //
+ int defaultStackSize = 1024 * 1024; // 1MB
+#else
+ int defaultStackSize = 0;
+#endif
+ int stackSize = properties->getPropertyAsIntWithDefault(_prefix + ".StackSize", defaultStackSize);
if(stackSize < 0)
{
Warning out(_instance->initializationData().logger);
diff --git a/cpp/test/Ice/echo/BlobjectI.cpp b/cpp/test/Ice/echo/BlobjectI.cpp
index 024b239ac4f..894e217569c 100644
--- a/cpp/test/Ice/echo/BlobjectI.cpp
+++ b/cpp/test/Ice/echo/BlobjectI.cpp
@@ -54,6 +54,14 @@ BlobjectI::BlobjectI() :
}
void
+BlobjectI::setConnection(const Ice::ConnectionPtr& connection)
+{
+ Lock sync(*this);
+ _connection = connection;
+ notifyAll();
+}
+
+void
BlobjectI::startBatch()
{
assert(!_batchProxy);
@@ -75,8 +83,9 @@ BlobjectI::ice_invokeAsync(std::vector<Ice::Byte> inEncaps,
std::function<void(std::exception_ptr)> ex,
const Ice::Current& current)
{
+ auto connection = getConnection(current);
const bool twoway = current.requestId > 0;
- auto obj = current.con->createProxy(current.id);
+ auto obj = connection->createProxy(current.id);
if(!twoway)
{
if(_startBatch)
@@ -124,8 +133,9 @@ void
BlobjectI::ice_invoke_async(const Ice::AMD_Object_ice_invokePtr& amdCb, const vector<Ice::Byte>& inEncaps,
const Ice::Current& current)
{
+ Ice::ConnectionPtr connection = getConnection(current);
const bool twoway = current.requestId > 0;
- Ice::ObjectPrx obj = current.con->createProxy(current.id);
+ Ice::ObjectPrx obj = connection->createProxy(current.id);
if(!twoway)
{
if(_startBatch)
@@ -171,3 +181,30 @@ BlobjectI::ice_invoke_async(const Ice::AMD_Object_ice_invokePtr& amdCb, const ve
}
}
#endif
+
+Ice::ConnectionPtr
+BlobjectI::getConnection(const Ice::Current& current)
+{
+ Lock sync(*this);
+ if(!_connection)
+ {
+ return current.con;
+ }
+
+ try
+ {
+ _connection->throwException();
+ }
+ catch(const Ice::ConnectionLostException&)
+ {
+ // If we lost the connection, wait 5 seconds for the server to re-establish it. Some tests,
+ // involve connection closure (e.g.: exceptions MemoryLimitException test) and the server
+ // automatically re-establishes the connection with the echo server.
+ timedWait(IceUtil::Time::seconds(5));
+ if(!_connection)
+ {
+ throw;
+ }
+ }
+ return _connection;
+}
diff --git a/cpp/test/Ice/echo/BlobjectI.h b/cpp/test/Ice/echo/BlobjectI.h
index fe8091c8f88..16db90e0b5c 100644
--- a/cpp/test/Ice/echo/BlobjectI.h
+++ b/cpp/test/Ice/echo/BlobjectI.h
@@ -12,7 +12,7 @@
#include <Ice/Object.h>
-class BlobjectI : public Ice::BlobjectAsync
+class BlobjectI : public Ice::BlobjectAsync, private IceUtil::Monitor<IceUtil::Mutex>
{
public:
@@ -20,6 +20,7 @@ public:
void startBatch();
void flushBatch();
+ void setConnection(const Ice::ConnectionPtr&);
#ifdef ICE_CPP11_MAPPING
@@ -35,8 +36,11 @@ public:
private:
+ Ice::ConnectionPtr getConnection(const Ice::Current&);
+
bool _startBatch;
Ice::ObjectPrxPtr _batchProxy;
+ Ice::ConnectionPtr _connection;
};
ICE_DEFINE_PTR(BlobjectIPtr, BlobjectI);
diff --git a/cpp/test/Ice/echo/Server.cpp b/cpp/test/Ice/echo/Server.cpp
index 56cd9f534bf..b0576241b02 100644
--- a/cpp/test/Ice/echo/Server.cpp
+++ b/cpp/test/Ice/echo/Server.cpp
@@ -25,6 +25,11 @@ public:
{
}
+ virtual void setConnection(const Ice::Current& current)
+ {
+ _blob->setConnection(current.con);
+ }
+
virtual void startBatch(const Ice::Current&)
{
_blob->startBatch();
diff --git a/cpp/test/Ice/echo/Test.ice b/cpp/test/Ice/echo/Test.ice
index 57f7e92da21..7cf7ec721bd 100644
--- a/cpp/test/Ice/echo/Test.ice
+++ b/cpp/test/Ice/echo/Test.ice
@@ -17,6 +17,7 @@ module Test
//
interface Echo
{
+ void setConnection();
void startBatch();
void flushBatch();
void shutdown();
diff --git a/cpp/test/Ice/echo/test.py b/cpp/test/Ice/echo/test.py
index 3f25f4bfa15..717826f73a2 100644
--- a/cpp/test/Ice/echo/test.py
+++ b/cpp/test/Ice/echo/test.py
@@ -9,7 +9,10 @@
class EchoServerTestCase(ClientServerTestCase):
+ def __init__(self):
+ ClientServerTestCase.__init__(self, "server", server=Server(quiet=True, waitForShutdown=False))
+
def runClientSide(self, current):
pass
-TestSuite(__name__, [EchoServerTestCase(name="server", server=Server(quiet=True, waitForShutdown=False))])
+TestSuite(__name__, [EchoServerTestCase()])
diff --git a/cpp/test/Ice/exceptions/AllTests.cpp b/cpp/test/Ice/exceptions/AllTests.cpp
index 7fb9c1a930a..32302c5c6d8 100644
--- a/cpp/test/Ice/exceptions/AllTests.cpp
+++ b/cpp/test/Ice/exceptions/AllTests.cpp
@@ -988,32 +988,42 @@ allTests(const Ice::CommunicatorPtr& communicator)
catch(const Ice::ConnectionLostException&)
{
}
+ catch(const Ice::UnknownLocalException&)
+ {
+ // Expected with JS bidir server
+ }
catch(const Ice::LocalException& ex)
{
cerr << ex << endl;
test(false);
}
- ThrowerPrxPtr thrower2 =
- ICE_UNCHECKED_CAST(ThrowerPrx, communicator->stringToProxy("thrower:" + getTestEndpoint(communicator, 1)));
- try
- {
- thrower2->throwMemoryLimitException(Ice::ByteSeq(2 * 1024 * 1024)); // 2MB (no limits)
- }
- catch(const Ice::MemoryLimitException&)
- {
- }
- ThrowerPrxPtr thrower3 =
- ICE_UNCHECKED_CAST(ThrowerPrx, communicator->stringToProxy("thrower:" + getTestEndpoint(communicator, 2)));
try
{
- thrower3->throwMemoryLimitException(Ice::ByteSeq(1024)); // 1KB limit
- test(false);
+ ThrowerPrxPtr thrower2 =
+ ICE_UNCHECKED_CAST(ThrowerPrx, communicator->stringToProxy("thrower:" + getTestEndpoint(communicator, 1)));
+ try
+ {
+ thrower2->throwMemoryLimitException(Ice::ByteSeq(2 * 1024 * 1024)); // 2MB (no limits)
+ }
+ catch(const Ice::MemoryLimitException&)
+ {
+ }
+ ThrowerPrxPtr thrower3 =
+ ICE_UNCHECKED_CAST(ThrowerPrx, communicator->stringToProxy("thrower:" + getTestEndpoint(communicator, 2)));
+ try
+ {
+ thrower3->throwMemoryLimitException(Ice::ByteSeq(1024)); // 1KB limit
+ test(false);
+ }
+ catch(const Ice::ConnectionLostException&)
+ {
+ }
}
- catch(const Ice::ConnectionLostException&)
+ catch(const Ice::ConnectionRefusedException&)
{
+ // Expected with JS bidir server
}
-
cout << "ok" << endl;
}
diff --git a/cpp/test/Ice/objects/AllTests.cpp b/cpp/test/Ice/objects/AllTests.cpp
index 5e6ba0460b8..95d44d6b962 100644
--- a/cpp/test/Ice/objects/AllTests.cpp
+++ b/cpp/test/Ice/objects/AllTests.cpp
@@ -323,6 +323,38 @@ allTests(const Ice::CommunicatorPtr& communicator)
test(retS.size() == 1 && outS.size() == 1);
cout << "ok" << endl;
+ cout << "testing recursive type... " << flush;
+ RecursivePtr top = ICE_MAKE_SHARED(Recursive);
+ RecursivePtr p = top;
+ int depth = 0;
+ try
+ {
+ for(; depth <= 2000; ++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
{
diff --git a/cpp/test/Ice/objects/Collocated.cpp b/cpp/test/Ice/objects/Collocated.cpp
index 60330b7061b..8c2d71b399b 100644
--- a/cpp/test/Ice/objects/Collocated.cpp
+++ b/cpp/test/Ice/objects/Collocated.cpp
@@ -154,6 +154,7 @@ main(int argc, char* argv[])
try
{
Ice::InitializationData initData = getTestInitData(argc, argv);
+ initData.properties->setProperty("Ice.Warn.Dispatch", "0");
Ice::CommunicatorHolder ich(argc, argv, initData);
return run(argc, argv, ich.communicator());
}
diff --git a/cpp/test/Ice/objects/Server.cpp b/cpp/test/Ice/objects/Server.cpp
index 991233bfa0a..a501281b29b 100644
--- a/cpp/test/Ice/objects/Server.cpp
+++ b/cpp/test/Ice/objects/Server.cpp
@@ -88,6 +88,7 @@ main(int argc, char* argv[])
try
{
Ice::InitializationData initData = getTestInitData(argc, argv);
+ initData.properties->setProperty("Ice.Warn.Dispatch", "0");
Ice::CommunicatorHolder ich(argc, argv, initData);
return run(argc, argv, ich.communicator());
}
diff --git a/cpp/test/Ice/objects/Test.ice b/cpp/test/Ice/objects/Test.ice
index 134a1aa2ea5..7d64f20614e 100644
--- a/cpp/test/Ice/objects/Test.ice
+++ b/cpp/test/Ice/objects/Test.ice
@@ -167,6 +167,11 @@ exception EDerived extends EBase
A1 a4;
};
+class Recursive
+{
+ Recursive v;
+};
+
interface Initial
{
void shutdown();
@@ -177,6 +182,9 @@ interface Initial
E getE();
F getF();
+ void setRecursive(Recursive p);
+ bool supportsClassGraphDepthMax();
+
["marshaled-result"] B getMB();
["amd", "marshaled-result"] B getAMDMB();
diff --git a/cpp/test/Ice/objects/TestI.cpp b/cpp/test/Ice/objects/TestI.cpp
index f17e1a7960d..803a278fba7 100644
--- a/cpp/test/Ice/objects/TestI.cpp
+++ b/cpp/test/Ice/objects/TestI.cpp
@@ -161,6 +161,17 @@ InitialI::getF(const Ice::Current&)
return _f;
}
+void
+InitialI::setRecursive(ICE_IN(RecursivePtr), const Ice::Current&)
+{
+}
+
+bool
+InitialI::supportsClassGraphDepthMax(const Ice::Current&)
+{
+ return true;
+}
+
#ifdef ICE_CPP11_MAPPING
InitialI::GetMBMarshaledResult
InitialI::getMB(const Ice::Current& current)
diff --git a/cpp/test/Ice/objects/TestI.h b/cpp/test/Ice/objects/TestI.h
index a7243ed95f6..1a467fc0f33 100644
--- a/cpp/test/Ice/objects/TestI.h
+++ b/cpp/test/Ice/objects/TestI.h
@@ -94,6 +94,9 @@ public:
virtual Test::EPtr getE(const Ice::Current&);
virtual Test::FPtr getF(const Ice::Current&);
+ virtual void setRecursive(ICE_IN(Test::RecursivePtr), const Ice::Current&);
+ virtual bool supportsClassGraphDepthMax(const Ice::Current&);
+
#ifdef ICE_CPP11_MAPPING
virtual GetMBMarshaledResult getMB(const Ice::Current&);
virtual void getAMDMBAsync(std::function<void(const GetAMDMBMarshaledResult&)>,
diff --git a/csharp/src/Ice/InputStream.cs b/csharp/src/Ice/InputStream.cs
index c942e132a82..0dd8c98b624 100644
--- a/csharp/src/Ice/InputStream.cs
+++ b/csharp/src/Ice/InputStream.cs
@@ -245,7 +245,7 @@ namespace Ice
_instance = instance;
_traceSlicing = _instance.traceLevels().slicing > 0;
-
+ _classGraphDepthMax = _instance.classGraphDepthMax();
_valueFactoryManager = _instance.initializationData().valueFactoryManager;
_logger = _instance.initializationData().logger;
_classResolver = _instance.resolveClass;
@@ -258,6 +258,7 @@ namespace Ice
_encapsStack = null;
_encapsCache = null;
_traceSlicing = false;
+ _classGraphDepthMax = 0x7fffffff;
_closure = null;
_sliceValues = true;
_startSeq = -1;
@@ -360,6 +361,22 @@ namespace Ice
}
/// <summary>
+ /// Set the maximum depth allowed for graph of Slice class instances.
+ /// </summary>
+ /// <param name="classGraphDepthMax">The maximum depth.</param>
+ public void setClassGraphDepthMax(int classGraphDepthMax)
+ {
+ if(classGraphDepthMax < 1)
+ {
+ _classGraphDepthMax = 0x7fffffff;
+ }
+ else
+ {
+ _classGraphDepthMax = classGraphDepthMax;
+ }
+ }
+
+ /// <summary>
/// Retrieves the closure object associated with this stream.
/// </summary>
/// <returns>The closure object.</returns>
@@ -413,6 +430,10 @@ namespace Ice
other._sliceValues = _sliceValues;
_sliceValues = tmpSliceValues;
+ int tmpClassGraphDepthMax = other._classGraphDepthMax;
+ other._classGraphDepthMax = _classGraphDepthMax;
+ _classGraphDepthMax = tmpClassGraphDepthMax;
+
//
// Swap is never called for InputStreams that have encapsulations being read. However,
// encapsulations might still be set in case un-marshalling failed. We just
@@ -2733,12 +2754,27 @@ namespace Ice
abstract private class EncapsDecoder
{
- internal EncapsDecoder(InputStream stream, Encaps encaps, bool sliceValues, ValueFactoryManager f,
+ protected struct PatchEntry
+ {
+ public PatchEntry(System.Action<Value> cb, int classGraphDepth)
+ {
+ this.cb = cb;
+ this.classGraphDepth = classGraphDepth;
+ }
+
+ public System.Action<Value> cb;
+ public int classGraphDepth;
+ };
+
+ internal EncapsDecoder(InputStream stream, Encaps encaps, bool sliceValues,
+ int classGraphDepthMax, ValueFactoryManager f,
System.Func<string, Type> cr)
{
_stream = stream;
_encaps = encaps;
_sliceValues = sliceValues;
+ _classGraphDepthMax = classGraphDepthMax;
+ _classGraphDepth = 0;
_valueFactoryManager = f;
_classResolver = cr;
_typeIdIndex = 0;
@@ -2889,7 +2925,7 @@ namespace Ice
if(_patchMap == null)
{
- _patchMap = new Dictionary<int, LinkedList<System.Action<Value>>>();
+ _patchMap = new Dictionary<int, LinkedList<PatchEntry>>();
}
//
@@ -2897,21 +2933,21 @@ namespace Ice
// the callback will be called when the instance is
// unmarshaled.
//
- LinkedList<System.Action<Value>> l;
+ LinkedList<PatchEntry> l;
if(!_patchMap.TryGetValue(index, out l))
{
//
// We have no outstanding instances to be patched for this
// index, so make a new entry in the patch map.
//
- l = new LinkedList<System.Action<Value>>();
+ l = new LinkedList<PatchEntry>();
_patchMap.Add(index, l);
}
//
// Append a patch entry for this instance.
//
- l.AddLast(cb);
+ l.AddLast(new PatchEntry(cb, _classGraphDepth));
}
protected void unmarshal(int index, Value v)
@@ -2932,7 +2968,7 @@ namespace Ice
//
// Patch all instances now that the instance is unmarshaled.
//
- LinkedList<System.Action<Value>> l;
+ LinkedList<PatchEntry> l;
if(_patchMap.TryGetValue(index, out l))
{
Debug.Assert(l.Count > 0);
@@ -2940,9 +2976,9 @@ namespace Ice
//
// Patch all pointers that refer to the instance.
//
- foreach(System.Action<Value> cb in l)
+ foreach(PatchEntry entry in l)
{
- cb(v);
+ entry.cb(v);
}
//
@@ -3001,13 +3037,15 @@ namespace Ice
protected readonly InputStream _stream;
protected readonly Encaps _encaps;
protected readonly bool _sliceValues;
+ protected readonly int _classGraphDepthMax;
+ protected int _classGraphDepth;
protected ValueFactoryManager _valueFactoryManager;
protected System.Func<string, Type> _classResolver;
//
// Encapsulation attributes for object unmarshaling.
//
- protected Dictionary<int, LinkedList<System.Action<Value>> > _patchMap;
+ protected Dictionary<int, LinkedList<PatchEntry>> _patchMap;
private Dictionary<int, Value> _unmarshaledMap;
private Dictionary<int, string> _typeIdMap;
private int _typeIdIndex;
@@ -3017,9 +3055,9 @@ namespace Ice
private sealed class EncapsDecoder10 : EncapsDecoder
{
- internal EncapsDecoder10(InputStream stream, Encaps encaps, bool sliceValues, ValueFactoryManager f,
- System.Func<string, Type> cr)
- : base(stream, encaps, sliceValues, f, cr)
+ internal EncapsDecoder10(InputStream stream, Encaps encaps, bool sliceValues, int classGraphDepthMax,
+ ValueFactoryManager f, System.Func<string, Type> cr)
+ : base(stream, encaps, sliceValues, classGraphDepthMax, f, cr)
{
_sliceType = SliceType.NoSlice;
}
@@ -3297,6 +3335,30 @@ namespace Ice
}
//
+ // Compute the biggest class graph depth of this object. To compute this,
+ // we get the class graph depth of each ancestor from the patch map and
+ // keep the biggest one.
+ //
+ _classGraphDepth = 0;
+ LinkedList<PatchEntry> l;
+ if(_patchMap != null && _patchMap.TryGetValue(index, out l))
+ {
+ Debug.Assert(l.Count > 0);
+ foreach(PatchEntry entry in l)
+ {
+ if(entry.classGraphDepth > _classGraphDepth)
+ {
+ _classGraphDepth = entry.classGraphDepth;
+ }
+ }
+ }
+
+ if(++_classGraphDepth > _classGraphDepthMax)
+ {
+ throw new MarshalException("maximum class graph depth reached");
+ }
+
+ //
// Unmarshal the instance and add it to the map of unmarshaled instances.
//
unmarshal(index, v);
@@ -3313,9 +3375,9 @@ namespace Ice
private sealed class EncapsDecoder11 : EncapsDecoder
{
- internal EncapsDecoder11(InputStream stream, Encaps encaps, bool sliceValues, ValueFactoryManager f,
- System.Func<string, Type> cr, System.Func<int, string> r)
- : base(stream, encaps, sliceValues, f, cr)
+ internal EncapsDecoder11(InputStream stream, Encaps encaps, bool sliceValues, int classGraphDepthMax,
+ ValueFactoryManager f, System.Func<string, Type> cr, System.Func<int, string> r)
+ : base(stream, encaps, sliceValues, classGraphDepthMax, f, cr)
{
_compactIdResolver = r;
_current = null;
@@ -3841,11 +3903,18 @@ namespace Ice
startSlice(); // Read next Slice header for next iteration.
}
+ if(++_classGraphDepth > _classGraphDepthMax)
+ {
+ throw new MarshalException("maximum class graph depth reached");
+ }
+
//
// Unmarshal the instance.
//
unmarshal(index, v);
+ --_classGraphDepth;
+
if(_current == null && _patchMap != null && _patchMap.Count > 0)
{
//
@@ -4008,19 +4077,20 @@ namespace Ice
{
if(_encapsStack.encoding_1_0)
{
- _encapsStack.decoder = new EncapsDecoder10(this, _encapsStack, _sliceValues, _valueFactoryManager,
- _classResolver);
+ _encapsStack.decoder = new EncapsDecoder10(this, _encapsStack, _sliceValues, _classGraphDepthMax,
+ _valueFactoryManager, _classResolver);
}
else
{
- _encapsStack.decoder = new EncapsDecoder11(this, _encapsStack, _sliceValues, _valueFactoryManager,
- _classResolver, _compactIdResolver);
+ _encapsStack.decoder = new EncapsDecoder11(this, _encapsStack, _sliceValues, _classGraphDepthMax,
+ _valueFactoryManager, _classResolver, _compactIdResolver);
}
}
}
private bool _sliceValues;
private bool _traceSlicing;
+ private int _classGraphDepthMax;
private int _startSeq;
private int _minSeqSize;
diff --git a/csharp/src/Ice/Instance.cs b/csharp/src/Ice/Instance.cs
index a4a1c3e7c1d..423b24b96d2 100644
--- a/csharp/src/Ice/Instance.cs
+++ b/csharp/src/Ice/Instance.cs
@@ -336,6 +336,12 @@ namespace IceInternal
return _batchAutoFlushSize;
}
+ public int classGraphDepthMax()
+ {
+ // No mutex lock, immutable.
+ return _classGraphDepthMax;
+ }
+
public Ice.ToStringMode
toStringMode()
{
@@ -857,6 +863,19 @@ namespace IceInternal
}
}
+ {
+ const int defaultValue = 100;
+ var num = _initData.properties.getPropertyAsIntWithDefault("Ice.ClassGraphDepthMax", defaultValue);
+ if(num < 1 || num > 0x7fffffff)
+ {
+ _classGraphDepthMax = 0x7fffffff;
+ }
+ else
+ {
+ _classGraphDepthMax = num;
+ }
+ }
+
string toStringModeStr = _initData.properties.getPropertyWithDefault("Ice.ToStringMode", "Unicode");
if(toStringModeStr == "Unicode")
{
@@ -1560,6 +1579,7 @@ namespace IceInternal
private DefaultsAndOverrides _defaultsAndOverrides; // Immutable, not reset by destroy().
private int _messageSizeMax; // Immutable, not reset by destroy().
private int _batchAutoFlushSize; // Immutable, not reset by destroy().
+ private int _classGraphDepthMax; // Immutable, not reset by destroy().
private Ice.ToStringMode _toStringMode; // Immutable, not reset by destroy().
private int _cacheMessageBuffers; // Immutable, not reset by destroy().
private ACMConfig _clientACM; // Immutable, not reset by destroy().
diff --git a/csharp/src/Ice/PropertyNames.cs b/csharp/src/Ice/PropertyNames.cs
index b5fa1fec421..3d1359ac6de 100644
--- a/csharp/src/Ice/PropertyNames.cs
+++ b/csharp/src/Ice/PropertyNames.cs
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Mar 23 15:24:16 2017
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -79,6 +79,7 @@ namespace IceInternal
new Property(@"^Ice\.BatchAutoFlush$", true, null),
new Property(@"^Ice\.BatchAutoFlushSize$", false, null),
new Property(@"^Ice\.ChangeUser$", false, null),
+ new Property(@"^Ice\.ClassGraphDepthMax$", false, null),
new Property(@"^Ice\.ClientAccessPolicyProtocol$", false, null),
new Property(@"^Ice\.Compression\.Level$", false, null),
new Property(@"^Ice\.CollectObjects$", false, null),
diff --git a/csharp/test/Ice/exceptions/AllTests.cs b/csharp/test/Ice/exceptions/AllTests.cs
index b0e7b109849..2627821fb7c 100644
--- a/csharp/test/Ice/exceptions/AllTests.cs
+++ b/csharp/test/Ice/exceptions/AllTests.cs
@@ -426,29 +426,40 @@ public class AllTests : TestCommon.AllTests
catch(Ice.ConnectionLostException)
{
}
+ catch(Ice.UnknownLocalException)
+ {
+ // Expected with JS bidir server
+ }
catch(Exception)
{
test(false);
}
- ThrowerPrx thrower2 = ThrowerPrxHelper.uncheckedCast(
- communicator.stringToProxy("thrower:" + app.getTestEndpoint(1)));
- try
- {
- thrower2.throwMemoryLimitException(new byte[2 * 1024 * 1024]); // 2MB (no limits)
- }
- catch(Ice.MemoryLimitException)
- {
- }
- ThrowerPrx thrower3 = ThrowerPrxHelper.uncheckedCast(
- communicator.stringToProxy("thrower:" + app.getTestEndpoint(2)));
try
{
- thrower3.throwMemoryLimitException(new byte[1024]); // 1KB limit
- test(false);
+ ThrowerPrx thrower2 = ThrowerPrxHelper.uncheckedCast(
+ communicator.stringToProxy("thrower:" + app.getTestEndpoint(1)));
+ try
+ {
+ thrower2.throwMemoryLimitException(new byte[2 * 1024 * 1024]); // 2MB (no limits)
+ }
+ catch(Ice.MemoryLimitException)
+ {
+ }
+ ThrowerPrx thrower3 = ThrowerPrxHelper.uncheckedCast(
+ communicator.stringToProxy("thrower:" + app.getTestEndpoint(2)));
+ try
+ {
+ thrower3.throwMemoryLimitException(new byte[1024]); // 1KB limit
+ test(false);
+ }
+ catch(Ice.ConnectionLostException)
+ {
+ }
}
- catch(Ice.ConnectionLostException)
+ catch(Ice.ConnectionRefusedException)
{
+ // Expected with JS bidir server
}
WriteLine("ok");
diff --git a/csharp/test/Ice/objects/AllTests.cs b/csharp/test/Ice/objects/AllTests.cs
index d050088c288..e61141f5daa 100644
--- a/csharp/test/Ice/objects/AllTests.cs
+++ b/csharp/test/Ice/objects/AllTests.cs
@@ -276,6 +276,38 @@ public class AllTests : TestCommon.AllTests
}
WriteLine("ok");
+ Write("testing recursive type... ");
+ Flush();
+ Recursive top = new Recursive();
+ Recursive p = top;
+ int depth = 0;
+ try
+ {
+ for(; depth <= 1000; ++depth)
+ {
+ p.v = new 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(Ice.UnknownLocalException)
+ {
+ // Expected marshal exception from the server (max class graph depth reached)
+ }
+ catch(Ice.UnknownException)
+ {
+ // Expected stack overflow from the server (Java only)
+ }
+ initial.setRecursive(new Recursive());
+ WriteLine("ok");
+
Write("testing compact ID...");
Flush();
try
diff --git a/csharp/test/Ice/objects/Collocated.cs b/csharp/test/Ice/objects/Collocated.cs
index 637b8a01b77..7a034a4eb44 100644
--- a/csharp/test/Ice/objects/Collocated.cs
+++ b/csharp/test/Ice/objects/Collocated.cs
@@ -33,6 +33,13 @@ public class Collocated : TestCommon.Application
return 0;
}
+ protected override Ice.InitializationData getInitData(ref string[] args)
+ {
+ Ice.InitializationData initData = base.getInitData(ref args);
+ initData.properties.setProperty("Ice.Warn.Dispatch", "0");
+ return initData;
+ }
+
public static int Main(string[] args)
{
Collocated app = new Collocated();
diff --git a/csharp/test/Ice/objects/InitialI.cs b/csharp/test/Ice/objects/InitialI.cs
index 686beac8e0f..05f133c40c6 100644
--- a/csharp/test/Ice/objects/InitialI.cs
+++ b/csharp/test/Ice/objects/InitialI.cs
@@ -44,7 +44,7 @@ public sealed class InitialI : InitialDisp_
c = _c;
d = _d;
}
-
+
public override B getB1(Ice.Current current)
{
return _b1;
@@ -89,7 +89,16 @@ public sealed class InitialI : InitialDisp_
{
return new HI();
}
-
+
+ public override void setRecursive(Recursive r, Ice.Current current)
+ {
+ }
+
+ public override bool supportsClassGraphDepthMax(Ice.Current current)
+ {
+ return true;
+ }
+
public override D1 getD1(D1 d1, Ice.Current current)
{
return d1;
diff --git a/csharp/test/Ice/objects/Server.cs b/csharp/test/Ice/objects/Server.cs
index 26157bc146a..ab1f3c9cce2 100644
--- a/csharp/test/Ice/objects/Server.cs
+++ b/csharp/test/Ice/objects/Server.cs
@@ -54,6 +54,13 @@ public class Server : TestCommon.Application
return 0;
}
+ protected override Ice.InitializationData getInitData(ref string[] args)
+ {
+ Ice.InitializationData initData = base.getInitData(ref args);
+ initData.properties.setProperty("Ice.Warn.Dispatch", "0");
+ return initData;
+ }
+
public static int Main(string[] args)
{
Server app = new Server();
diff --git a/csharp/test/Ice/objects/Test.ice b/csharp/test/Ice/objects/Test.ice
index d985d0676ed..e33229ad4e9 100644
--- a/csharp/test/Ice/objects/Test.ice
+++ b/csharp/test/Ice/objects/Test.ice
@@ -162,6 +162,11 @@ exception EDerived extends EBase
A1 a4;
};
+class Recursive
+{
+ Recursive v;
+};
+
interface Initial
{
void shutdown();
@@ -172,6 +177,9 @@ interface Initial
E getE();
F getF();
+ void setRecursive(Recursive p);
+ bool supportsClassGraphDepthMax();
+
["marshaled-result"] B getMB();
["amd", "marshaled-result"] B getAMDMB();
diff --git a/java-compat/src/Ice/src/main/java/Ice/ConnectionI.java b/java-compat/src/Ice/src/main/java/Ice/ConnectionI.java
index 165b6578b0e..08336df7d02 100644
--- a/java-compat/src/Ice/src/main/java/Ice/ConnectionI.java
+++ b/java-compat/src/Ice/src/main/java/Ice/ConnectionI.java
@@ -2823,7 +2823,9 @@ public final class ConnectionI extends IceInternal.EventHandler
//
// Suppress AssertionError and OutOfMemoryError, rethrow everything else.
//
- if(!(t instanceof java.lang.AssertionError || t instanceof java.lang.OutOfMemoryError))
+ if(!(t instanceof java.lang.AssertionError ||
+ t instanceof java.lang.OutOfMemoryError ||
+ t instanceof java.lang.StackOverflowError))
{
throw (java.lang.Error)t;
}
@@ -2848,7 +2850,9 @@ public final class ConnectionI extends IceInternal.EventHandler
//
// Suppress AssertionError and OutOfMemoryError, rethrow everything else.
//
- if(!(ex instanceof java.lang.AssertionError || ex instanceof java.lang.OutOfMemoryError))
+ if(!(ex instanceof java.lang.AssertionError ||
+ ex instanceof java.lang.OutOfMemoryError ||
+ ex instanceof java.lang.StackOverflowError))
{
throw ex;
}
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/CollocatedRequestHandler.java b/java-compat/src/Ice/src/main/java/IceInternal/CollocatedRequestHandler.java
index ac11851836e..94402c7389e 100644
--- a/java-compat/src/Ice/src/main/java/IceInternal/CollocatedRequestHandler.java
+++ b/java-compat/src/Ice/src/main/java/IceInternal/CollocatedRequestHandler.java
@@ -340,7 +340,9 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
//
// Suppress AssertionError and OutOfMemoryError, rethrow everything else.
//
- if(!(t instanceof java.lang.AssertionError || t instanceof java.lang.OutOfMemoryError))
+ if(!(t instanceof java.lang.AssertionError ||
+ t instanceof java.lang.OutOfMemoryError ||
+ t instanceof java.lang.StackOverflowError))
{
throw (java.lang.Error)t;
}
@@ -365,13 +367,17 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
//
// Suppress AssertionError and OutOfMemoryError, rethrow everything else.
//
- if(!(ex instanceof java.lang.AssertionError || ex instanceof java.lang.OutOfMemoryError))
+ if(!(ex instanceof java.lang.AssertionError ||
+ ex instanceof java.lang.OutOfMemoryError ||
+ ex instanceof java.lang.StackOverflowError))
{
throw ex;
}
}
-
- _adapter.decDirectCount();
+ finally
+ {
+ _adapter.decDirectCount();
+ }
}
private void
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java b/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java
index 1b2db0f1030..dc971363790 100644
--- a/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java
+++ b/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Mar 23 15:24:16 2017
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -79,6 +79,7 @@ public final class PropertyNames
new Property("Ice\\.BatchAutoFlush", true, null),
new Property("Ice\\.BatchAutoFlushSize", false, null),
new Property("Ice\\.ChangeUser", false, null),
+ new Property("Ice\\.ClassGraphDepthMax", false, null),
new Property("Ice\\.ClientAccessPolicyProtocol", false, null),
new Property("Ice\\.Compression\\.Level", false, null),
new Property("Ice\\.CollectObjects", false, null),
diff --git a/java-compat/test/src/main/java/test/Ice/exceptions/AllTests.java b/java-compat/test/src/main/java/test/Ice/exceptions/AllTests.java
index d00bd7bef7c..bb5e82db6f4 100644
--- a/java-compat/test/src/main/java/test/Ice/exceptions/AllTests.java
+++ b/java-compat/test/src/main/java/test/Ice/exceptions/AllTests.java
@@ -1131,6 +1131,10 @@ public class AllTests
catch(Ice.ConnectionLostException ex)
{
}
+ catch(Ice.UnknownLocalException ex)
+ {
+ // Expected with JS bidir server
+ }
catch(Ice.SocketException ex)
{
// This can be raised if the connection is closed during the client's call to write().
@@ -1141,24 +1145,31 @@ public class AllTests
test(false);
}
- ThrowerPrx thrower2 = ThrowerPrxHelper.uncheckedCast(
- communicator.stringToProxy("thrower:" + app.getTestEndpoint(1)));
try
{
- thrower2.throwMemoryLimitException(new byte[2 * 1024 * 1024]); // 2MB (no limits)
- }
- catch(Ice.MemoryLimitException ex)
- {
- }
- ThrowerPrx thrower3 = ThrowerPrxHelper.uncheckedCast(
- communicator.stringToProxy("thrower:" + app.getTestEndpoint(2)));
- try
- {
- thrower3.throwMemoryLimitException(new byte[1024]); // 1KB limit
- test(false);
+ ThrowerPrx thrower2 = ThrowerPrxHelper.uncheckedCast(
+ communicator.stringToProxy("thrower:" + app.getTestEndpoint(1)));
+ try
+ {
+ thrower2.throwMemoryLimitException(new byte[2 * 1024 * 1024]); // 2MB (no limits)
+ }
+ catch(Ice.MemoryLimitException ex)
+ {
+ }
+ ThrowerPrx thrower3 = ThrowerPrxHelper.uncheckedCast(
+ communicator.stringToProxy("thrower:" + app.getTestEndpoint(2)));
+ try
+ {
+ thrower3.throwMemoryLimitException(new byte[1024]); // 1KB limit
+ test(false);
+ }
+ catch(Ice.ConnectionLostException ex)
+ {
+ }
}
- catch(Ice.ConnectionLostException ex)
+ catch(Ice.ConnectionRefusedException ex)
{
+ // Expected with JS bidir server
}
out.println("ok");
diff --git a/java-compat/test/src/main/java/test/Ice/objects/AllTests.java b/java-compat/test/src/main/java/test/Ice/objects/AllTests.java
index f71bf5010a4..0e4588c6e94 100644
--- a/java-compat/test/src/main/java/test/Ice/objects/AllTests.java
+++ b/java-compat/test/src/main/java/test/Ice/objects/AllTests.java
@@ -31,6 +31,7 @@ import test.Ice.objects.Test.BaseSeqHolder;
import test.Ice.objects.Test.InitialPrx;
import test.Ice.objects.Test.InitialPrxHelper;
import test.Ice.objects.Test.J;
+import test.Ice.objects.Test.Recursive;
import test.Ice.objects.Test.UnexpectedObjectExceptionTestPrx;
import test.Ice.objects.Test.UnexpectedObjectExceptionTestPrxHelper;
@@ -251,6 +252,42 @@ public class AllTests
}
out.println("ok");
+ out.print("testing recursive type... ");
+ out.flush();
+ Recursive top = new Recursive();
+ Recursive p = top;
+ int depth = 0;
+ try
+ {
+ for(; depth <= 20000; ++depth)
+ {
+ p.v = new 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(Ice.UnknownLocalException ex)
+ {
+ // Expected marshal exception from the server (max class graph depth reached)
+ }
+ catch(Ice.UnknownException ex)
+ {
+ // Expected stack overflow from the server (Java only)
+ }
+ catch(java.lang.StackOverflowError ex)
+ {
+ // Stack overflow while writing instances
+ }
+ initial.setRecursive(new Recursive());
+ out.println("ok");
+
out.print("testing compact ID...");
out.flush();
try
diff --git a/java-compat/test/src/main/java/test/Ice/objects/Collocated.java b/java-compat/test/src/main/java/test/Ice/objects/Collocated.java
index f83e0167f26..9a66174ba08 100644
--- a/java-compat/test/src/main/java/test/Ice/objects/Collocated.java
+++ b/java-compat/test/src/main/java/test/Ice/objects/Collocated.java
@@ -105,6 +105,7 @@ public class Collocated extends test.Util.Application
{
Ice.InitializationData initData = super.getInitData(argsH);
initData.properties.setProperty("Ice.Package.Test", "test.Ice.objects");
+ initData.properties.setProperty("Ice.Warn.Dispatch", "0");
return initData;
}
diff --git a/java-compat/test/src/main/java/test/Ice/objects/InitialI.java b/java-compat/test/src/main/java/test/Ice/objects/InitialI.java
index ddb1957d013..24ae8c3e697 100644
--- a/java-compat/test/src/main/java/test/Ice/objects/InitialI.java
+++ b/java-compat/test/src/main/java/test/Ice/objects/InitialI.java
@@ -24,6 +24,7 @@ import test.Ice.objects.Test.D1;
import test.Ice.objects.Test.EDerived;
import test.Ice.objects.Test.Base;
import test.Ice.objects.Test.BaseSeqHolder;
+import test.Ice.objects.Test.Recursive;
import test.Ice.objects.Test.Initial;
import test.Ice.objects.Test.Compact;
import test.Ice.objects.Test.CompactExt;
@@ -126,6 +127,18 @@ public final class InitialI extends Initial
}
@Override
+ public void
+ setRecursive(Recursive r, Ice.Current current)
+ {
+ }
+
+ @Override
+ public boolean supportsClassGraphDepthMax(Ice.Current current)
+ {
+ return false;
+ }
+
+ @Override
public B
getMB(Ice.Current current)
{
@@ -159,14 +172,14 @@ public final class InitialI extends Initial
{
return new HI();
}
-
+
@Override
public D1
getD1(D1 d1, Ice.Current current)
{
return d1;
}
-
+
@Override
public void
throwEDerived(Ice.Current current) throws EDerived
diff --git a/java-compat/test/src/main/java/test/Ice/objects/Server.java b/java-compat/test/src/main/java/test/Ice/objects/Server.java
index 560befcbe0d..6d36d75e5f7 100644
--- a/java-compat/test/src/main/java/test/Ice/objects/Server.java
+++ b/java-compat/test/src/main/java/test/Ice/objects/Server.java
@@ -58,6 +58,7 @@ public class Server extends test.Util.Application
{
Ice.InitializationData initData = super.getInitData(argsH);
initData.properties.setProperty("Ice.Package.Test", "test.Ice.objects");
+ initData.properties.setProperty("Ice.Warn.Dispatch", "0");
initData.properties.setProperty("TestAdapter.Endpoints", getTestEndpoint(initData.properties, 0));
return initData;
}
diff --git a/java-compat/test/src/main/java/test/Ice/objects/Test.ice b/java-compat/test/src/main/java/test/Ice/objects/Test.ice
index 629cc8c10b8..07cfcd797d4 100644
--- a/java-compat/test/src/main/java/test/Ice/objects/Test.ice
+++ b/java-compat/test/src/main/java/test/Ice/objects/Test.ice
@@ -163,6 +163,11 @@ exception EDerived extends EBase
A1 a4;
};
+class Recursive
+{
+ Recursive v;
+};
+
class Initial
{
void shutdown();
@@ -173,6 +178,9 @@ class Initial
E getE();
F getF();
+ void setRecursive(Recursive p);
+ bool supportsClassGraphDepthMax();
+
["marshaled-result"] B getMB();
["amd", "marshaled-result"] B getAMDMB();
diff --git a/java/src/Ice/src/main/java/com/zeroc/Ice/ConnectionI.java b/java/src/Ice/src/main/java/com/zeroc/Ice/ConnectionI.java
index 296f0af7969..c1c33414122 100644
--- a/java/src/Ice/src/main/java/com/zeroc/Ice/ConnectionI.java
+++ b/java/src/Ice/src/main/java/com/zeroc/Ice/ConnectionI.java
@@ -2727,7 +2727,9 @@ public final class ConnectionI extends com.zeroc.IceInternal.EventHandler
//
// Suppress AssertionError and OutOfMemoryError, rethrow everything else.
//
- if(!(t instanceof java.lang.AssertionError || t instanceof java.lang.OutOfMemoryError))
+ if(!(t instanceof java.lang.AssertionError ||
+ t instanceof java.lang.OutOfMemoryError ||
+ t instanceof java.lang.StackOverflowError))
{
throw (java.lang.Error)t;
}
@@ -2752,7 +2754,9 @@ public final class ConnectionI extends com.zeroc.IceInternal.EventHandler
//
// Suppress AssertionError and OutOfMemoryError, rethrow everything else.
//
- if(!(ex instanceof java.lang.AssertionError || ex instanceof java.lang.OutOfMemoryError))
+ if(!(ex instanceof java.lang.AssertionError ||
+ ex instanceof java.lang.OutOfMemoryError ||
+ ex instanceof java.lang.StackOverflowError))
{
throw ex;
}
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/CollocatedRequestHandler.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/CollocatedRequestHandler.java
index 7512638a7c0..a9a6ee0f919 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/CollocatedRequestHandler.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/CollocatedRequestHandler.java
@@ -341,7 +341,9 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
//
// Suppress AssertionError and OutOfMemoryError, rethrow everything else.
//
- if(!(t instanceof java.lang.AssertionError || t instanceof java.lang.OutOfMemoryError))
+ if(!(t instanceof java.lang.AssertionError ||
+ t instanceof java.lang.OutOfMemoryError ||
+ t instanceof java.lang.StackOverflowError))
{
throw (java.lang.Error)t;
}
@@ -366,13 +368,17 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
//
// Suppress AssertionError and OutOfMemoryError, rethrow everything else.
//
- if(!(ex instanceof java.lang.AssertionError || ex instanceof java.lang.OutOfMemoryError))
+ if(!(ex instanceof java.lang.AssertionError ||
+ ex instanceof java.lang.OutOfMemoryError ||
+ ex instanceof java.lang.StackOverflowError))
{
throw ex;
}
}
-
- _adapter.decDirectCount();
+ finally
+ {
+ _adapter.decDirectCount();
+ }
}
private void
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java
index eb3319e9b46..77db7c18407 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Mar 23 15:24:16 2017
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -79,6 +79,7 @@ public final class PropertyNames
new Property("Ice\\.BatchAutoFlush", true, null),
new Property("Ice\\.BatchAutoFlushSize", false, null),
new Property("Ice\\.ChangeUser", false, null),
+ new Property("Ice\\.ClassGraphDepthMax", false, null),
new Property("Ice\\.ClientAccessPolicyProtocol", false, null),
new Property("Ice\\.Compression\\.Level", false, null),
new Property("Ice\\.CollectObjects", false, null),
diff --git a/java/test/src/main/java/test/Ice/exceptions/AllTests.java b/java/test/src/main/java/test/Ice/exceptions/AllTests.java
index 1cce083ca40..acfb3dc000b 100644
--- a/java/test/src/main/java/test/Ice/exceptions/AllTests.java
+++ b/java/test/src/main/java/test/Ice/exceptions/AllTests.java
@@ -438,6 +438,10 @@ public class AllTests
catch(com.zeroc.Ice.ConnectionLostException ex)
{
}
+ catch(com.zeroc.Ice.UnknownLocalException ex)
+ {
+ // Expected with JS bidir server
+ }
catch(com.zeroc.Ice.SocketException ex)
{
// This can be raised if the connection is closed during the client's call to write().
@@ -448,24 +452,31 @@ public class AllTests
test(false);
}
- ThrowerPrx thrower2 = ThrowerPrx.uncheckedCast(communicator.stringToProxy("thrower:" +
- app.getTestEndpoint(1)));
- try
- {
- thrower2.throwMemoryLimitException(new byte[2 * 1024 * 1024]); // 2MB (no limits)
- }
- catch(com.zeroc.Ice.MemoryLimitException ex)
- {
- }
- ThrowerPrx thrower3 = ThrowerPrx.uncheckedCast(communicator.stringToProxy("thrower:" +
- app.getTestEndpoint(2)));
try
{
- thrower3.throwMemoryLimitException(new byte[1024]); // 1KB limit
- test(false);
- }
- catch(com.zeroc.Ice.ConnectionLostException ex)
- {
+ ThrowerPrx thrower2 = ThrowerPrx.uncheckedCast(communicator.stringToProxy("thrower:" +
+ app.getTestEndpoint(1)));
+ try
+ {
+ thrower2.throwMemoryLimitException(new byte[2 * 1024 * 1024]); // 2MB (no limits)
+ }
+ catch(com.zeroc.Ice.MemoryLimitException ex)
+ {
+ }
+ ThrowerPrx thrower3 = ThrowerPrx.uncheckedCast(communicator.stringToProxy("thrower:" +
+ app.getTestEndpoint(2)));
+ try
+ {
+ thrower3.throwMemoryLimitException(new byte[1024]); // 1KB limit
+ test(false);
+ }
+ catch(com.zeroc.Ice.ConnectionLostException ex)
+ {
+ }
+ }
+ catch(com.zeroc.Ice.ConnectionRefusedException ex)
+ {
+ // Expected with JS bidir server
}
out.println("ok");
diff --git a/java/test/src/main/java/test/Ice/objects/AllTests.java b/java/test/src/main/java/test/Ice/objects/AllTests.java
index c7b65fe7164..31dc2f69cea 100644
--- a/java/test/src/main/java/test/Ice/objects/AllTests.java
+++ b/java/test/src/main/java/test/Ice/objects/AllTests.java
@@ -27,6 +27,7 @@ import test.Ice.objects.Test.S;
import test.Ice.objects.Test.Initial;
import test.Ice.objects.Test.InitialPrx;
import test.Ice.objects.Test.J;
+import test.Ice.objects.Test.Recursive;
import test.Ice.objects.Test.UnexpectedObjectExceptionTestPrx;
public class AllTests
@@ -241,6 +242,42 @@ public class AllTests
}
out.println("ok");
+ out.print("testing recursive type... ");
+ out.flush();
+ Recursive top = new Recursive();
+ Recursive p = top;
+ int depth = 0;
+ try
+ {
+ for(; depth <= 20000; ++depth)
+ {
+ p.v = new 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(com.zeroc.Ice.UnknownLocalException ex)
+ {
+ // Expected marshal exception from the server (max class graph depth reached)
+ }
+ catch(com.zeroc.Ice.UnknownException ex)
+ {
+ // Expected stack overflow from the server (Java only)
+ }
+ catch(java.lang.StackOverflowError ex)
+ {
+ // Stack overflow while writing instances
+ }
+ initial.setRecursive(new Recursive());
+ out.println("ok");
+
out.print("testing compact ID...");
out.flush();
try
diff --git a/java/test/src/main/java/test/Ice/objects/Collocated.java b/java/test/src/main/java/test/Ice/objects/Collocated.java
index 44ca644bf4d..ffb62ec24e4 100644
--- a/java/test/src/main/java/test/Ice/objects/Collocated.java
+++ b/java/test/src/main/java/test/Ice/objects/Collocated.java
@@ -108,6 +108,7 @@ public class Collocated extends test.Util.Application
{
com.zeroc.Ice.InitializationData initData = super.getInitData(args, rArgs);
initData.properties.setProperty("Ice.Package.Test", "test.Ice.objects");
+ initData.properties.setProperty("Ice.Warn.Dispatch", "0");
return initData;
}
diff --git a/java/test/src/main/java/test/Ice/objects/InitialI.java b/java/test/src/main/java/test/Ice/objects/InitialI.java
index 8b0876bc4c6..fe879cf5276 100644
--- a/java/test/src/main/java/test/Ice/objects/InitialI.java
+++ b/java/test/src/main/java/test/Ice/objects/InitialI.java
@@ -106,6 +106,17 @@ public final class InitialI implements Initial
}
@Override
+ public void setRecursive(Recursive r, com.zeroc.Ice.Current current)
+ {
+ }
+
+ @Override
+ public boolean supportsClassGraphDepthMax(com.zeroc.Ice.Current current)
+ {
+ return false;
+ }
+
+ @Override
public com.zeroc.Ice.Value getI(com.zeroc.Ice.Current current)
{
return new II();
diff --git a/java/test/src/main/java/test/Ice/objects/Server.java b/java/test/src/main/java/test/Ice/objects/Server.java
index f6989af992b..d8e051a0592 100644
--- a/java/test/src/main/java/test/Ice/objects/Server.java
+++ b/java/test/src/main/java/test/Ice/objects/Server.java
@@ -58,6 +58,7 @@ public class Server extends test.Util.Application
{
com.zeroc.Ice.InitializationData initData = super.getInitData(args, rArgs);
initData.properties.setProperty("Ice.Package.Test", "test.Ice.objects");
+ initData.properties.setProperty("Ice.Warn.Dispatch", "0");
initData.properties.setProperty("TestAdapter.Endpoints", getTestEndpoint(initData.properties, 0));
return initData;
}
diff --git a/java/test/src/main/java/test/Ice/objects/Test.ice b/java/test/src/main/java/test/Ice/objects/Test.ice
index c9b3b592b26..173d3e50d97 100644
--- a/java/test/src/main/java/test/Ice/objects/Test.ice
+++ b/java/test/src/main/java/test/Ice/objects/Test.ice
@@ -163,6 +163,11 @@ exception EDerived extends EBase
A1 a4;
};
+class Recursive
+{
+ Recursive v;
+};
+
interface Initial
{
void shutdown();
@@ -173,6 +178,9 @@ interface Initial
E getE();
F getF();
+ void setRecursive(Recursive p);
+ bool supportsClassGraphDepthMax();
+
["marshaled-result"] B getMB();
["amd", "marshaled-result"] B getAMDMB();
diff --git a/js/bin/HttpServer.js b/js/bin/HttpServer.js
index 53c42327368..5390d306be3 100644
--- a/js/bin/HttpServer.js
+++ b/js/bin/HttpServer.js
@@ -26,13 +26,12 @@ function Init()
json: "application/json",
};
- var TestData =
- {
- languages: [{value: "cpp", name: "C++"}, {value: "java", name: "Java"}]
- };
+ var TestData = {};
+
+ var languages = [{value: "cpp", name: "C++"}, {value: "java", name: "Java"}]
if(process.platform == "win32")
{
- TestData.languages.push({value: "csharp", name: "C#"});
+ languages.push({value: "csharp", name: "C#"});
}
var libraries = ["/lib/Ice.js", "/lib/Ice.min.js",
@@ -98,9 +97,9 @@ function Init()
}
else
{
- var languages = TestData.languages.map(function(o) { return o.value; });
- var j = languages.indexOf(language);
- language = languages[j == languages.length - 1 ? 0 : j + 1];
+ var lgs = languages.map(function(o) { return o.value; });
+ var j = lgs.indexOf(language);
+ language = lgs[j == lgs.length - 1 ? 0 : j + 1];
worker = false;
protocol = "http";
}
@@ -159,6 +158,11 @@ function Init()
"/test/Common/TestSuite.js"
];
}
+ TestData.languages = languages.slice();
+ if(testSuite.files.indexOf("Server.js") >= 0)
+ {
+ TestData.languages.push({value: "js", name: "JavaScript"});
+ }
res.writeHead(200, {"Content-Type": "text/html"});
res.end(template.render(TestData));
console.log("HTTP/200 (Ok)" + req.method + " " + req.url.pathname);
diff --git a/js/src/Ice/Buffer.js b/js/src/Ice/Buffer.js
index d6f395629ba..499d8726cdc 100644
--- a/js/src/Ice/Buffer.js
+++ b/js/src/Ice/Buffer.js
@@ -371,12 +371,12 @@ class Buffer
s = decodeURIComponent(escape(s));
return s;
}
-
+
get position()
{
return this._position;
}
-
+
set position(value)
{
if(value >= 0 && value <= this._limit)
@@ -384,12 +384,12 @@ class Buffer
this._position = value;
}
}
-
+
get limit()
{
return this._limit;
}
-
+
set limit(value)
{
if(value <= this.capacity)
@@ -401,17 +401,17 @@ class Buffer
}
}
}
-
+
get capacity()
{
return this.b === null ? 0 : this.b.byteLength;
}
-
+
get remaining()
{
return this._limit - this._position;
}
-
+
//
// Create a native buffer from an array of bytes.
//
diff --git a/js/src/Ice/ConnectionI.js b/js/src/Ice/ConnectionI.js
index 1bf5c7d0b28..d937186a6fb 100644
--- a/js/src/Ice/ConnectionI.js
+++ b/js/src/Ice/ConnectionI.js
@@ -1729,9 +1729,10 @@ class ConnectionI
}
return AsyncStatus.Sent;
}
+
message.doAdopt();
- this._writeStream.swap(stream);
+ this._writeStream.swap(message.stream);
this._sendStreams.push(message);
this.scheduleTimeout(SocketOperation.Write, this._endpoint.timeout());
@@ -1930,9 +1931,18 @@ class ConnectionI
{
this.invokeException(ex, invokeNum);
}
+ else if(ex instanceof Ice.ServantError)
+ {
+ // Ignore
+ }
else
{
- throw ex;
+ //
+ // An Error was raised outside of servant code (i.e., by Ice code).
+ // Attempt to log the error and clean up.
+ //
+ this._logger.error("unexpected exception:\n" + ex.toString());
+ this.invokeException(requestId, new Ice.UnknownException(ex), invokeNum, false);
}
}
}
diff --git a/js/src/Ice/Exception.js b/js/src/Ice/Exception.js
index 3ad61513fa7..14d9472df16 100644
--- a/js/src/Ice/Exception.js
+++ b/js/src/Ice/Exception.js
@@ -51,6 +51,17 @@ const toString = function(key, object, objectTable, ident)
return s;
};
+class ServantError extends Error
+{
+ constructor(cause)
+ {
+ super();
+ this.cause = cause;
+ }
+}
+
+Ice.ServantError = ServantError;
+
//
// Ice.Exception
//
@@ -99,7 +110,7 @@ class Exception extends Error
this._inToStringAlready = false;
return s;
}
-
+
static captureStackTrace(object)
{
const stack = new Error().stack;
@@ -112,7 +123,7 @@ class Exception extends Error
Object.defineProperty(object, "stack", {
get: function()
{
- return stack;
+ return stack;
}
});
}
diff --git a/js/src/Ice/IncomingAsync.js b/js/src/Ice/IncomingAsync.js
index 76e4a29666b..4ef1526eb44 100644
--- a/js/src/Ice/IncomingAsync.js
+++ b/js/src/Ice/IncomingAsync.js
@@ -150,22 +150,7 @@ class IncomingAsync
this._instance.initializationData().logger.warning(s.join(""));
}
- servantLocatorFinished()
- {
- Debug.assert(this._locator !== null && this._servant !== null);
- try
- {
- this._locator.finished(this._current, this._servant, this._cookie.value);
- return true;
- }
- catch(ex)
- {
- this.handleException(ex);
- }
- return false;
- }
-
- handleException(ex)
+ handleException(ex, amd)
{
Debug.assert(this._connection !== null);
@@ -366,6 +351,11 @@ class IncomingAsync
{
this._connection.sendNoResponse();
}
+
+ if(!amd)
+ {
+ throw new Ice.ServantError(ex);
+ }
}
this._connection = null;
@@ -431,7 +421,7 @@ class IncomingAsync
catch(ex)
{
this.skipReadParams(); // Required for batch requests.
- this.handleException(ex);
+ this.handleException(ex, false);
return;
}
}
@@ -457,7 +447,7 @@ class IncomingAsync
catch(ex)
{
this.skipReadParams(); // Required for batch requests.
- this.handleException(ex);
+ this.handleException(ex, false);
return;
}
}
@@ -468,16 +458,16 @@ class IncomingAsync
let promise = this._servant._iceDispatch(this, this._current);
if(promise !== null)
{
- promise.then(() => this.response(), (ex) => this.exception(ex));
+ promise.then(() => this.completed(null, true), (ex) => this.completed(ex, true));
return;
}
Debug.assert(!this._response || this._os !== null);
- this.response();
+ this.completed(null, false);
}
catch(ex)
{
- this.exception(ex);
+ this.completed(ex, false);
}
}
@@ -512,18 +502,31 @@ class IncomingAsync
this._current.encoding = this._is.skipEncapsulation();
}
- response()
+ completed(exc, amd)
{
try
{
- if(this._locator !== null && !this.servantLocatorFinished())
+ if(this._locator !== null && !this.servantLocatorFinished(amd))
{
- return;
+ Debug.assert(this._locator !== null && this._servant !== null);
+ try
+ {
+ this._locator.finished(this._current, this._servant, this._cookie.value);
+ }
+ catch(ex)
+ {
+ this.handleException(ex, amd);
+ return;
+ }
}
Debug.assert(this._connection !== null);
- if(this._response)
+ if(exc != null)
+ {
+ this.handleException(exc, amd);
+ }
+ else if(this._response)
{
this._connection.sendResponse(this._os);
}
@@ -534,26 +537,18 @@ class IncomingAsync
}
catch(ex)
{
- this._connection.invokeException(ex, 1);
- }
- this._connection = null;
- }
-
- exception(exc)
- {
- try
- {
- if(this._locator !== null && !this.servantLocatorFinished())
+ if(ex instanceof Ice.LocalException)
{
- return;
+ this._connection.invokeException(ex, 1);
+ }
+ else
+ {
+ throw ex;
}
- this.handleException(exc);
- }
- catch(ex)
- {
- this._connection.invokeException(ex, 1);
}
+ this._connection = null;
}
+
}
Ice.IncomingAsync = IncomingAsync;
diff --git a/js/src/Ice/ObjectAdapterFactory.js b/js/src/Ice/ObjectAdapterFactory.js
index 2115358984a..d68aa5ff46e 100644
--- a/js/src/Ice/ObjectAdapterFactory.js
+++ b/js/src/Ice/ObjectAdapterFactory.js
@@ -48,7 +48,7 @@ class ObjectAdapterFactory
this._instance = null;
this._communicator = null;
- this._shutdownPromise = _Promise.all(this._adapters.map(adapter => adapter.deactivate()));
+ _Promise.all(this._adapters.map(adapter => adapter.deactivate())).then(() => this._shutdownPromise.resolve());
return this._shutdownPromise;
}
diff --git a/js/src/Ice/PropertyNames.js b/js/src/Ice/PropertyNames.js
index 835a981434d..7271a5973c2 100644
--- a/js/src/Ice/PropertyNames.js
+++ b/js/src/Ice/PropertyNames.js
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Mar 23 15:24:16 2017
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -80,6 +80,7 @@ PropertyNames.IceProps =
new Property("/^Ice\.BatchAutoFlush/", true, null),
new Property("/^Ice\.BatchAutoFlushSize/", false, null),
new Property("/^Ice\.ChangeUser/", false, null),
+ new Property("/^Ice\.ClassGraphDepthMax/", false, null),
new Property("/^Ice\.ClientAccessPolicyProtocol/", false, null),
new Property("/^Ice\.Compression\.Level/", false, null),
new Property("/^Ice\.CollectObjects/", false, null),
diff --git a/js/src/Ice/Stream.js b/js/src/Ice/Stream.js
index 85386ff8786..8ac72046c6e 100644
--- a/js/src/Ice/Stream.js
+++ b/js/src/Ice/Stream.js
@@ -1252,7 +1252,7 @@ class InputStream
{
if(this._encapsStack !== null)
{
- Debug.assert(this._encapsStack.next);
+ Debug.assert(this._encapsStack.next === null);
this._encapsStack.next = this._encapsCache;
this._encapsCache = this._encapsStack;
this._encapsCache.reset();
@@ -1840,7 +1840,7 @@ class InputStream
//
this._encapsStack.decoder.readValue.call(
this._encapsStack.decoder,
- obj =>
+ cb === null ? null : obj =>
{
if(obj !== null && !(obj instanceof T))
{
diff --git a/js/src/Ice/TraceUtil.js b/js/src/Ice/TraceUtil.js
index eee9a10d7b1..05452817e2f 100644
--- a/js/src/Ice/TraceUtil.js
+++ b/js/src/Ice/TraceUtil.js
@@ -25,18 +25,8 @@ const Protocol = Ice.Protocol;
const StringUtil = Ice.StringUtil;
const OperationMode = Ice.OperationMode;
const Identity = Ice.Identity;
-
const slicingIds = new Map();
-function traceSlicing(kind, typeId, slicingCat, logger)
-{
- if(!slicingIds.has(typeId))
- {
- logger.trace(slicingCat, `unknown ${kind} type \`${typeId}'`);
- slicingIds.set(typeId, 1);
- }
-}
-
function printIdentityFacetOperation(s, stream)
{
let toStringMode = Ice.ToStringMode.Unicode;
@@ -366,6 +356,15 @@ function getMessageTypeAsString(type)
class TraceUtil
{
+ static traceSlicing(kind, typeId, slicingCat, logger)
+ {
+ if(!slicingIds.has(typeId))
+ {
+ logger.trace(slicingCat, `unknown ${kind} type \`${typeId}'`);
+ slicingIds.set(typeId, 1);
+ }
+ }
+
static traceSend(stream, logger, traceLevels)
{
if(traceLevels.protocol >= 1)
diff --git a/js/test/Common/ControllerI.js b/js/test/Common/ControllerI.js
index f83b3fc7083..17433db22d6 100644
--- a/js/test/Common/ControllerI.js
+++ b/js/test/Common/ControllerI.js
@@ -33,17 +33,40 @@ function isWindows()
return navigator.userAgent.indexOf("Windows") != -1;
}
+class Logger extends Ice.Logger
+{
+ constructor(out)
+ {
+ super()
+ this._out = out
+ }
+
+ write(message, indent)
+ {
+ if(indent)
+ {
+ message = message.replace(/\n/g, "\n ");
+ }
+ this._out.writeLine(message);
+ }
+}
+
class ProcessI extends Test.Common.Process
{
- constructor(promise, output)
+ constructor(promise, output, ready)
{
super();
this._promise = promise;
this._output = output;
+ this._ready = ready;
}
waitReady(timeout, current)
{
+ if(this._ready)
+ {
+ return this._ready;
+ }
}
waitSuccess(timeout, current)
@@ -66,11 +89,11 @@ class ProcessI extends Test.Common.Process
class ProcessControllerI extends Test.Common.ProcessController
{
- constructor(output, logger, useWorker, scripts)
+ constructor(clientOutput, serverOutput, useWorker, scripts)
{
super();
- this._output = output;
- this._logger = logger;
+ this._clientOutput = clientOutput;
+ this._serverOutput = serverOutput;
this._useWorker = useWorker;
this._scripts = scripts;
}
@@ -78,9 +101,13 @@ class ProcessControllerI extends Test.Common.ProcessController
start(testSuite, exe, args, current)
{
let promise;
+ let ready = null;
+ if(exe === "Server" || exe === "ServerAMD")
+ {
+ ready = new Ice.Promise();
+ }
if(this._useWorker)
{
- let out = this._output;
let scripts = this._scripts;
promise = new Promise((resolve, reject) => {
let worker;
@@ -96,11 +123,23 @@ class ProcessControllerI extends Test.Common.ProcessController
worker.onmessage = function(e) {
if(e.data.type == "write")
{
- out.write(e.data.message);
+ this._clientOutput.write(e.data.message);
}
else if(e.data.type == "writeLine")
{
- out.writeLine(e.data.message);
+ this._clientOutput.writeLine(e.data.message);
+ }
+ if(e.data.type == "serverWrite")
+ {
+ this._serverOutput.write(e.data.message);
+ }
+ else if(e.data.type == "serverWriteLine")
+ {
+ this._serverOutput.writeLine(e.data.message);
+ }
+ else if(e.data.type == "ready" && (exe === "Server" || exe === "ServerAMD"))
+ {
+ ready.resolve();
}
else if(e.data.type == "finished")
{
@@ -121,19 +160,22 @@ class ProcessControllerI extends Test.Common.ProcessController
else
{
let initData = new Ice.InitializationData();
- initData.logger = this._logger;
initData.properties = Ice.createProperties(args);
process.argv = args
- if(exe === "ClientBidir")
+ if(exe === "Server" || exe === "ServerAMD")
{
- promise = _testBidir(this._output, initData);
+ initData.logger = new Logger(this._serverOutput);
+ let test = exe === "Server" ? _server : _serveramd;
+ promise = test(this._serverOutput, initData, ready);
}
else
{
- promise = _test(this._output, initData);
+ initData.logger = new Logger(this._clientOutput);
+ promise = _test(this._clientOutput, initData);
}
}
- return Test.Common.ProcessPrx.uncheckedCast(current.adapter.addWithUUID(new ProcessI(promise, this._output)));
+ let out = exe === "Server" || exe === "ServerAMD" ? this._serverOutput : this._clientOutput;
+ return Test.Common.ProcessPrx.uncheckedCast(current.adapter.addWithUUID(new ProcessI(promise, out, ready)));
}
getHost(protocol, ipv6, current)
@@ -142,25 +184,31 @@ class ProcessControllerI extends Test.Common.ProcessController
}
};
-function runController(output, scripts)
+function runController(clientOutput, serverOutput, scripts)
{
- let out =
+ function wrapOutput(output)
{
- write: function(msg)
- {
- let text = output.val();
- output.val((text === "") ? msg : (text + msg));
- },
- writeLine: function(msg)
- {
- out.write(msg + "\n");
- output.scrollTop(output.get(0).scrollHeight);
- },
- get: function()
- {
- return output.val()
- }
- };
+ return {
+ write: function(msg)
+ {
+ let text = output.val();
+ output.val((text === "") ? msg : (text + msg));
+ },
+ writeLine: function(msg)
+ {
+ msg = msg + "\n";
+ let text = output.val();
+ output.val((text === "") ? msg : (text + msg));
+ output.scrollTop(output.get(0).scrollHeight);
+ },
+ get: function()
+ {
+ return output.val()
+ }
+ };
+ }
+ let out = wrapOutput(clientOutput);
+ let serverOut = wrapOutput(serverOutput);
window.onerror = function(msg, url, line, column, err)
{
@@ -173,24 +221,6 @@ function runController(output, scripts)
return false;
};
- class Logger extends Ice.Logger
- {
- constructor(out)
- {
- super()
- this._out = out
- }
-
- write(message, indent)
- {
- if(indent)
- {
- message = message.replace(/\n/g, "\n ");
- }
- out.writeLine(message);
- }
- }
-
let uri = new URI(document.location.href)
let initData = new Ice.InitializationData();
let protocol = uri.protocol() === "http" ? "ws" : "wss";
@@ -226,7 +256,7 @@ function runController(output, scripts)
let registry = Test.Common.ProcessControllerRegistryPrx.uncheckedCast(comm.stringToProxy(str));
comm.createObjectAdapter("").then(adapter => {
let ident = new Ice.Identity("ProcessController", "Browser");
- let processController = adapter.add(new ProcessControllerI(out, initData.logger, worker, scripts), ident);
+ let processController = adapter.add(new ProcessControllerI(out, serverOut, worker, scripts), ident);
adapter.activate();
registerProcessController(adapter, registry, processController);
}).catch(ex => {
diff --git a/js/test/Common/ControllerWorker.js b/js/test/Common/ControllerWorker.js
index e01c557fe83..a9fa6071cf3 100644
--- a/js/test/Common/ControllerWorker.js
+++ b/js/test/Common/ControllerWorker.js
@@ -13,7 +13,7 @@
*/
var process = { argv : [] };
-let out =
+let clientOut =
{
write: function(msg)
{
@@ -25,6 +25,18 @@ let out =
}
};
+let serverOut =
+{
+ write: function(msg)
+ {
+ self.postMessage({type:"serverWrite", message:msg});
+ },
+ writeLine: function(msg)
+ {
+ self.postMessage({type:"serverWriteLine", message:msg});
+ }
+};
+
self.onmessage = function(e)
{
try
@@ -54,16 +66,20 @@ self.onmessage = function(e)
let promise
let initData = new Ice.InitializationData();
- initData.logger = new Logger(out);
initData.properties = Ice.createProperties(e.data.args);
process.argv = e.data.args;
- if(e.data.exe === "ClientBidir")
+ if(e.data.exe === "Server" || e.data.exe === "ServerAMD")
{
- promise = _testBidir(out, initData);
+ initData.logger = new Logger(serverOut);
+ let ready = new Ice.Promise();
+ let test = e.data.exe === "Server" ? _server : _serveramd;
+ promise = test(serverOut, initData, ready);
+ ready.then(() => self.postMessage({type:"ready"}));
}
else
{
- promise = _test(out, initData);
+ initData.logger = new Logger(clientOut);
+ promise = _test(clientOut, initData);
}
promise.then(function() {
self.postMessage({ type: "finished" });
diff --git a/js/test/Common/TestRunner.js b/js/test/Common/TestRunner.js
index 9725c0e9352..8fa5f6d1978 100644
--- a/js/test/Common/TestRunner.js
+++ b/js/test/Common/TestRunner.js
@@ -10,7 +10,7 @@
/* global
_test : false,
- _testBidir : false,
+ _runServer : false,
Test : false,
*/
@@ -108,7 +108,6 @@ function runTest(testsuite, language, host, protocol, testcases, out)
var communicator;
var id = new Ice.InitializationData();
var port = protocol == "ws" ? 15002 : 15003;
- var serverTestCase;
id.logger = Logger;
id.properties = Ice.createProperties();
id.properties.setProperty("Ice.Default.Host", host);
@@ -119,7 +118,7 @@ function runTest(testsuite, language, host, protocol, testcases, out)
return Ice.Promise.try(
function()
{
- if(typeof(_runServer) === "undefined" && typeof(_testBidir) === "undefined")
+ if(typeof(_runServer) === "undefined")
{
return _test(out, id);
}
@@ -140,17 +139,18 @@ function runTest(testsuite, language, host, protocol, testcases, out)
}
var runTestCase;
- if(typeof(_testBidir) !== "undefined" && client == _testBidir)
+ out.writeLine("[ running " + testcase.name + " test]");
+ if(language === "js")
{
- out.writeLine("[ running bidir " + testcase.name + " test]");
- runTestCase = function() { return controller.runTestCase("cpp", "Ice/echo", "server", language); };
+ runTestCase = function() { return controller.runTestCase("cpp", "Ice/echo", "server", ""); };
}
else
{
- out.writeLine("[ running " + testcase.name + " test]");
runTestCase = function() { return controller.runTestCase("js", testsuite, testcase.name, language) };
}
out.write("starting server side... ");
+ var serverTestCase;
+ var server;
return runTestCase().then(
function(proxy)
{
@@ -164,17 +164,40 @@ function runTest(testsuite, language, host, protocol, testcases, out)
function()
{
out.writeLine("ok")
+ process.argv = testcase.args;
+ if(language === "js")
+ {
+ var initData = id.clone();
+ if(testcase.args !== undefined)
+ {
+ initData.properties = Ice.createProperties(testcase.args, id.properties);
+ }
+ ready = new Ice.Promise();
+ server = _server(out, initData.clone(), ready)
+ return ready;
+ }
+ }
+ ).then(
+ function()
+ {
var initData = id.clone();
if(testcase.args !== undefined)
{
initData.properties = Ice.createProperties(testcase.args, id.properties);
- process.argv = testcase.args;
}
return client(out, initData);
}
).then(
function()
{
+ if(server)
+ {
+ return server; // Wait for server to terminate
+ }
+ }
+ ).then(
+ function()
+ {
return serverTestCase.stopServerSide(true);
}
).catch(
@@ -194,19 +217,9 @@ function runTest(testsuite, language, host, protocol, testcases, out)
}
var p = Ice.Promise.resolve();
- if(typeof(_runServer) !== "undefined")
- {
- testcases.forEach(function(testcase) {
- p = p.then(function() { return run(testcase, _test); })
- });
- }
- if(typeof(_testBidir) !== "undefined" && language === "cpp")
- {
- testcases.forEach(function(testcase) {
- options = typeof(_runEchoServerOptions) !== "undefined" ? _runEchoServerOptions : []
- p = p.then(function() { return run(testcase, _testBidir); })
- });
- }
+ testcases.forEach(function(testcase) {
+ p = p.then(function() { return run(testcase, _test); })
+ });
return p;
}
).finally(
diff --git a/js/test/Common/TestSuites.json b/js/test/Common/TestSuites.json
index feefddd79f9..c69de6be963 100644
--- a/js/test/Common/TestSuites.json
+++ b/js/test/Common/TestSuites.json
@@ -31,7 +31,7 @@
},
"Ice/exceptions":
{
- "files": ["Test.js", "Client.js", "ThrowerI.js", "AMDThrowerI.js", "ClientBidir.js"],
+ "files": ["Test.js", "Client.js", "ThrowerI.js", "AMDThrowerI.js", "Server.js", "ServerAMD.js"],
"testcases":
[
{
@@ -49,7 +49,7 @@
},
"Ice/facets":
{
- "files": ["Test.js", "Client.js", "TestI.js", "ClientBidir.js"]
+ "files": ["Test.js", "Client.js", "TestI.js", "Server.js"]
},
"Ice/hold":
{
@@ -61,16 +61,16 @@
},
"Ice/inheritance":
{
- "files": ["Test.js", "Client.js", "InitialI.js", "ClientBidir.js"]
+ "files": ["Test.js", "Client.js", "InitialI.js", "Server.js"]
},
"Ice/operations":
{
"files": ["Test.js", "Twoways.js", "Oneways.js", "BatchOneways.js", "Client.js",
- "MyDerivedClassI.js", "AMDMyDerivedClassI.js", "ClientBidir.js"]
+ "MyDerivedClassI.js", "AMDMyDerivedClassI.js", "Server.js", "ServerAMD.js"]
},
"Ice/objects":
{
- "files": ["Test.js", "Client.js"],
+ "files": ["Test.js", "Client.js", "InitialI.js", "Server.js"],
"testcases":
[
{
@@ -88,7 +88,7 @@
},
"Ice/optional":
{
- "files": ["Test.js", "Client.js", "ClientPrivate.js", "InitialI.js", "AMDInitialI.js", "ClientBidir.js"],
+ "files": ["Test.js", "Client.js", "ClientPrivate.js", "InitialI.js", "AMDInitialI.js", "Server.js", "ServerAMD.js"],
"testcases":
[
{
diff --git a/js/test/Common/controller.html b/js/test/Common/controller.html
index 24c547c5d97..33f53873f28 100644
--- a/js/test/Common/controller.html
+++ b/js/test/Common/controller.html
@@ -13,8 +13,9 @@
<script>
$(document).foundation();
$(document).ready(function() {
- $("#console").height(300);
- runController($("#console"), "{{{scripts}}}".split(","));
+ $("#clientConsole").height(300);
+ $("#serverConsole").height(100);
+ runController($("#clientConsole"), $("#serverConsole"), "{{{scripts}}}".split(","));
});
</script>
</head>
@@ -31,7 +32,8 @@
<section role="main" id="body">
<div class="row">
<div class="large-12 medium-12 columns">
- <textarea id="console" class="disabled" height="300" readonly></textarea>
+ <textarea id="clientConsole" class="disabled" height="300" readonly></textarea>
+ <textarea id="serverConsole" class="disabled" height="100" readonly></textarea>
</div>
</div>
</section>
diff --git a/js/test/Common/run.js b/js/test/Common/run.js
index f4fa106f176..105085ef5f2 100755
--- a/js/test/Common/run.js
+++ b/js/test/Common/run.js
@@ -25,19 +25,28 @@ var writeLine = function(msg)
this.write(msg + "\n");
};
+var exception = function(ex)
+{
+ console.log(ex.toString());
+ if(ex.stack)
+ {
+ console.log(ex.stack);
+ }
+ process.exit(1);
+};
+
var id = new Ice.InitializationData();
id.properties = Ice.createProperties(process.argv);
exe = process.argv[2]
var test = module.require(exe)
-test = exe === "ClientBidir" ? test._testBidir : test._test;
-
-test({write: write, writeLine: writeLine}, id).catch(
- ex =>
- {
- console.log(ex.toString());
- if(ex.stack)
- {
- console.log(ex.stack);
- }
- process.exit(1);
- });
+if(exe === "Server" || exe === "ServerAMD")
+{
+ var ready = new Ice.Promise();
+ test = exe === "Server" ? test._server : test._serveramd;
+ test({write: write, writeLine: writeLine}, id, ready).catch(exception)
+ ready.then(() => console.log("server ready"));
+}
+else
+{
+ test._test({write: write, writeLine: writeLine}, id).catch(exception)
+} \ No newline at end of file
diff --git a/js/test/Ice/exceptions/AMDThrowerI.js b/js/test/Ice/exceptions/AMDThrowerI.js
index a19e0904d07..b7adcbe5000 100644
--- a/js/test/Ice/exceptions/AMDThrowerI.js
+++ b/js/test/Ice/exceptions/AMDThrowerI.js
@@ -11,7 +11,6 @@
{
var Ice = require("ice").Ice;
var Test = require("Test").Test;
- var Class = Ice.Class;
var test = function(b)
{
diff --git a/js/test/Ice/exceptions/Client.js b/js/test/Ice/exceptions/Client.js
index a4841d61a0d..c613df0fa74 100644
--- a/js/test/Ice/exceptions/Client.js
+++ b/js/test/Ice/exceptions/Client.js
@@ -12,13 +12,13 @@
var Ice = require("ice").Ice;
var Test = require("Test").Test;
- var allTests = function(out, communicator, Test, bidir)
+ var allTests = function(out, communicator, Test)
{
class EmptyI extends Test.Empty
{
}
- class ServantLocatorI
+ class ServantLocatorI
{
locate(curr, cookie)
{
@@ -355,25 +355,22 @@
).then(
function()
{
- if(!bidir)
- {
- out.write("testing memory limit marshal exception...");
- return thrower.throwMemoryLimitException(null).then(
- failCB,
- function(ex)
- {
- test(ex instanceof Ice.MemoryLimitException);
- return thrower.throwMemoryLimitException(Ice.Buffer.createNative(20 * 1024));
- }
- ).then(
- failCB,
- function(ex)
- {
- test(ex instanceof Ice.ConnectionLostException);
- out.writeLine("ok");
- }
- );
- }
+ out.write("testing memory limit marshal exception...");
+ return thrower.throwMemoryLimitException(null).then(
+ failCB,
+ function(ex)
+ {
+ test(ex instanceof Ice.MemoryLimitException);
+ return thrower.throwMemoryLimitException(Ice.Buffer.createNative(20 * 1024));
+ }
+ ).then(
+ failCB,
+ function(ex)
+ {
+ test(ex.toString().indexOf("ConnectionLostException") > 0);
+ out.writeLine("ok");
+ }
+ );
}
).then(
function()
diff --git a/js/test/Ice/exceptions/Server.js b/js/test/Ice/exceptions/Server.js
new file mode 100644
index 00000000000..ffb45677831
--- /dev/null
+++ b/js/test/Ice/exceptions/Server.js
@@ -0,0 +1,56 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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.
+//
+// **********************************************************************
+
+(function(module, require, exports)
+{
+ var Ice = require("ice").Ice;
+ var Test = require("Test").Test;
+ var ThrowerI = require("ThrowerI").ThrowerI;
+
+ var run = function(out, id, ready)
+ {
+ id.properties.setProperty("Ice.MessageSizeMax", "10");
+ id.properties.setProperty("Ice.Warn.Dispatch", "0");
+ id.properties.setProperty("Ice.Warn.Connections", "0");
+ var communicator = Ice.initialize(id);
+ var adapter;
+ var echo = Test.EchoPrx.uncheckedCast(communicator.stringToProxy("__echo:default -p 12010"));
+ return Ice.Promise.try(() =>
+ {
+ return communicator.createObjectAdapter("");
+ }
+ ).then(adpt =>
+ {
+ adapter = adpt;
+ adapter.add(new ThrowerI(), Ice.stringToIdentity("thrower"));
+ return echo.setConnection();
+ }
+ ).then(() =>
+ {
+ var connection = echo.ice_getCachedConnection();
+ connection.setCloseCallback((con) => {
+ // Re-establish connection if it fails (necessary for MemoryLimitException test)
+ echo.setConnection().then(() => echo.ice_getCachedConnection().setAdapter(adapter))
+ });
+ connection.setAdapter(adapter);
+ adapter.activate();
+ ready.resolve();
+ return communicator.waitForShutdown();
+ }
+ ).then(() =>
+ {
+ return echo.shutdown();
+ }
+ ).finally(() => communicator.destroy());
+ };
+ exports._server = run;
+}
+(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/exceptions/ServerAMD.js b/js/test/Ice/exceptions/ServerAMD.js
new file mode 100644
index 00000000000..f6383f2ee3d
--- /dev/null
+++ b/js/test/Ice/exceptions/ServerAMD.js
@@ -0,0 +1,57 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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.
+//
+// **********************************************************************
+
+(function(module, require, exports)
+{
+ var Ice = require("ice").Ice;
+ var Test = require("Test").Test;
+ var AMDThrowerI = require("AMDThrowerI").AMDThrowerI;
+
+ var run = function(out, id, ready)
+ {
+ id.properties.setProperty("Ice.MessageSizeMax", "10");
+ id.properties.setProperty("Ice.Warn.Dispatch", "0");
+ id.properties.setProperty("Ice.Warn.Connections", "0");
+ var communicator = Ice.initialize(id);
+ var adapter;
+ var echo = Test.EchoPrx.uncheckedCast(communicator.stringToProxy("__echo:default -p 12010"));
+ return Ice.Promise.try(() =>
+ {
+ return communicator.createObjectAdapter("");
+ }
+ ).then(adpt =>
+ {
+ adapter = adpt;
+ adapter.add(new AMDThrowerI(), Ice.stringToIdentity("thrower"));
+ return echo.setConnection();
+ }
+ ).then(() =>
+ {
+ var connection = echo.ice_getCachedConnection();
+ connection.setCloseCallback((con) => {
+ // Re-establish connection if it fails (necessary for MemoryLimitException test)
+ echo.setConnection().then(() => echo.ice_getCachedConnection().setAdapter(adapter))
+ });
+ connection.setAdapter(adapter);
+ echo.ice_getCachedConnection().setAdapter(adapter);
+ adapter.activate();
+ ready.resolve();
+ return communicator.waitForShutdown();
+ }
+ ).then(() =>
+ {
+ return echo.shutdown();
+ }
+ ).finally(() => communicator.destroy());
+ };
+ exports._serveramd = run;
+}
+(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/exceptions/Test.ice b/js/test/Ice/exceptions/Test.ice
index be0c5f0253e..1b3c3a49425 100644
--- a/js/test/Ice/exceptions/Test.ice
+++ b/js/test/Ice/exceptions/Test.ice
@@ -75,6 +75,7 @@ interface WrongOperation
interface Echo
{
+ void setConnection();
void startBatch();
void flushBatch();
void shutdown();
diff --git a/js/test/Ice/exceptions/ThrowerI.js b/js/test/Ice/exceptions/ThrowerI.js
index 7686ecb8a92..2725cf51c87 100644
--- a/js/test/Ice/exceptions/ThrowerI.js
+++ b/js/test/Ice/exceptions/ThrowerI.js
@@ -12,8 +12,6 @@
var Ice = require("ice").Ice;
var Test = require("Test").Test;
- var Class = Ice.Class;
-
var test = function(b)
{
if(!b)
diff --git a/js/test/Ice/facets/ClientBidir.js b/js/test/Ice/facets/Server.js
index c301dd5e39f..1c34aeac407 100644
--- a/js/test/Ice/facets/ClientBidir.js
+++ b/js/test/Ice/facets/Server.js
@@ -11,7 +11,6 @@
{
var Ice = require("ice").Ice;
var Test = require("Test").Test;
- var Client = require("Client");
var TestI = require("TestI");
var DI = TestI.DI;
@@ -19,26 +18,29 @@
var HI = TestI.HI;
var EmptyI = TestI.EmptyI;
- var allTests = function(out, communicator)
+ var test = function(b)
{
- var p = new Ice.Promise();
- var test = function(b)
+ if(!b)
{
- if(!b)
+ try
{
- try
- {
- throw new Error("test failed");
- }
- catch(err)
- {
- p.reject(err);
- throw err;
- }
+ throw new Error("test failed");
}
- };
+ catch(err)
+ {
+ p.reject(err);
+ throw err;
+ }
+ }
+ };
+
+ var run = function(out, id, ready)
+ {
+ var communicator = Ice.initialize(id);
+ var adapter;
+ var echo = Test.EchoPrx.uncheckedCast(communicator.stringToProxy("__echo:default -p 12010"));
- Ice.Promise.try(
+ return Ice.Promise.try(
function()
{
out.write("testing facet registration exceptions... ");
@@ -102,14 +104,13 @@
return adapter.deactivate();
}
- ).then(
- function(r)
+ ).then(() =>
{
return communicator.createObjectAdapter("");
}
- ).then(
- function(adapter)
+ ).then(adpt =>
{
+ adapter = adpt;
var di = new DI();
adapter.add(di, Ice.stringToIdentity("d"));
adapter.addFacet(di, Ice.stringToIdentity("d"), "facetABCD");
@@ -117,53 +118,22 @@
adapter.addFacet(fi, Ice.stringToIdentity("d"), "facetEF");
var hi = new HI();
adapter.addFacet(hi, Ice.stringToIdentity("d"), "facetGH");
-
- var prx = Ice.ObjectPrx.uncheckedCast(communicator.stringToProxy("d:default -p 12010"));
- return prx.ice_getConnection().then(
- function(conn)
- {
- conn.setAdapter(adapter);
- return Client._clientAllTests(out, communicator);
- });
+ return echo.setConnection();
}
- ).then(p.resolve, p.reject);
-
- return p;
- };
-
- var run = function(out, id)
- {
- var communicator = Ice.initialize(id);
- return Ice.Promise.try(
- function()
- {
- out.writeLine("testing bidir callbacks with synchronous dispatch...");
- return allTests(out, communicator);
- }
- ).then(
- function()
+ ).then(() =>
{
- return communicator.destroy();
+ echo.ice_getCachedConnection().setAdapter(adapter);
+ adapter.activate();
+ ready.resolve();
+ return communicator.waitForShutdown();
}
- ).then(
- function()
- {
- communicator = Ice.initialize(id);
- return Test.EchoPrx.checkedCast(communicator.stringToProxy("__echo:default -p 12010"));
- }
- ).then(
- function(prx)
- {
- return prx.shutdown();
- }
- ).finally(
- function()
+ ).then(() =>
{
- return communicator.destroy();
+ return echo.shutdown();
}
- );
+ ).finally(() => communicator.destroy());
};
- exports._testBidir = run;
+ exports._server = run;
}
(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
diff --git a/js/test/Ice/facets/Test.ice b/js/test/Ice/facets/Test.ice
index 3ac9c3429f4..319b12bced0 100644
--- a/js/test/Ice/facets/Test.ice
+++ b/js/test/Ice/facets/Test.ice
@@ -59,6 +59,7 @@ interface H extends G
interface Echo
{
+ void setConnection();
void startBatch();
void flushBatch();
void shutdown();
diff --git a/js/test/Ice/inheritance/ClientBidir.js b/js/test/Ice/inheritance/ClientBidir.js
deleted file mode 100644
index 0c908cfd4f0..00000000000
--- a/js/test/Ice/inheritance/ClientBidir.js
+++ /dev/null
@@ -1,73 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2017 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.
-//
-// **********************************************************************
-
-(function(module, require, exports)
-{
- var Ice = require("ice").Ice;
- var Test = require("Test").Test;
- var InitialI = require("InitialI").InitialI;
- var Client = require("Client");
-
- var allTests = function(out, communicator)
- {
- return Ice.Promise.try(
- function()
- {
- return communicator.createObjectAdapter("").then(
- function(adapter)
- {
- var base = communicator.stringToProxy("initial:default -p 12010");
- adapter.add(new InitialI(adapter, base), Ice.stringToIdentity("initial"));
- return base.ice_getConnection().then(
- function(conn)
- {
- conn.setAdapter(adapter);
- return Client._clientAllTests(out, communicator);
- });
- });
- });
- };
-
- var run = function(out, id)
- {
- var communicator = Ice.initialize(id);
- return Ice.Promise.try(
- function()
- {
- out.writeLine("testing bidir callbacks with synchronous dispatch...");
- return allTests(out, communicator);
- }
- ).then(
- function()
- {
- return communicator.destroy();
- }
- ).then(
- function()
- {
- communicator = Ice.initialize(id);
- return Test.EchoPrx.checkedCast(communicator.stringToProxy("__echo:default -p 12010"));
- }
- ).then(
- function(prx)
- {
- return prx.shutdown();
- }
- ).finally(
- function()
- {
- return communicator.destroy();
- }
- );
- };
- exports._testBidir = run;
-}
-(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
- typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
- typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/inheritance/Server.js b/js/test/Ice/inheritance/Server.js
new file mode 100644
index 00000000000..3b104cf02c0
--- /dev/null
+++ b/js/test/Ice/inheritance/Server.js
@@ -0,0 +1,49 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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.
+//
+// **********************************************************************
+
+(function(module, require, exports)
+{
+ var Ice = require("ice").Ice;
+ var Test = require("Test").Test;
+ var InitialI = require("InitialI").InitialI;
+
+ var run = function(out, id, ready)
+ {
+ var communicator = Ice.initialize(id);
+ var adapter;
+ var echo = Test.EchoPrx.uncheckedCast(communicator.stringToProxy("__echo:default -p 12010"));
+ return Ice.Promise.try(() =>
+ {
+ return communicator.createObjectAdapter("");
+ }
+ ).then(adpt =>
+ {
+ adapter = adpt;
+ var base = communicator.stringToProxy("initial:default -p 12010");
+ adapter.add(new InitialI(adapter, base), Ice.stringToIdentity("initial"));
+ return echo.setConnection();
+ }
+ ).then(() =>
+ {
+ echo.ice_getCachedConnection().setAdapter(adapter);
+ adapter.activate();
+ ready.resolve();
+ return communicator.waitForShutdown();
+ }
+ ).then(() =>
+ {
+ return echo.shutdown();
+ }
+ ).finally(() => communicator.destroy());
+ };
+ exports._server = run;
+}
+(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/inheritance/Test.ice b/js/test/Ice/inheritance/Test.ice
index fe15a5c29bb..b0924bb8cdd 100644
--- a/js/test/Ice/inheritance/Test.ice
+++ b/js/test/Ice/inheritance/Test.ice
@@ -235,6 +235,7 @@ class D extends C
interface Echo
{
+ void setConnection();
void startBatch();
void flushBatch();
void shutdown();
diff --git a/js/test/Ice/objects/Client.js b/js/test/Ice/objects/Client.js
index 91413c1d1d7..175519b65cf 100644
--- a/js/test/Ice/objects/Client.js
+++ b/js/test/Ice/objects/Client.js
@@ -12,6 +12,19 @@
var Ice = require("ice").Ice;
var Test = require("Test").Test;
+ function loop(fn, repetitions) {
+ var i = 0;
+ var next = function next() {
+ while (i++ < repetitions) {
+ var r = fn.call(null, i);
+ if (r) {
+ return r.then(next);
+ }
+ }
+ };
+ return next();
+ }
+
class BI extends Test.B
{
ice_preMarshal()
@@ -377,8 +390,55 @@
var [retS, outS] = r;
test(retS.length === 1 && outS.length === 1);
out.writeLine("ok");
- out.write("testing compact ID... ");
+ out.write("testing recursive types... ");
+
+ var top = new Test.Recursive();
+ var p = top;
+ return loop(depth => {
+ p.v = new Test.Recursive();
+ p = p.v;
+ if((depth < 10 && (depth % 10) == 0) ||
+ (depth < 1000 && (depth % 100) == 0) ||
+ (depth < 10000 && (depth % 1000) == 0) ||
+ (depth % 10000) == 0)
+ {
+ return initial.setRecursive(top);
+ }
+ return null;
+ }, 20001);
+ }
+ ).then(() =>
+ {
+ return initial.supportsClassGraphDepthMax().then(function(v) { test(!v); });
+ },
+ (ex) =>
+ {
+ if(ex instanceof Ice.UnknownLocalException)
+ {
+ // Expected marshal exception from the server (max class graph depth reached)
+ }
+ else if(ex instanceof Ice.UnknownException)
+ {
+ // Expected stack overflow from the server (Java only)
+ }
+ else if(ex instanceof RangeError)
+ {
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+ ).then(()=>
+ {
+ return initial.setRecursive(new Test.Recursive());
+ }
+ ).then(()=>
+ {
+ out.writeLine("ok");
+
+ out.write("testing compact ID... ");
return initial.getCompact();
}
).then(compact =>
@@ -413,9 +473,12 @@
},
ex =>
{
- test(ex instanceof Ice.UnexpectedObjectException);
- test(ex.type == "::Test::AlsoEmpty");
- test(ex.expectedType == "::Test::Empty");
+ if(!(ex instanceof Ice.ObjectNotExistException))
+ {
+ test(ex instanceof Ice.UnexpectedObjectException);
+ test(ex.type == "::Test::AlsoEmpty");
+ test(ex.expectedType == "::Test::Empty");
+ }
}
).then(() =>
{
@@ -466,6 +529,7 @@
return Ice.Promise.try(() => allTests(out, c)).finally(() => c.destroy());
};
exports._test = run;
+ exports._clientAllTests = allTests;
exports._runServer = true;
}
(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
diff --git a/js/test/Ice/objects/InitialI.js b/js/test/Ice/objects/InitialI.js
new file mode 100644
index 00000000000..e8cd5c4a3db
--- /dev/null
+++ b/js/test/Ice/objects/InitialI.js
@@ -0,0 +1,319 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICEthis._LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+(function(module, require, exports)
+{
+ var Ice = require("ice").Ice;
+ var Test = require("Test").Test;
+
+ var test = function(b)
+ {
+ if(!b)
+ {
+ throw new Error("test failed");
+ }
+ };
+
+ class BI extends Test.B
+ {
+ ice_preMarshal()
+ {
+ this.preMarshalInvoked = true;
+ }
+
+ ice_postUnmarshal()
+ {
+ this.postUnmarshalInvoked = true;
+ }
+ };
+
+ class CI extends Test.C
+ {
+ ice_preMarshal()
+ {
+ this.preMarshalInvoked = true;
+ }
+
+ ice_postUnmarshal()
+ {
+ this.postUnmarshalInvoked = true;
+ }
+ };
+
+ class DI extends Test.D
+ {
+ ice_preMarshal()
+ {
+ this.preMarshalInvoked = true;
+ }
+
+ ice_postUnmarshal()
+ {
+ this.postUnmarshalInvoked = true;
+ }
+ };
+
+ class EI extends Test.E
+ {
+ constructor()
+ {
+ super(1, "hello");
+ }
+
+ checkValues()
+ {
+ return this.i == 1 && this.s == "hello";
+ }
+ };
+
+ class FI extends Test.F
+ {
+ constructor(e)
+ {
+ super(e, e);
+ }
+
+ checkValues()
+ {
+ return this.e1 !== null && this.e1 === this.e2;
+ }
+ };
+
+ class HI extends Test.H
+ {
+ };
+
+ class II extends Ice.InterfaceByValue
+ {
+ constructor()
+ {
+ super(Test.I.ice_staticId());
+ }
+ };
+
+ class JI extends Ice.InterfaceByValue
+ {
+ constructor()
+ {
+ super(Test.J.ice_staticId());
+ }
+ };
+
+ function MyValueFactory(type)
+ {
+ switch(type)
+ {
+ case "::Test::B":
+ return new BI();
+ case "::Test::C":
+ return new CI();
+ case "::Test::D":
+ return new DI();
+ case "::Test::E":
+ return new EI();
+ case "::Test::F":
+ return new FI();
+ case "::Test::I":
+ return new II();
+ case "::Test::J":
+ return new JI();
+ case "::Test::H":
+ return new HI();
+ case "::Test::Inner::A":
+ return new Test.Inner.A();
+ case "::Test::Inner::Sub::A":
+ return new Test.Inner.Sub.A();
+ default:
+ break;
+ }
+ return null;
+ }
+
+ class InitialI extends Test.Initial
+ {
+ constructor(communicator)
+ {
+ super();
+ if(communicator !== undefined)
+ {
+ communicator.getValueFactoryManager().add(MyValueFactory, "::Test::B");
+ communicator.getValueFactoryManager().add(MyValueFactory, "::Test::C");
+ communicator.getValueFactoryManager().add(MyValueFactory, "::Test::D");
+ communicator.getValueFactoryManager().add(MyValueFactory, "::Test::E");
+ communicator.getValueFactoryManager().add(MyValueFactory, "::Test::F");
+ communicator.getValueFactoryManager().add(MyValueFactory, "::Test::I");
+ communicator.getValueFactoryManager().add(MyValueFactory, "::Test::J");
+ communicator.getValueFactoryManager().add(MyValueFactory, "::Test::H");
+ communicator.getValueFactoryManager().add(MyValueFactory, "::Test::Inner::A");
+ communicator.getValueFactoryManager().add(MyValueFactory, "::Test::Inner::Sub::A");
+ }
+
+ this._b1 = new BI();
+ this._b2 = new BI();
+ this._c = new CI();
+ this._d = new DI();
+ this._e = new EI();
+ this._f = new FI(this._e, this._e);
+
+ this._b1.theA = this._b2; // Cyclic reference to another B
+ this._b1.theB = this._b1; // Self reference.
+ this._b1.theC = null; // Null reference.
+
+ this._b2.theA = this._b2; // Self reference, using base.
+ this._b2.theB = this._b1; // Cyclic reference to another B
+ this._b2.theC = this._c; // Cyclic reference to a C.
+
+ this._c.theB = this._b2; // Cyclic reference to a B.
+
+ this._d.theA = this._b1; // Reference to a B.
+ this._d.theB = this._b2; // Reference to a B.
+ this._d.theC = null; // Reference to a C.
+ }
+
+ getAll(current)
+ {
+ this._b1.preMarshalInvoked = false;
+ this._b2.preMarshalInvoked = false;
+ this._c.preMarshalInvoked = false;
+ this._d.preMarshalInvoked = false;
+ return [this._b1, this._b2, this._c, this._d]
+ }
+
+ getB1(current)
+ {
+ this._b1.preMarshalInvoked = false;
+ this._b2.preMarshalInvoked = false;
+ this._c.preMarshalInvoked = false;
+ return this._b1;
+ }
+
+ getB2(current)
+ {
+ this._b1.preMarshalInvoked = false;
+ this._b2.preMarshalInvoked = false;
+ this._c.preMarshalInvoked = false;
+ return this._b2;
+ }
+
+ getC(current)
+ {
+ this._b1.preMarshalInvoked = false;
+ this._b2.preMarshalInvoked = false;
+ this._c.preMarshalInvoked = false;
+ return this._c;
+ }
+
+ getD(current)
+ {
+ this._b1.preMarshalInvoked = false;
+ this._b2.preMarshalInvoked = false;
+ this._c.preMarshalInvoked = false;
+ this._d.preMarshalInvoked = false;
+ return this._d;
+ }
+
+ getE(current)
+ {
+ return this._e;
+ }
+
+ getF(current)
+ {
+ return this._f;
+ }
+
+ setRecursive(r, current)
+ {
+ }
+
+ supportsClassGraphDepthMax(current)
+ {
+ return false;
+ }
+
+ getMB(current)
+ {
+ return this._b1;
+ }
+
+ getAMDMB(current)
+ {
+ return Ice.Promise.resolve(this._b1);
+ }
+
+ getI(current)
+ {
+ return new II();
+ }
+
+ getJ(current)
+ {
+ return new JI();
+ }
+
+ getH(current)
+ {
+ return new HI();
+ }
+
+ getD1(d1, current)
+ {
+ return d1;
+ }
+
+ throwEDerived(current)
+ {
+ throw new Test.EDerived(new Test.A1("a1"), new Test.A1("a2"), new Test.A1("a3"), new Test.A1("a4"));
+ }
+
+ setI(theI, current)
+ {
+ }
+
+ opBaseSeq(inS, current)
+ {
+ return [inS, inS];
+ }
+
+ getCompact(current)
+ {
+ return new Test.CompactExt();
+ }
+
+ getInnerA(current)
+ {
+ return new Test.Inner.A(this._b1);
+ }
+
+ getInnerSubA(current)
+ {
+ return new Test.Inner.Sub.A(new Test.Inner.A(this._b1));
+ }
+
+ throwInnerEx(current)
+ {
+ throw new Test.Inner.Ex("Inner::Ex");
+ }
+
+ throwInnerSubEx(current)
+ {
+ throw new Test.Inner.Sub.Ex("Inner::Sub::Ex");
+ }
+
+ shutdown(current)
+ {
+ current.adapter.getCommunicator().shutdown();
+ }
+ }
+
+ exports.InitialI = InitialI;
+}
+(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/objects/Server.js b/js/test/Ice/objects/Server.js
new file mode 100644
index 00000000000..b15a4cde8fc
--- /dev/null
+++ b/js/test/Ice/objects/Server.js
@@ -0,0 +1,58 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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.
+//
+// **********************************************************************
+
+(function(module, require, exports)
+{
+ var Ice = require("ice").Ice;
+ var Test = require("Test").Test;
+ var InitialI = require("InitialI").InitialI;
+
+ class UnexpectedObjectExceptionTestI extends Test.UnexpectedObjectExceptionTest
+ {
+ op(current)
+ {
+ return new Test.AlsoEmpty();
+ }
+ };
+
+ var run = function(out, id, ready)
+ {
+ id.properties.setProperty("Ice.Warn.Dispatch", "0");
+ var communicator = Ice.initialize(id);
+ var adapter;
+ var echo = Test.EchoPrx.uncheckedCast(communicator.stringToProxy("__echo:default -p 12010"));
+ return Ice.Promise.try(() =>
+ {
+ return communicator.createObjectAdapter("");
+ }
+ ).then(adpt =>
+ {
+ adapter = adpt;
+ adapter.add(new InitialI(communicator), Ice.stringToIdentity("initial"));
+ adapter.add(new UnexpectedObjectExceptionTestI(), Ice.stringToIdentity("uoet"));
+ return echo.setConnection();
+ }
+ ).then(() =>
+ {
+ echo.ice_getCachedConnection().setAdapter(adapter);
+ adapter.activate();
+ ready.resolve();
+ return communicator.waitForShutdown();
+ }
+ ).then(() =>
+ {
+ return echo.shutdown();
+ }
+ ).finally(() => communicator.destroy());
+ };
+ exports._server = run;
+}
+(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/objects/Test.ice b/js/test/Ice/objects/Test.ice
index b49ecf6f887..3bc810f5848 100644
--- a/js/test/Ice/objects/Test.ice
+++ b/js/test/Ice/objects/Test.ice
@@ -167,7 +167,12 @@ exception Ex
};
-class Initial
+class Recursive
+{
+ Recursive v;
+};
+
+interface Initial
{
void shutdown();
B getB1();
@@ -177,6 +182,9 @@ class Initial
E getE();
F getF();
+ void setRecursive(Recursive p);
+ bool supportsClassGraphDepthMax();
+
["marshaled-result"] B getMB();
["amd", "marshaled-result"] B getAMDMB();
@@ -255,4 +263,10 @@ struct STwoMembers
dictionary<int, COneMember> DOneMember;
dictionary<int, CTwoMembers> DTwoMembers;
+interface Echo
+{
+ void setConnection();
+ void shutdown();
+};
+
};
diff --git a/js/test/Ice/operations/AMDMyDerivedClassI.js b/js/test/Ice/operations/AMDMyDerivedClassI.js
index 54f969cfc61..e62488edd95 100644
--- a/js/test/Ice/operations/AMDMyDerivedClassI.js
+++ b/js/test/Ice/operations/AMDMyDerivedClassI.js
@@ -25,10 +25,11 @@
//
// Override the Object "pseudo" operations to verify the operation mode.
//
- constructor()
+ constructor(endpoints)
{
super();
this._opByteSOnewayCount = 0;
+ this._endpoints = endpoints;
}
ice_isA(id, current)
@@ -154,7 +155,7 @@
var p3 = Test.MyClassPrx.uncheckedCast(
current.adapter.createProxy(Ice.stringToIdentity("noSuchIdentity")));
var r = Test.MyClassPrx.uncheckedCast(current.adapter.createProxy(current.id));
- return Promise.resolve([r, p2, p3]);
+ return Promise.resolve([r.ice_endpoints(this._endpoints), p2, p3.ice_endpoints(this._endpoints)]);
}
opMyEnum(p1, current)
@@ -490,6 +491,11 @@
Test.su0, Test.su1, Test.su2]);
}
+ opWStringLiterals(current)
+ {
+ return this.opStringLiterals(current);
+ }
+
opMStruct1(current)
{
return Promise.resolve(new Test.Structure());
diff --git a/js/test/Ice/operations/ClientBidir.js b/js/test/Ice/operations/ClientBidir.js
deleted file mode 100644
index 5aaa3775a37..00000000000
--- a/js/test/Ice/operations/ClientBidir.js
+++ /dev/null
@@ -1,68 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2017 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.
-//
-// **********************************************************************
-
-(function(module, require, exports)
-{
- var Ice = require("ice").Ice;
- var Test = require("Test").Test;
- var MyDerivedClassI = require("MyDerivedClassI").MyDerivedClassI;
- var AMDMyDerivedClassI = require("AMDMyDerivedClassI").AMDMyDerivedClassI;
- var Client = require("Client.js");
-
- var allTests = function(out, communicator, amd)
- {
- return communicator.createObjectAdapter("").then(adapter =>
- {
- if(amd)
- {
- adapter.add(new AMDMyDerivedClassI(), Ice.stringToIdentity("test"));
- }
- else
- {
- adapter.add(new MyDerivedClassI(), Ice.stringToIdentity("test"));
- }
- var base = communicator.stringToProxy("test:default -p 12010");
- return base.ice_getConnection().then(conn =>
- {
- conn.setAdapter(adapter);
- return Client._clientAllTests(out, communicator, Test, true);
- });
- });
- };
-
- var run = function(out, id)
- {
- id.properties.setProperty("Ice.BatchAutoFlushSize", "100");
- var communicator = Ice.initialize(id);
- return Ice.Promise.try(() =>
- {
- out.writeLine("testing bidir callbacks with synchronous dispatch...");
- return allTests(out, communicator, false);
- }
- ).then(() => communicator.destroy()
- ).then(() =>
- {
- communicator = Ice.initialize(id);
- out.writeLine("testing bidir callbacks with asynchronous dispatch...");
- return allTests(out, communicator, true);
- }
- ).then(() => communicator.destroy()
- ).then(() =>
- {
- communicator = Ice.initialize(id);
- return Test.EchoPrx.checkedCast(communicator.stringToProxy("__echo:default -p 12010"));
- }
- ).then(prx => prx.shutdown()
- ).finally(() => communicator.destroy());
- };
- exports._testBidir = run;
-}
-(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
- typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
- typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/operations/MyDerivedClassI.js b/js/test/Ice/operations/MyDerivedClassI.js
index dcb945ef8cb..f550f28f574 100644
--- a/js/test/Ice/operations/MyDerivedClassI.js
+++ b/js/test/Ice/operations/MyDerivedClassI.js
@@ -25,10 +25,11 @@
//
// Override the Object "pseudo" operations to verify the operation mode.
//
- constructor()
+ constructor(endpoints)
{
super();
this._opByteSOnewayCount = 0;
+ this._endpoints = endpoints;
}
ice_isA(id, current)
@@ -152,7 +153,7 @@
var p3 = Test.MyClassPrx.uncheckedCast(
current.adapter.createProxy(Ice.stringToIdentity("noSuchIdentity")));
var r = Test.MyClassPrx.uncheckedCast(current.adapter.createProxy(current.id));
- return [r, p2, p3];
+ return [r.ice_endpoints(this._endpoints), p2, p3.ice_endpoints(this._endpoints)];
}
opMyEnum(p1, current)
@@ -483,6 +484,11 @@
Test.su0, Test.su1, Test.su2];
}
+ opWStringLiterals(current)
+ {
+ return this.opStringLiterals(current);
+ }
+
opMStruct1(current)
{
return new Test.Structure();
diff --git a/js/test/Ice/operations/Server.js b/js/test/Ice/operations/Server.js
new file mode 100644
index 00000000000..e1d21e10495
--- /dev/null
+++ b/js/test/Ice/operations/Server.js
@@ -0,0 +1,49 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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.
+//
+// **********************************************************************
+
+(function(module, require, exports)
+{
+ var Ice = require("ice").Ice;
+ var Test = require("Test").Test;
+ var MyDerivedClassI = require("MyDerivedClassI").MyDerivedClassI;
+
+ var run = function(out, id, ready)
+ {
+ id.properties.setProperty("Ice.BatchAutoFlushSize", "100");
+ var communicator = Ice.initialize(id);
+ var adapter;
+ var echo = Test.EchoPrx.uncheckedCast(communicator.stringToProxy("__echo:default -p 12010"));
+ return Ice.Promise.try(() =>
+ {
+ return communicator.createObjectAdapter("");
+ }
+ ).then(adpt =>
+ {
+ adapter = adpt;
+ adapter.add(new MyDerivedClassI(echo.ice_getEndpoints()), Ice.stringToIdentity("test"));
+ return echo.setConnection();
+ }
+ ).then(() =>
+ {
+ echo.ice_getCachedConnection().setAdapter(adapter);
+ adapter.activate();
+ ready.resolve();
+ return communicator.waitForShutdown();
+ }
+ ).then(() =>
+ {
+ return echo.shutdown();
+ }
+ ).finally(() => communicator.destroy());
+ };
+ exports._server = run;
+}
+(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/operations/ServerAMD.js b/js/test/Ice/operations/ServerAMD.js
new file mode 100644
index 00000000000..60b87b2f8de
--- /dev/null
+++ b/js/test/Ice/operations/ServerAMD.js
@@ -0,0 +1,49 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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.
+//
+// **********************************************************************
+
+(function(module, require, exports)
+{
+ var Ice = require("ice").Ice;
+ var Test = require("Test").Test;
+ var AMDMyDerivedClassI = require("AMDMyDerivedClassI").AMDMyDerivedClassI;
+
+ var run = function(out, id, ready)
+ {
+ id.properties.setProperty("Ice.BatchAutoFlushSize", "100");
+ var communicator = Ice.initialize(id);
+ var adapter;
+ var echo = Test.EchoPrx.uncheckedCast(communicator.stringToProxy("__echo:default -p 12010"));
+ return Ice.Promise.try(() =>
+ {
+ return communicator.createObjectAdapter("");
+ }
+ ).then(adpt =>
+ {
+ adapter = adpt;
+ adapter.add(new AMDMyDerivedClassI(echo.ice_getEndpoints()), Ice.stringToIdentity("test"));
+ return echo.setConnection();
+ }
+ ).then(() =>
+ {
+ echo.ice_getCachedConnection().setAdapter(adapter);
+ adapter.activate();
+ ready.resolve();
+ return communicator.waitForShutdown();
+ }
+ ).then(() =>
+ {
+ return echo.shutdown();
+ }
+ ).finally(() => communicator.destroy());
+ };
+ exports._serveramd = run;
+}
+(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/operations/Test.ice b/js/test/Ice/operations/Test.ice
index 7899646dcfd..c9056b5c581 100644
--- a/js/test/Ice/operations/Test.ice
+++ b/js/test/Ice/operations/Test.ice
@@ -43,6 +43,7 @@ sequence<long> LongS;
sequence<float> FloatS;
sequence<double> DoubleS;
sequence<string> StringS;
+sequence<["cpp:type:wstring"]string> WStringS;
sequence<MyEnum> MyEnumS;
sequence<MyClass*> MyClassS;
@@ -248,6 +249,7 @@ interface MyClass
ByteBoolD opByteBoolD2(ByteBoolD byteBoolD);
StringS opStringLiterals();
+ WStringS opWStringLiterals();
["marshaled-result"] Structure opMStruct1();
["marshaled-result"] Structure opMStruct2(Structure p1, out Structure p2);
@@ -282,6 +284,7 @@ interface MyDerivedClass extends MyClass
interface Echo
{
+ void setConnection();
void startBatch();
void flushBatch();
void shutdown();
diff --git a/js/test/Ice/optional/AMDInitialI.js b/js/test/Ice/optional/AMDInitialI.js
index 9a5706f10ca..7b90fa13697 100644
--- a/js/test/Ice/optional/AMDInitialI.js
+++ b/js/test/Ice/optional/AMDInitialI.js
@@ -337,6 +337,11 @@
return Promise.resolve(false);
}
+ supportsCppStringView(current)
+ {
+ return false;
+ }
+
supportsCsharpSerializable(current)
{
return Promise.resolve(false);
diff --git a/js/test/Ice/optional/Client.js b/js/test/Ice/optional/Client.js
index dd45a676ed6..0847fb98194 100644
--- a/js/test/Ice/optional/Client.js
+++ b/js/test/Ice/optional/Client.js
@@ -319,6 +319,15 @@
}
).then(() =>
{
+ var recursive1 = [new Test.Recursive()];
+ var recursive2 = [new Test.Recursive()];
+ recursive1[0].value = recursive2;
+ var outer = new Test.Recursive();
+ outer.value = recursive1;
+ initial.pingPong(outer);
+ }
+ ).then(() =>
+ {
var g = new Test.G();
g.gg1Opt = new Test.G1("gg1Opt");
g.gg2 = new Test.G2(new Ice.Long(0, 10));
diff --git a/js/test/Ice/optional/ClientBidir.js b/js/test/Ice/optional/ClientBidir.js
deleted file mode 100644
index d61abfeb8af..00000000000
--- a/js/test/Ice/optional/ClientBidir.js
+++ /dev/null
@@ -1,82 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2017 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.
-//
-// **********************************************************************
-
-(function(module, require, exports)
-{
- var Ice = require("ice").Ice;
- var Test = require("Test").Test;
- var InitialI = require("InitialI").InitialI;
- var AMDInitialI = require("AMDInitialI").AMDInitialI;
- var Client = require("Client");
-
- var ArrayUtil = Ice.ArrayUtil;
-
- var allTests = function(out, communicator, amd)
- {
- var base;
- return Ice.Promise.try(() =>
- {
- base = communicator.stringToProxy("initial:default -p 12010");
- return communicator.createObjectAdapter("");
- }
- ).then(adapter =>
- {
- if(amd)
- {
- adapter.add(new AMDInitialI(), Ice.stringToIdentity("initial"));
- }
- else
- {
- adapter.add(new InitialI(), Ice.stringToIdentity("initial"));
- }
- return base.ice_getConnection().then(conn =>
- {
- conn.setAdapter(adapter);
- return Client._clientAllTests(out, communicator, Test);
- });
- });
- };
-
- var run = function(out, id)
- {
- var communicator = null;
- return Ice.Promise.try(() =>
- {
- communicator = Ice.initialize(id);
- out.writeLine("testing bidir callbacks with synchronous dispatch...");
- return allTests(out, communicator, false);
- }
- ).then(() => communicator.destroy()
- ).then(() =>
- {
- communicator = Ice.initialize(id);
- out.writeLine("testing bidir callbacks with asynchronous dispatch...");
- return allTests(out, communicator, true);
- }
- ).then(() => communicator.destroy()
- ).then(() =>
- {
- communicator = Ice.initialize(id);
- var base = communicator.stringToProxy("__echo:default -p 12010");
- return Test.EchoPrx.checkedCast(base);
- }
- ).then(prx => prx.shutdown()
- ).finally(() =>
- {
- if(communicator)
- {
- return communicator.destroy();
- }
- });
- };
- exports._testBidir = run;
-}
-(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
- typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
- typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/optional/ClientPrivate.ice b/js/test/Ice/optional/ClientPrivate.ice
index ddb03cd4aa5..ea6072ee803 100644
--- a/js/test/Ice/optional/ClientPrivate.ice
+++ b/js/test/Ice/optional/ClientPrivate.ice
@@ -17,12 +17,16 @@ module Test
//
// The server doesn't know this class.
//
-class D extends B
-{
- string ds;
- optional(990) StringSeq seq;
- optional(1000) A ao;
-};
+// We don't define it in JavaScript to allow the cross tests to work when running
+// only the JavaScript server within the browser (which loads ClientPrivate.js for
+// the server as well)
+//
+// class D extends B
+// {
+// string ds;
+// optional(990) StringSeq seq;
+// optional(1000) A ao;
+// };
//
// This class is a hack that allows us to invoke the opClassAndUnknownOptional operation
diff --git a/js/test/Ice/optional/InitialI.js b/js/test/Ice/optional/InitialI.js
index ec7e7f6b99e..efc5ff788b7 100644
--- a/js/test/Ice/optional/InitialI.js
+++ b/js/test/Ice/optional/InitialI.js
@@ -333,6 +333,11 @@
return false;
}
+ supportsCppStringView(current)
+ {
+ return false;
+ }
+
supportsCsharpSerializable(current)
{
return false;
diff --git a/js/test/Ice/optional/Server.js b/js/test/Ice/optional/Server.js
new file mode 100644
index 00000000000..2442eaa3f09
--- /dev/null
+++ b/js/test/Ice/optional/Server.js
@@ -0,0 +1,48 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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.
+//
+// **********************************************************************
+
+(function(module, require, exports)
+{
+ var Ice = require("ice").Ice;
+ var Test = require("Test").Test;
+ var InitialI = require("InitialI").InitialI;
+
+ var run = function(out, id, ready)
+ {
+ var communicator = Ice.initialize(id);
+ var adapter;
+ var echo = Test.EchoPrx.uncheckedCast(communicator.stringToProxy("__echo:default -p 12010"));
+ return Ice.Promise.try(() =>
+ {
+ return communicator.createObjectAdapter("");
+ }
+ ).then(adpt =>
+ {
+ adapter = adpt;
+ adapter.add(new InitialI(), Ice.stringToIdentity("initial"));
+ return echo.setConnection();
+ }
+ ).then(() =>
+ {
+ echo.ice_getCachedConnection().setAdapter(adapter);
+ adapter.activate();
+ ready.resolve();
+ return communicator.waitForShutdown();
+ }
+ ).then(() =>
+ {
+ return echo.shutdown();
+ }
+ ).finally(() => communicator.destroy());
+ };
+ exports._server = run;
+}
+(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/optional/ServerAMD.js b/js/test/Ice/optional/ServerAMD.js
new file mode 100644
index 00000000000..86779fd2d76
--- /dev/null
+++ b/js/test/Ice/optional/ServerAMD.js
@@ -0,0 +1,49 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2017 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.
+//
+// **********************************************************************
+
+(function(module, require, exports)
+{
+ var Ice = require("ice").Ice;
+ var Test = require("Test").Test;
+ var AMDInitialI = require("AMDInitialI").AMDInitialI;
+
+
+ var run = function(out, id, ready)
+ {
+ var communicator = Ice.initialize(id);
+ var adapter;
+ var echo = Test.EchoPrx.uncheckedCast(communicator.stringToProxy("__echo:default -p 12010"));
+ return Ice.Promise.try(() =>
+ {
+ return communicator.createObjectAdapter("");
+ }
+ ).then(adpt =>
+ {
+ adapter = adpt;
+ adapter.add(new AMDInitialI(), Ice.stringToIdentity("initial"));
+ return echo.setConnection();
+ }
+ ).then(() =>
+ {
+ echo.ice_getCachedConnection().setAdapter(adapter);
+ adapter.activate();
+ ready.resolve();
+ return communicator.waitForShutdown();
+ }
+ ).then(() =>
+ {
+ return echo.shutdown();
+ }
+ ).finally(() => communicator.destroy());
+ };
+ exports._serveramd = run;
+}
+(typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? module : undefined,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? require : this.Ice._require,
+ typeof(global) !== "undefined" && typeof(global.process) !== "undefined" ? exports : this));
diff --git a/js/test/Ice/optional/Test.ice b/js/test/Ice/optional/Test.ice
index 70262e8cd6f..4c206934991 100644
--- a/js/test/Ice/optional/Test.ice
+++ b/js/test/Ice/optional/Test.ice
@@ -189,6 +189,14 @@ class G
G1 gg1;
};
+class Recursive;
+sequence<Recursive> RecursiveSeq;
+
+class Recursive
+{
+ optional(0) RecursiveSeq value;
+};
+
interface Initial
{
void shutdown();
@@ -298,11 +306,14 @@ interface Initial
bool supportsCsharpSerializable();
+ bool supportsCppStringView();
+
bool supportsNullOptional();
};
interface Echo
{
+ void setConnection();
void startBatch();
void flushBatch();
void shutdown();
diff --git a/objective-c/test/Ice/exceptions/AllTests.m b/objective-c/test/Ice/exceptions/AllTests.m
index 1ca917c2439..c65792c71e3 100644
--- a/objective-c/test/Ice/exceptions/AllTests.m
+++ b/objective-c/test/Ice/exceptions/AllTests.m
@@ -376,31 +376,39 @@ exceptionsAllTests(id<ICECommunicator> communicator)
@catch(ICEConnectionLostException *ex)
{
}
+ @catch(ICEUnknownLocalException *ex)
+ {
+ }
@catch(NSException *ex)
{
test(false);
}
- id<TestExceptionsThrowerPrx> thrower2 =
- [TestExceptionsThrowerPrx checkedCast:[communicator stringToProxy:@"thrower:default -p 12011"]];
- @try
- {
- [thrower2 throwMemoryLimitException:[NSMutableData dataWithLength:20 * 1024 * 1024]]; // 2MB (no limits)
- }
- @catch(ICEMemoryLimitException *ex)
- {
- }
- id<TestExceptionsThrowerPrx> thrower3 =
- [TestExceptionsThrowerPrx checkedCast:[communicator stringToProxy:@"thrower:default -p 12012"]];
@try
{
- [thrower3 throwMemoryLimitException:[NSMutableData dataWithLength:1024]]; // 1KB limit
- test(NO);
+ id<TestExceptionsThrowerPrx> thrower2 =
+ [TestExceptionsThrowerPrx checkedCast:[communicator stringToProxy:@"thrower:default -p 12011"]];
+ @try
+ {
+ [thrower2 throwMemoryLimitException:[NSMutableData dataWithLength:20 * 1024 * 1024]]; // 2MB (no limits)
+ }
+ @catch(ICEMemoryLimitException *ex)
+ {
+ }
+ id<TestExceptionsThrowerPrx> thrower3 =
+ [TestExceptionsThrowerPrx checkedCast:[communicator stringToProxy:@"thrower:default -p 12012"]];
+ @try
+ {
+ [thrower3 throwMemoryLimitException:[NSMutableData dataWithLength:1024]]; // 1KB limit
+ test(NO);
+ }
+ @catch(ICEConnectionLostException *ex)
+ {
+ }
}
- @catch(ICEConnectionLostException *ex)
+ @catch(ICEConnectionRefusedException* ex)
{
}
-
tprintf("ok\n");
}
diff --git a/objective-c/test/Ice/objects/AllTests.m b/objective-c/test/Ice/objects/AllTests.m
index ae7ded112a1..cea5cc6e22a 100644
--- a/objective-c/test/Ice/objects/AllTests.m
+++ b/objective-c/test/Ice/objects/AllTests.m
@@ -242,6 +242,38 @@ objectsAllTests(id<ICECommunicator> communicator, BOOL collocated)
[initial setI:h];
tprintf("ok\n");
+ tprintf("testing recursive type... ");
+ TestObjectsRecursive* top = [TestObjectsRecursive recursive];
+ TestObjectsRecursive* p = top;
+ int depth = 0;
+ @try
+ {
+ for(; depth <= 20000; ++depth)
+ {
+ p.v = [TestObjectsRecursive 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(ICEUnknownLocalException*)
+ {
+ // Expected marshal exception from the server (max class graph depth reached)
+ test(depth == 100); // The default is 100.
+ }
+ @catch(ICEUnknownException*)
+ {
+ // Expected stack overflow from the server (Java only)
+ }
+ [initial setRecursive:[TestObjectsRecursive recursive]];
+ tprintf("ok\n");
+
tprintf("testing sequences... ");
TestObjectsMutableBaseSeq* inS = [TestObjectsMutableBaseSeq array];
TestObjectsMutableBaseSeq* outS;
diff --git a/objective-c/test/Ice/objects/Collocated.m b/objective-c/test/Ice/objects/Collocated.m
index 11c816f415f..855cf3bbd4a 100644
--- a/objective-c/test/Ice/objects/Collocated.m
+++ b/objective-c/test/Ice/objects/Collocated.m
@@ -133,6 +133,7 @@ main(int argc, char* argv[])
{
ICEInitializationData* initData = [ICEInitializationData initializationData];
initData.properties = defaultServerProperties(&argc, argv);
+ [initData.properties setProperty:@"Ice.Warn.Dispatch" value:@"0"];
#if TARGET_OS_IPHONE
initData.prefixTable_ = [NSDictionary dictionaryWithObjectsAndKeys:
@"TestObjects", @"::Test",
diff --git a/objective-c/test/Ice/objects/ObjectsTest.ice b/objective-c/test/Ice/objects/ObjectsTest.ice
index dc903444902..4feb80d45e4 100644
--- a/objective-c/test/Ice/objects/ObjectsTest.ice
+++ b/objective-c/test/Ice/objects/ObjectsTest.ice
@@ -178,6 +178,11 @@ dictionary<string, Object*> ObjectPrxDict; // For Objective-C only
dictionary<string, Base> BaseDict; // For Objective-C only
dictionary<string, Base*> BasePrxDict; // For Objective-C only
+class Recursive
+{
+ Recursive v;
+};
+
class Initial
{
void shutdown();
@@ -188,6 +193,9 @@ class Initial
E getE();
F getF();
+ void setRecursive(Recursive p);
+ bool supportsClassGraphDepthMax();
+
["marshaled-result"] B getMB();
["amd", "marshaled-result"] B getAMDMB();
diff --git a/objective-c/test/Ice/objects/Server.m b/objective-c/test/Ice/objects/Server.m
index 4f7dfd61703..5b4944e6ffd 100644
--- a/objective-c/test/Ice/objects/Server.m
+++ b/objective-c/test/Ice/objects/Server.m
@@ -81,6 +81,7 @@ main(int argc, char* argv[])
{
ICEInitializationData* initData = [ICEInitializationData initializationData];
initData.properties = defaultServerProperties(&argc, argv);
+ [initData.properties setProperty:@"Ice.Warn.Dispatch" value:@"0"];
#if TARGET_OS_IPHONE
initData.prefixTable_ = [NSDictionary dictionaryWithObjectsAndKeys:
@"TestObjects", @"::Test",
diff --git a/objective-c/test/Ice/objects/TestI.m b/objective-c/test/Ice/objects/TestI.m
index cea50b4118c..75977e5d138 100644
--- a/objective-c/test/Ice/objects/TestI.m
+++ b/objective-c/test/Ice/objects/TestI.m
@@ -192,6 +192,15 @@
return _f;
}
+-(void) setRecursive:(TestObjectsRecursive*)recursive current:(ICECurrent*)current
+{
+}
+
+-(BOOL) supportsClassGraphDepthMax:(ICECurrent*)current
+{
+ return YES;
+}
+
-(TestObjectsB*) getMB:(ICECurrent*)current
{
return _b1;
diff --git a/php/test/Ice/exceptions/Client.php b/php/test/Ice/exceptions/Client.php
index 430c985a125..8732f7eaea8 100644
--- a/php/test/Ice/exceptions/Client.php
+++ b/php/test/Ice/exceptions/Client.php
@@ -297,7 +297,8 @@ function allTests($communicator)
catch(Exception $ex)
{
$uue = $NS ? "Ice\\ConnectionLostException" : "Ice_ConnectionLostException";
- if(!($ex instanceof $uue))
+ $ule = $NS ? "Ice\\UnknownLocalException" : "Ice_UnknownLocalException";
+ if(!($ex instanceof $uue) && !($ex instanceof $ule))
{
throw $ex;
}
@@ -432,7 +433,7 @@ function allTests($communicator)
$initData = $NS ? eval("return new Ice\\InitializationData;") : eval("return new Ice_InitializationData;");
$initData->properties = $NS ? eval("return Ice\\getProperties();") : eval("return Ice_getProperties();");
$initData->properties->setProperty("Ice.MessageSizeMax", "10");
-$communicator = $NS ? eval("return Ice\\initialize(\$argv, \$initData);") :
+$communicator = $NS ? eval("return Ice\\initialize(\$argv, \$initData);") :
eval("return Ice_initialize(\$argv, \$initData);");
// This property is set by the test suite, howerver we need to override it for this test.
diff --git a/php/test/Ice/objects/Client.php b/php/test/Ice/objects/Client.php
index 40a454b92c7..64b4e824dd2 100644
--- a/php/test/Ice/objects/Client.php
+++ b/php/test/Ice/objects/Client.php
@@ -31,6 +31,7 @@ if($NS)
abstract class Test_E extends Test\E {}
abstract class Test_F extends Test\F {}
class Test_H extends Test\H {}
+ class Test_Recursive extends Test\Recursive {}
class Ice_Value extends Ice\Value {}
class Ice_InterfaceByValue extends Ice\InterfaceByValue {}
interface Ice_ObjectFactory extends Ice\ObjectFactory {}
@@ -408,6 +409,48 @@ function allTests($communicator)
test(count($retS) == 1 && count($outS) == 1);
echo "ok\n";
+ echo "testing recursive type... ";
+ flush();
+ $top = new Test_Recursive();
+ $p = $top;
+ $depth = 0;
+ try
+ {
+ while($depth <= 1000)
+ {
+ $p->v = new Test_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);
+ }
+ $depth += 1;
+ }
+ test(!$initial->supportsClassGraphDepthMax());
+ }
+ catch(Exception $ex)
+ {
+ $ule = $NS ? "Ice\\UnknownLocalException" : "Ice_UnknownLocalException";
+ $ue = $NS ? "Ice\\UnknownException" : "Ice_UnknownException";
+ if($ex instanceof $ule)
+ {
+ // Expected marshal exception from the server (max class graph depth reached)
+ }
+ else if($ex instanceof $ue)
+ {
+ // Expected stack overflow from the server (Java only)
+ }
+ else
+ {
+ throw $ex;
+ }
+ }
+ $initial->setRecursive(new Test_Recursive());
+ echo "ok\n";
+
echo "testing compact ID... ";
flush();
try
@@ -480,7 +523,7 @@ function allTests($communicator)
return $initial;
}
-$communicator = $NS ? eval("return Ice\\initialize(\$argv);") :
+$communicator = $NS ? eval("return Ice\\initialize(\$argv);") :
eval("return Ice_initialize(\$argv);");
$factory = new MyValueFactory();
$communicator->getValueFactoryManager()->add($factory, "::Test::B");
diff --git a/php/test/Ice/objects/Test.ice b/php/test/Ice/objects/Test.ice
index db1d3c67f50..05076845442 100644
--- a/php/test/Ice/objects/Test.ice
+++ b/php/test/Ice/objects/Test.ice
@@ -132,6 +132,11 @@ exception EDerived extends EBase
A1 a4;
};
+class Recursive
+{
+ Recursive v;
+};
+
interface Initial
{
void shutdown();
@@ -142,6 +147,9 @@ interface Initial
E getE();
F getF();
+ void setRecursive(Recursive p);
+ bool supportsClassGraphDepthMax();
+
["marshaled-result"] B getMB();
["amd", "marshaled-result"] B getAMDMB();
diff --git a/python/test/Ice/exceptions/AllTests.py b/python/test/Ice/exceptions/AllTests.py
index f876c844cae..fdfc2bddca6 100644
--- a/python/test/Ice/exceptions/AllTests.py
+++ b/python/test/Ice/exceptions/AllTests.py
@@ -483,6 +483,8 @@ def allTests(communicator):
test(False)
except Ice.ConnectionLostException:
pass
+ except Ice.UnknownLocalException:
+ pass
except:
test(False)
diff --git a/python/test/Ice/objects/AllTests.py b/python/test/Ice/objects/AllTests.py
index 7578f850ecf..a280939fe94 100644
--- a/python/test/Ice/objects/AllTests.py
+++ b/python/test/Ice/objects/AllTests.py
@@ -213,6 +213,31 @@ def allTests(communicator):
pass
print("ok")
+ sys.stdout.write("testing recursive type... ")
+ sys.stdout.flush()
+ top = Test.Recursive()
+ p = top;
+ depth = 0;
+ try:
+ while depth <= 1000:
+ p.v = Test.Recursive()
+ p = p.v;
+ if (depth < 10 and (depth % 10) == 0) or \
+ (depth < 1000 and (depth % 100) == 0) or \
+ (depth < 10000 and (depth % 1000) == 0) or \
+ (depth % 10000) == 0:
+ initial.setRecursive(top)
+ depth += 1
+ test(not initial.supportsClassGraphDepthMax())
+ except Ice.UnknownLocalException:
+ # Expected marshal exception from the server (max class graph depth reached)
+ pass
+ except Ice.UnknownException:
+ # Expected stack overflow from the server (Java only)
+ pass
+ initial.setRecursive(Test.Recursive())
+ print("ok")
+
sys.stdout.write("testing compact ID... ")
sys.stdout.flush()
try:
diff --git a/python/test/Ice/objects/Collocated.py b/python/test/Ice/objects/Collocated.py
index 845d56c4cea..2ee0bade6dd 100755
--- a/python/test/Ice/objects/Collocated.py
+++ b/python/test/Ice/objects/Collocated.py
@@ -32,7 +32,10 @@ def run(args, communicator):
return True
try:
- with Ice.initialize(sys.argv) as communicator:
+ initData = Ice.InitializationData()
+ initData.properties = Ice.createProperties(sys.argv)
+ initData.properties.setProperty("Ice.Warn.Dispatch", "0");
+ with Ice.initialize(sys.argv, initData) as communicator:
status = run(sys.argv, communicator)
except:
traceback.print_exc()
diff --git a/python/test/Ice/objects/Server.py b/python/test/Ice/objects/Server.py
index b4352d82b5d..40b9f273c1b 100755
--- a/python/test/Ice/objects/Server.py
+++ b/python/test/Ice/objects/Server.py
@@ -40,8 +40,11 @@ def run(args, communicator):
return True
try:
- with Ice.initialize(sys.argv) as communicator:
- status = run(sys.argv, communicator)
+ initData = Ice.InitializationData()
+ initData.properties = Ice.createProperties(sys.argv)
+ initData.properties.setProperty("Ice.Warn.Dispatch", "0");
+ with Ice.initialize(sys.argv, initData) as communicator:
+ status = run(sys.argv, communicator)
except:
traceback.print_exc()
status = False
diff --git a/python/test/Ice/objects/Test.ice b/python/test/Ice/objects/Test.ice
index e7464b00292..7d9cdba97c9 100644
--- a/python/test/Ice/objects/Test.ice
+++ b/python/test/Ice/objects/Test.ice
@@ -162,6 +162,11 @@ exception Ex
};
+class Recursive
+{
+ Recursive v;
+};
+
interface Initial
{
void shutdown();
@@ -172,6 +177,9 @@ interface Initial
E getE();
F getF();
+ void setRecursive(Recursive p);
+ bool supportsClassGraphDepthMax();
+
["marshaled-result"] B getMB();
["amd", "marshaled-result"] B getAMDMB();
diff --git a/python/test/Ice/objects/TestI.py b/python/test/Ice/objects/TestI.py
index 44d70a90d4c..8ce0c271081 100644
--- a/python/test/Ice/objects/TestI.py
+++ b/python/test/Ice/objects/TestI.py
@@ -125,6 +125,12 @@ class InitialI(Test.Initial):
def getF(self, current=None):
return self._f
+ def setRecursive(self, r, current):
+ pass
+
+ def supportsClassGraphDepthMax(self, current):
+ return True
+
def getMB(self, current):
return self._b1
diff --git a/ruby/test/Ice/exceptions/AllTests.rb b/ruby/test/Ice/exceptions/AllTests.rb
index 6fafd8367bc..3fc5166147b 100644
--- a/ruby/test/Ice/exceptions/AllTests.rb
+++ b/ruby/test/Ice/exceptions/AllTests.rb
@@ -278,6 +278,8 @@ def allTests(communicator)
test(false)
rescue Ice::ConnectionLostException
# Expected
+ rescue Ice::UnknownLocalException
+ # Expected
rescue
print $!.backtrace.join("\n")
test(false)
diff --git a/ruby/test/Ice/objects/AllTests.rb b/ruby/test/Ice/objects/AllTests.rb
index 84ac5d61363..a4d5d235ec8 100644
--- a/ruby/test/Ice/objects/AllTests.rb
+++ b/ruby/test/Ice/objects/AllTests.rb
@@ -258,6 +258,32 @@ def allTests(communicator)
test(retS.length == 1 && outS.length == 1)
puts "ok"
+ print "testing recursive type... "
+ STDOUT.flush
+ top = Test::Recursive.new
+ p = top;
+ depth = 0;
+ begin
+ while depth <= 1000
+ p.v = Test::Recursive.new
+ 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)
+ end
+ depth += 1
+ end
+ test(!initial.supportsClassGraphDepthMax())
+ rescue Ice::UnknownLocalException
+ # Expected marshal exception from the server (max class graph depth reached)
+ rescue Ice::UnknownException
+ # Expected stack overflow from the server (Java only)
+ end
+ initial.setRecursive(Test::Recursive.new)
+ puts "ok"
+
print "testing compact ID... "
STDOUT.flush
begin
diff --git a/ruby/test/Ice/objects/Test.ice b/ruby/test/Ice/objects/Test.ice
index 3708ae63297..571b20b2db4 100644
--- a/ruby/test/Ice/objects/Test.ice
+++ b/ruby/test/Ice/objects/Test.ice
@@ -132,6 +132,11 @@ exception EDerived extends EBase
A1 a4;
};
+class Recursive
+{
+ Recursive v;
+};
+
class Initial
{
void shutdown();
@@ -142,6 +147,9 @@ class Initial
E getE();
F getF();
+ void setRecursive(Recursive p);
+ bool supportsClassGraphDepthMax();
+
["marshaled-result"] B getMB();
["amd", "marshaled-result"] B getAMDMB();
diff --git a/scripts/Controller.py b/scripts/Controller.py
index 69eecfc54f6..2dce0d40dbf 100755
--- a/scripts/Controller.py
+++ b/scripts/Controller.py
@@ -130,7 +130,7 @@ class ControllerDriver(Driver):
self.current.config.parsedOptions.append(a)
setattr(self.current.config, a, v)
- class ControllerI(getServantClass("Test.Common", "Controller")):
+ class ControllerI(Test.Common.Controller):
def __init__(self, driver):
self.driver = driver
self.testcase = None
diff --git a/scripts/LocalDriver.py b/scripts/LocalDriver.py
index 8a6e4915c4b..71f8d4a4791 100644
--- a/scripts/LocalDriver.py
+++ b/scripts/LocalDriver.py
@@ -458,15 +458,16 @@ class LocalDriver(Driver):
if self.allCross and cross == current.testcase.getMapping():
continue
- # If the given mapping doesn't support server-side, skip this mapping.
- if cross and cross != cross.getServerMapping():
- continue
-
- # Skip if the mapping doesn't provide the test case.
+ # Skip if the mapping doesn't provide the test case
server = current.testcase.getServerTestCase(cross)
if not server:
continue
+ if cross and server.getMapping() != cross:
+ if not self.allCross:
+ current.writeln("skipped, no server available for `{0}' mapping".format(cross))
+ continue
+
current.writeln("[ running {0} test ]".format(current.testcase))
if not self.all:
current.config = current.config.cloneRunnable(current)
diff --git a/scripts/Util.py b/scripts/Util.py
index f2e60647a9c..878b4c8216c 100644
--- a/scripts/Util.py
+++ b/scripts/Util.py
@@ -763,21 +763,19 @@ class Mapping:
# with the mapping
return (self.getDefaultSource(f) in files) if m == self else m.hasSource(testId, f)
except KeyError:
- # Expected if the mapping doesn't support the process type (such as clientBidir)
+ # Expected if the mapping doesn't support the process type
return False
- checkClient = lambda f: checkFile(f, self.getClientMapping())
- checkServer = lambda f: checkFile(f, self.getServerMapping())
+ checkClient = lambda f: checkFile(f, self.getClientMapping(testId))
+ checkServer = lambda f: checkFile(f, self.getServerMapping(testId))
testcases = []
if checkClient("client") and checkServer("server"):
testcases.append(ClientServerTestCase())
- if checkClient("client") and checkServer("serveramd") and self.getServerMapping() == self:
+ if checkClient("client") and checkServer("serveramd") and self.getServerMapping(testId) == self:
testcases.append(ClientAMDServerTestCase())
if checkClient("client") and len(testcases) == 0:
testcases.append(ClientTestCase())
- if checkClient("clientBidir") and self.getServerMapping().hasSource("Ice/echo", "server"):
- testcases.append(ClientEchoServerTestCase())
if checkClient("collocated"):
testcases.append(CollocatedTestCase())
if len(testcases) > 0:
@@ -804,32 +802,32 @@ class Mapping:
def getDefaultSource(self, processType):
return processType
- def getDefaultProcess(self, processType, testsuite):
+ def getDefaultProcesses(self, processType, testsuite):
#
# If no server or client is explicitly set with a testcase, getDefaultProcess is called
# to figure out which process class to instantiate. Based on the processType and the testsuite
# we instantiate the right default process class.
#
if processType is None:
- return None
+ return []
elif testsuite.getId().startswith("IceUtil") or testsuite.getId().startswith("Slice"):
- return SimpleClient()
+ return [SimpleClient()]
elif testsuite.getId().startswith("IceGrid"):
if processType in ["client", "collocated"]:
- return IceGridClient()
+ return [IceGridClient()]
if processType in ["server", "serveramd"]:
- return IceGridServer()
+ return [IceGridServer()]
else:
- return Server() if processType in ["server", "serveramd"] else Client()
+ return [Server()] if processType in ["server", "serveramd"] else [Client()]
def getDefaultExe(self, processType, config):
return processType
- def getClientMapping(self):
+ def getClientMapping(self, testId=None):
# The client mapping is always the same as this mapping.
return self
- def getServerMapping(self):
+ def getServerMapping(self, testId=None):
# Can be overridden for client-only mapping that relies on another mapping for servers
return self
@@ -1208,6 +1206,18 @@ class SliceTranslator(ProcessFromBinDir, SimpleClient):
return translator
+class EchoServer(Server):
+
+ def __init__(self):
+ Server.__init__(self, mapping=Mapping.getByName("cpp"), quiet=True, waitForShutdown=False)
+
+ def getCommandLine(self, current):
+ current.push(self.mapping.findTestSuite("Ice/echo").findTestCase("server"))
+ try:
+ return Server.getCommandLine(self, current)
+ finally:
+ current.pop()
+
#
# A test case is composed of servers and clients. When run, all servers are started
# sequentially. When the servers are ready, the clients are also ran sequentially.
@@ -1263,16 +1273,14 @@ class TestCase(Runnable):
# returns the type of client to instantiate (client, collocated, etc)
#
if not self.clients:
- client = self.mapping.getDefaultProcess(self.getClientType(), testsuite)
- self.clients = [client] if client else []
+ self.clients = self.mapping.getDefaultProcesses(self.getClientType(), testsuite)
#
# If no servers are explicitly specified, we instantiate one if getServerType()
# returns the type of server to instantiate (server, serveramd, etc)
#
if not self.servers:
- server = self.mapping.getDefaultProcess(self.getServerType(), testsuite)
- self.servers = [server] if server else []
+ self.servers = self.mapping.getDefaultProcesses(self.getServerType(), testsuite)
def getOptions(self, current):
return self.options(current) if callable(self.options) else self.options
@@ -1354,11 +1362,11 @@ class TestCase(Runnable):
return None
def getServerTestCase(self, cross=None):
- testsuite = (cross or self.mapping.getServerMapping()).findTestSuite(self.testsuite)
+ testsuite = (cross or self.mapping).getServerMapping(self.testsuite.getId()).findTestSuite(self.testsuite)
return testsuite.findTestCase(self) if testsuite else None
def getClientTestCase(self):
- testsuite = self.mapping.getClientMapping().findTestSuite(self.testsuite)
+ testsuite = self.mapping.getClientMapping(self.testsuite.getId()).findTestSuite(self.testsuite)
return testsuite.findTestCase(self) if testsuite else None
def _startServerSide(self, current):
@@ -1459,20 +1467,6 @@ class ClientServerTestCase(ClientTestCase):
def getServerType(self):
return "server"
-class ClientEchoServerTestCase(ClientServerTestCase):
-
- def __init__(self, name="client/echo server", *args, **kargs):
- ClientServerTestCase.__init__(self, name, *args, **kargs)
-
- def getServerTestCase(self, cross=None):
- ts = Mapping.getByName("cpp").findTestSuite("Ice/echo")
- if ts:
- return ts.findTestCase("server")
- return None
-
- def getClientType(self):
- return "clientBidir"
-
class CollocatedTestCase(ClientTestCase):
def __init__(self, name="collocated", *args, **kargs):
@@ -2079,6 +2073,7 @@ class BrowserProcessController(RemoteProcessController):
def __init__(self, current):
RemoteProcessController.__init__(self, current, "ws -h 127.0.0.1 -p 15002:wss -h 127.0.0.1 -p 15003")
self.httpServer = None
+ self.testcase = None
try:
from selenium import webdriver
if not hasattr(webdriver, current.config.browser):
@@ -2105,7 +2100,7 @@ class BrowserProcessController(RemoteProcessController):
self.driver = getattr(webdriver, current.config.browser)()
cmd = "node -e \"require('./bin/HttpServer')()\"";
- cwd = current.testsuite.getMapping().getPath()
+ cwd = current.testcase.getMapping().getPath()
self.httpServer = Expect.Expect(cmd, cwd=cwd)
self.httpServer.expect("listening on ports")
except:
@@ -2116,26 +2111,27 @@ class BrowserProcessController(RemoteProcessController):
return str(self.driver)
def getControllerIdentity(self, current):
-
#
- # Load the controller page each time we're asked for the controller, the controller page
- # will connect to the process controller registry to register itself with this script.
+ # Load the controller page each time we're asked for the controller and if we're running
+ # another testcase, the controller page will connect to the process controller registry
+ # to register itself with this script.
#
- testsuite = ("es5/" if current.config.es5 else "") + str(current.testsuite)
- if current.config.protocol == "wss":
- protocol = "https"
- port = "9090"
- cport = "15003"
- else:
- protocol = "http"
- port = "8080"
- cport = "15002"
-
- self.driver.get("{0}://127.0.0.1:{1}/test/{2}/controller.html?port={3}&worker={4}".format(protocol,
- port,
- testsuite,
- cport,
- current.config.worker))
+ if self.testcase != current.testcase:
+ self.testcase = current.testcase
+ testsuite = ("es5/" if current.config.es5 else "") + str(current.testsuite)
+ if current.config.protocol == "wss":
+ protocol = "https"
+ port = "9090"
+ cport = "15003"
+ else:
+ protocol = "http"
+ port = "8080"
+ cport = "15002"
+ self.driver.get("{0}://127.0.0.1:{1}/test/{2}/controller.html?port={3}&worker={4}".format(protocol,
+ port,
+ testsuite,
+ cport,
+ current.config.worker))
return "Browser/ProcessController"
def destroy(self, driver):
@@ -2395,7 +2391,7 @@ class Driver:
processController = LocalProcessController
else:
processController = UWPProcessController
- elif isinstance(current.testcase.getMapping(), JavaScriptMapping) and current.config.browser:
+ elif process and isinstance(process.getMapping(current), JavaScriptMapping) and current.config.browser:
processController = BrowserProcessController
else:
processController = LocalProcessController
@@ -2764,7 +2760,7 @@ class CppBasedClientMapping(CppBasedMapping):
Mapping.loadTestSuites(self, tests, config, filters, rfilters)
self.getServerMapping().loadTestSuites(self.testsuites.keys(), config)
- def getServerMapping(self):
+ def getServerMapping(self, testId=None):
return Mapping.getByName("cpp") # By default, run clients against C++ mapping executables
def getDefaultExe(self, processType, config):
@@ -2861,8 +2857,16 @@ class JavaScriptMapping(Mapping):
Mapping.loadTestSuites(self, tests, config, filters, rfilters)
self.getServerMapping().loadTestSuites(list(self.testsuites.keys()) + ["Ice/echo"], config, filters, rfilters)
- def getServerMapping(self):
- return Mapping.getByName("cpp") # By default, run clients against C++ mapping executables
+ def getServerMapping(self, testId=None):
+ if testId and self.hasSource(testId, "server"):
+ return self
+ else:
+ return Mapping.getByName("cpp") # Run clients against C++ mapping servers if no JS server provided
+
+ def getDefaultProcesses(self, processType, testsuite):
+ if processType in ["server", "serveramd"]:
+ return [EchoServer(), Server()]
+ return Mapping.getDefaultProcesses(self, processType, testsuite)
def getCommandLine(self, current, process, exe):
if current.config.es5:
@@ -2871,7 +2875,7 @@ class JavaScriptMapping(Mapping):
return "node {0}/test/Common/run.js {1}".format(self.path, exe)
def getDefaultSource(self, processType):
- return { "client" : "Client.js", "clientBidir" : "ClientBidir.js" }[processType]
+ return { "client" : "Client.js", "serveramd" : "ServerAMD.js", "server" : "Server.js" }[processType]
def getDefaultExe(self, processType, config=None):
return self.getDefaultSource(processType).replace(".js", "")
@@ -2952,12 +2956,6 @@ def runTests(mappings=None, drivers=None):
if not drivers:
drivers = Driver.getAll()
- #
- # All mappings contains all the mappings necessary to run the tests from the given mappings. Some
- # mappings depend on other mappings for running (e.g.: Ruby needs the C++ mapping).
- #
- allMappings = list(set([m.getClientMapping() for m in mappings] + [m.getServerMapping() for m in mappings]))
-
def usage():
print("Usage: " + sys.argv[0] + " [options] [tests]")
print("")
@@ -2969,7 +2967,7 @@ def runTests(mappings=None, drivers=None):
driver.usage()
Mapping.Config.commonUsage()
- for mapping in allMappings:
+ for mapping in Mapping.getAll():
mapping.Config.usage()
print("")
@@ -3001,7 +2999,7 @@ def runTests(mappings=None, drivers=None):
# python mapping because we might use the local IcePy build to initialize a communicator).
#
configs = {}
- for mapping in allMappings + driver.getMappings() + [Mapping.getByName("python")]:
+ for mapping in Mapping.getAll():
if mapping not in configs:
configs[mapping] = mapping.createConfig(opts[:])
diff --git a/scripts/tests/Ice/exceptions.py b/scripts/tests/Ice/exceptions.py
index a4d2fc1a2a0..c0b5cabe5df 100644
--- a/scripts/tests/Ice/exceptions.py
+++ b/scripts/tests/Ice/exceptions.py
@@ -21,14 +21,6 @@ if Mapping.getByPath(__name__).hasSource("Ice/exceptions", "serveramd"):
ClientAMDServerTestCase("client/amd server with 1.0 encoding", props={ "Ice.Default.EncodingVersion" : "1.0"}),
]
-# If the mapping has bidir clients, also run with the bidir clients.
-if Mapping.getByPath(__name__).getClientMapping().hasSource("Ice/exceptions", "clientBidir"):
- testcases += [
- ClientEchoServerTestCase("client/echo server with compact format"),
- ClientEchoServerTestCase("client/echo server with sliced format", props={"Ice.Default.SlicedFormat" : True}),
- ClientEchoServerTestCase("client/echo server with 1.0 encoding", props={"Ice.Default.EncodingVersion" : "1.0"}),
- ]
-
if Mapping.getByPath(__name__).hasSource("Ice/exceptions", "collocated"):
testcases += [ CollocatedTestCase() ]
diff --git a/scripts/tests/Ice/objects.py b/scripts/tests/Ice/objects.py
index 3e77deee0a8..8f9460e3a27 100644
--- a/scripts/tests/Ice/objects.py
+++ b/scripts/tests/Ice/objects.py
@@ -7,10 +7,24 @@
#
# **********************************************************************
+#
+# Use a server stack size of 512KB, this is in particular important for Java
+# servers which don't implement Ice.ClassGraphDepthMax and which could cause
+# a client stack overflow if the client stack is too small compared to the
+# Java server stack.
+#
+class ObjectClientServerTestCase(ClientServerTestCase):
+
+ def getProps(self, process, current):
+ props = ClientServerTestCase.getProps(self, process, current)
+ if isinstance(process, Server) and not isinstance(process, EchoServer):
+ props["Ice.ThreadPool.Server.StackSize"] = 512 * 1024
+ return props
+
testcases = [
- ClientServerTestCase("client/server with compact format"),
- ClientServerTestCase("client/server with sliced format", props={ "Ice.Default.SlicedFormat" : True }),
- ClientServerTestCase("client/server with 1.0 encoding", props={ "Ice.Default.EncodingVersion" : "1.0" }),
+ ObjectClientServerTestCase("client/server with compact format"),
+ ObjectClientServerTestCase("client/server with sliced format", props = {"Ice.Default.SlicedFormat" : True}),
+ ObjectClientServerTestCase("client/server with 1.0 encoding", props = {"Ice.Default.EncodingVersion" : "1.0"}),
]
if Mapping.getByPath(__name__).hasSource("Ice/objects", "collocated"):
diff --git a/scripts/tests/Ice/optional.py b/scripts/tests/Ice/optional.py
index 02c0b7d73c0..2b1d1bb97a1 100644
--- a/scripts/tests/Ice/optional.py
+++ b/scripts/tests/Ice/optional.py
@@ -20,11 +20,4 @@ if Mapping.getByPath(__name__).hasSource("Ice/optional", "serveramd"):
ClientAMDServerTestCase("client/amd server with sliced format", props={ "Ice.Default.SlicedFormat" : True }),
]
-# If the mapping has bidir clients, also run with the bidir clients.
-if Mapping.getByPath(__name__).getClientMapping().hasSource("Ice/optional", "clientBidir"):
- testcases += [
- ClientEchoServerTestCase("client/echo server with compact format"),
- ClientEchoServerTestCase("client/echo server with sliced format", props={ "Ice.Default.SlicedFormat" : True }),
- ]
-
TestSuite(__name__, testcases) \ No newline at end of file