summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose <jose@zeroc.com>2015-06-16 16:12:59 +0200
committerJose <jose@zeroc.com>2015-06-16 16:12:59 +0200
commit0fe91035e5d1f074c011a9489d9113cea8f17008 (patch)
tree5155aa107a49696407bc5c5a190899275bd7c9f6
parentFixed ICE-6594: IceGrid/replication test failure (diff)
downloadice-0fe91035e5d1f074c011a9489d9113cea8f17008.tar.bz2
ice-0fe91035e5d1f074c011a9489d9113cea8f17008.tar.xz
ice-0fe91035e5d1f074c011a9489d9113cea8f17008.zip
Fixed ICE-6602: optionals marshaling bug
-rw-r--r--cpp/src/slice2cs/Gen.cpp169
-rw-r--r--cpp/src/slice2java/Gen.cpp112
-rw-r--r--cpp/src/slice2java/Gen.h2
-rw-r--r--cpp/src/slice2js/Gen.cpp39
-rw-r--r--cpp/src/slice2js/Gen.h4
-rw-r--r--cpp/test/Ice/optional/AllTests.cpp12
-rw-r--r--cpp/test/Ice/optional/Test.ice20
-rw-r--r--cpp/test/Ice/optional/TestAMD.ice20
-rw-r--r--cpp/test/Ice/optional/TestAMDI.cpp8
-rw-r--r--cpp/test/Ice/optional/TestAMDI.h4
-rw-r--r--cpp/test/Ice/optional/TestI.cpp6
-rw-r--r--cpp/test/Ice/optional/TestI.h2
-rw-r--r--csharp/test/Ice/optional/AllTests.cs11
-rw-r--r--csharp/test/Ice/optional/Test.ice23
-rw-r--r--csharp/test/Ice/optional/TestAMD.ice20
-rw-r--r--csharp/test/Ice/optional/TestAMDI.cs5
-rw-r--r--csharp/test/Ice/optional/TestI.cs5
-rw-r--r--java/test/src/main/java/test/Ice/optional/AMDInitialI.java7
-rw-r--r--java/test/src/main/java/test/Ice/optional/AllTests.java11
-rw-r--r--java/test/src/main/java/test/Ice/optional/InitialI.java7
-rw-r--r--java/test/src/main/java/test/Ice/optional/Test.ice20
-rw-r--r--java/test/src/main/java/test/Ice/optional/TestAMD.ice20
-rw-r--r--js/test/Ice/optional/Client.js15
-rw-r--r--js/test/Ice/optional/Test.ice20
-rw-r--r--js/test/Ice/optionalBidir/AMDInitialI.js4
-rw-r--r--js/test/Ice/optionalBidir/InitialI.js4
-rw-r--r--js/test/Ice/optionalBidir/Test.ice20
-rw-r--r--js/test/Ice/optionalBidir/TestAMD.ice20
-rw-r--r--php/test/Ice/optional/Client.php16
-rw-r--r--php/test/Ice/optional/Test.ice20
-rw-r--r--python/test/Ice/optional/AllTests.py11
-rwxr-xr-xpython/test/Ice/optional/Server.py3
-rwxr-xr-xpython/test/Ice/optional/ServerAMD.py3
-rw-r--r--python/test/Ice/optional/Test.ice20
-rw-r--r--python/test/Ice/optional/TestAMD.ice20
-rw-r--r--ruby/test/Ice/optional/AllTests.rb12
-rw-r--r--ruby/test/Ice/optional/Test.ice20
37 files changed, 638 insertions, 97 deletions
diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp
index 81f83b2202e..afcb39346cc 100644
--- a/cpp/src/slice2cs/Gen.cpp
+++ b/cpp/src/slice2cs/Gen.cpp
@@ -1456,7 +1456,7 @@ Slice::CsVisitor::writeDispatchAndMarshalling(const ClassDefPtr& p, bool stream)
}
_out << eb;
- if(allClassMembers.size() != 0)
+ if(classMembers.size() != 0)
{
_out << sp;
if(!p->isInterface())
@@ -1479,14 +1479,14 @@ Slice::CsVisitor::writeDispatchAndMarshalling(const ClassDefPtr& p, bool stream)
_out << sp << nl << "internal Patcher__(string type, Ice.Object instance";
}
- if(allClassMembers.size() > 1)
+ if(classMembers.size() > 1)
{
_out << ", int member";
}
_out << ") : base(type)";
_out << sb;
_out << nl << "_instance = (" << name << ")instance;";
- if(allClassMembers.size() > 1)
+ if(classMembers.size() > 1)
{
_out << nl << "_member = member;";
}
@@ -1496,15 +1496,19 @@ Slice::CsVisitor::writeDispatchAndMarshalling(const ClassDefPtr& p, bool stream)
_out << sb;
_out << nl << "try";
_out << sb;
- if(allClassMembers.size() > 1)
+ if(classMembers.size() > 1)
{
_out << nl << "switch(_member)";
_out << sb;
}
int memberCount = 0;
- for(DataMemberList::const_iterator d = allClassMembers.begin(); d != allClassMembers.end(); ++d)
+ for(DataMemberList::const_iterator d = classMembers.begin(); d != classMembers.end(); ++d)
{
- if(allClassMembers.size() > 1)
+ if((*d)->optional())
+ {
+ continue;
+ }
+ if(classMembers.size() > 1)
{
_out.dec();
_out << nl << "case " << memberCount << ":";
@@ -1512,36 +1516,69 @@ Slice::CsVisitor::writeDispatchAndMarshalling(const ClassDefPtr& p, bool stream)
}
string memberName = fixId((*d)->name(), DotNet::ICloneable, true);
string memberType = typeToString((*d)->type(), (*d)->optional());
- if((*d)->optional())
+
+ if(ClassDeclPtr::dynamicCast((*d)->type()))
{
- if(ClassDeclPtr::dynamicCast((*d)->type()))
- {
- _out << nl << "_instance." << memberName << " = new " << memberType << "(("
- << typeToString((*d)->type()) << ")v);";
- }
- else
- {
- _out << nl << "_instance." << memberName << " = new " << memberType << "(v);";
- }
+ _out << nl << "_instance." << memberName << " = (" << memberType << ")v;";
}
else
{
- if(ClassDeclPtr::dynamicCast((*d)->type()))
+ _out << nl << "_instance." << memberName << " = v;";
+ }
+
+ if(classMembers.size() > 1)
+ {
+ _out << nl << "break;";
+ }
+ memberCount++;
+ }
+
+ for(DataMemberList::const_iterator d = optionalMembers.begin(); d != optionalMembers.end(); ++d)
+ {
+ TypePtr paramType = (*d)->type();
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(paramType);
+ if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(paramType))
+ {
+ if(classMembers.size() > 1)
{
- _out << nl << "_instance." << memberName << " = (" << memberType << ")v;";
+ _out.dec();
+ _out << nl << "case " << memberCount << ":";
+ _out.inc();
+ }
+ string memberName = fixId((*d)->name(), DotNet::ICloneable, true);
+ string memberType = typeToString((*d)->type(), (*d)->optional());
+ if((*d)->optional())
+ {
+ if(ClassDeclPtr::dynamicCast((*d)->type()))
+ {
+ _out << nl << "_instance." << memberName << " = new " << memberType << "(("
+ << typeToString((*d)->type()) << ")v);";
+ }
+ else
+ {
+ _out << nl << "_instance." << memberName << " = new " << memberType << "(v);";
+ }
}
else
{
- _out << nl << "_instance." << memberName << " = v;";
+ if(ClassDeclPtr::dynamicCast((*d)->type()))
+ {
+ _out << nl << "_instance." << memberName << " = (" << memberType << ")v;";
+ }
+ else
+ {
+ _out << nl << "_instance." << memberName << " = v;";
+ }
}
+ if(classMembers.size() > 1)
+ {
+ _out << nl << "break;";
+ }
+ memberCount++;
}
- if(allClassMembers.size() > 1)
- {
- _out << nl << "break;";
- }
- memberCount++;
}
- if(allClassMembers.size() > 1)
+
+ if(classMembers.size() > 1)
{
_out << eb;
}
@@ -1553,7 +1590,7 @@ Slice::CsVisitor::writeDispatchAndMarshalling(const ClassDefPtr& p, bool stream)
_out << eb;
_out << sp << nl << "private " << name << " _instance;";
- if(allClassMembers.size() > 1)
+ if(classMembers.size() > 1)
{
_out << nl << "private int _member;";
}
@@ -1570,7 +1607,7 @@ Slice::CsVisitor::writeDispatchAndMarshalling(const ClassDefPtr& p, bool stream)
_out << sb;
_out << nl << "is__.startReadSlice();";
int classMemberCount = static_cast<int>(allClassMembers.size() - classMembers.size());
- const bool needCustomPatcher = classMembers.size() > 1 || allClassMembers.size() > 1;
+ const bool needCustomPatcher = classMembers.size() > 1;
for(DataMemberList::const_iterator d = members.begin(); d != members.end(); ++d)
{
if(!(*d)->optional())
@@ -3516,6 +3553,9 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
DataMemberList allDataMembers = p->allDataMembers();
DataMemberList dataMembers = p->dataMembers();
+ DataMemberList allClassMembers = p->allClassDataMembers();
+ DataMemberList classMembers = p->classDataMembers();
+ DataMemberList optionalMembers = p->orderedOptionalDataMembers();
vector<string> allParamDecl;
for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
@@ -3823,8 +3863,8 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
}
_out << eb;
- DataMemberList allClassMembers = p->allClassDataMembers();
- if(allClassMembers.size() != 0)
+
+ if(classMembers.size() != 0)
{
_out << sp;
emitGeneratedCodeAttribute();
@@ -3836,14 +3876,14 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
_out << "class Patcher__ : IceInternal.Patcher";
_out << sb;
_out << sp << nl << "internal Patcher__(string type, Ice.Exception instance";
- if(allClassMembers.size() > 1)
+ if(classMembers.size() > 1)
{
_out << ", int member";
}
_out << ") : base(type)";
_out << sb;
_out << nl << "_instance = (" << name << ")instance;";
- if(allClassMembers.size() > 1)
+ if(classMembers.size() > 1)
{
_out << nl << "_member = member;";
}
@@ -3853,15 +3893,19 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
_out << sb;
_out << nl << "try";
_out << sb;
- if(allClassMembers.size() > 1)
+ if(classMembers.size() > 1)
{
_out << nl << "switch(_member)";
_out << sb;
}
int memberCount = 0;
- for(DataMemberList::const_iterator q = allClassMembers.begin(); q != allClassMembers.end(); ++q)
+ for(DataMemberList::const_iterator q = classMembers.begin(); q != classMembers.end(); ++q)
{
- if(allClassMembers.size() > 1)
+ if((*q)->optional())
+ {
+ continue;
+ }
+ if(classMembers.size() > 1)
{
_out.dec();
_out << nl << "case " << memberCount << ":";
@@ -3892,13 +3936,60 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
_out << nl << "_instance." << memberName << " = v;";
}
}
- if(allClassMembers.size() > 1)
+ if(classMembers.size() > 1)
{
_out << nl << "break;";
}
memberCount++;
}
- if(allClassMembers.size() > 1)
+
+ for(DataMemberList::const_iterator q = optionalMembers.begin(); q != optionalMembers.end(); ++q)
+ {
+
+ TypePtr paramType = (*q)->type();
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(paramType);
+ if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(paramType))
+ {
+ if(classMembers.size() > 1)
+ {
+ _out.dec();
+ _out << nl << "case " << memberCount << ":";
+ _out.inc();
+ }
+ string memberName = fixId((*q)->name(), DotNet::Exception);
+ string memberType = typeToString((*q)->type(), (*q)->optional());
+ if((*q)->optional())
+ {
+ if(ClassDeclPtr::dynamicCast((*q)->type()))
+ {
+ _out << nl << "_instance." << memberName << " = new " << memberType << "(("
+ << typeToString((*q)->type()) << ")v);";
+ }
+ else
+ {
+ _out << nl << "_instance." << memberName << " = new " << memberType << "(v);";
+ }
+ }
+ else
+ {
+ if(ClassDeclPtr::dynamicCast((*q)->type()))
+ {
+ _out << nl << "_instance." << memberName << " = (" << memberType << ")v;";
+ }
+ else
+ {
+ _out << nl << "_instance." << memberName << " = v;";
+ }
+ }
+ if(classMembers.size() > 1)
+ {
+ _out << nl << "break;";
+ }
+ memberCount++;
+ }
+ }
+
+ if(classMembers.size() > 1)
{
_out << eb;
}
@@ -3910,7 +4001,7 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
_out << eb;
_out << sp << nl << "private " << name << " _instance;";
- if(allClassMembers.size() > 1)
+ if(classMembers.size() > 1)
{
_out << nl << "private int _member;";
}
@@ -3922,9 +4013,9 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
_out << nl << "protected override void readImpl__(IceInternal.BasicStream is__)";
_out << sb;
_out << nl << "is__.startReadSlice();";
- DataMemberList classMembers = p->classDataMembers();
+
int classMemberCount = static_cast<int>(allClassMembers.size() - classMembers.size());
- const bool needCustomPatcher = classMembers.size() > 1 || allClassMembers.size() > 1;
+ const bool needCustomPatcher = classMembers.size() > 1;
for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
{
writeUnmarshalDataMember(*q, fixId((*q)->name(), DotNet::Exception), needCustomPatcher, classMemberCount);
diff --git a/cpp/src/slice2java/Gen.cpp b/cpp/src/slice2java/Gen.cpp
index 0cfbdc57c37..469a8751f5e 100644
--- a/cpp/src/slice2java/Gen.cpp
+++ b/cpp/src/slice2java/Gen.cpp
@@ -855,7 +855,8 @@ Slice::JavaVisitor::writeStreamUnmarshalDataMember(Output& out, const string& pa
}
void
-Slice::JavaVisitor::writePatcher(Output& out, const string& package, const DataMemberList& classMembers, bool stream)
+Slice::JavaVisitor::writePatcher(Output& out, const string& package, const DataMemberList& classMembers,
+ const DataMemberList& optionalMembers, bool stream)
{
out << sp << nl << "private class Patcher implements IceInternal.Patcher";
if(stream)
@@ -881,6 +882,11 @@ Slice::JavaVisitor::writePatcher(Output& out, const string& package, const DataM
int memberCount = 0;
for(DataMemberList::const_iterator d = classMembers.begin(); d != classMembers.end(); ++d)
{
+ if((*d)->optional())
+ {
+ continue;
+ }
+
BuiltinPtr b = BuiltinPtr::dynamicCast((*d)->type());
if(b)
{
@@ -902,8 +908,60 @@ Slice::JavaVisitor::writePatcher(Output& out, const string& package, const DataM
}
}
- if((*d)->optional())
+ string memberName = fixKwd((*d)->name());
+ if(b)
+ {
+ out << nl << memberName << " = v;";
+ }
+ else
+ {
+ string memberType = typeToString((*d)->type(), TypeModeMember, package);
+ out << nl << "if(v == null || v instanceof " << memberType << ")";
+ out << sb;
+ out << nl << memberName << " = (" << memberType << ")v;";
+ out << eb;
+ out << nl << "else";
+ out << sb;
+ out << nl << "IceInternal.Ex.throwUOE(type(), v);";
+ out << eb;
+ }
+
+ if(classMembers.size() > 1)
+ {
+ out << nl << "break;";
+ }
+
+ memberCount++;
+ }
+
+ for(DataMemberList::const_iterator d = optionalMembers.begin(); d != optionalMembers.end(); ++d)
+ {
+ BuiltinPtr b = BuiltinPtr::dynamicCast((*d)->type());
+ if(b && b->kind() != Builtin::KindObject)
{
+ continue;
+ }
+
+ TypePtr paramType = (*d)->type();
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(paramType);
+ if((builtin && builtin->kind() == Builtin::KindObject) || ClassDeclPtr::dynamicCast(paramType))
+ {
+
+ if(classMembers.size() > 1)
+ {
+ out.dec();
+ out << nl << "case " << memberCount << ":";
+ out.inc();
+ if(b)
+ {
+ out << nl << "__typeId = Ice.ObjectImpl.ice_staticId();";
+ }
+ else
+ {
+ out << nl << "__typeId = \"" << (*d)->type()->typeId() << "\";";
+ }
+ }
+
string capName = (*d)->name();
capName[0] = toupper(static_cast<unsigned char>(capName[0]));
@@ -923,35 +981,16 @@ Slice::JavaVisitor::writePatcher(Output& out, const string& package, const DataM
out << nl << "IceInternal.Ex.throwUOE(type(), v);";
out << eb;
}
- }
- else
- {
- string memberName = fixKwd((*d)->name());
- if(b)
+
+ if(classMembers.size() > 1)
{
- out << nl << memberName << " = v;";
+ out << nl << "break;";
}
- else
- {
- string memberType = typeToString((*d)->type(), TypeModeMember, package);
- out << nl << "if(v == null || v instanceof " << memberType << ")";
- out << sb;
- out << nl << memberName << " = (" << memberType << ")v;";
- out << eb;
- out << nl << "else";
- out << sb;
- out << nl << "IceInternal.Ex.throwUOE(type(), v);";
- out << eb;
- }
- }
- if(classMembers.size() > 1)
- {
- out << nl << "break;";
+ memberCount++;
}
-
- memberCount++;
}
+
if(classMembers.size() > 1)
{
out << eb;
@@ -1709,18 +1748,20 @@ Slice::JavaVisitor::writeDispatchAndMarshalling(Output& out, const ClassDefPtr&
}
out << eb;
+ DataMemberList classMembers = p->classDataMembers();
DataMemberList allClassMembers = p->allClassDataMembers();
- if(allClassMembers.size() != 0)
+
+ if(classMembers.size() != 0)
{
- writePatcher(out, package, allClassMembers, stream);
+ writePatcher(out, package, classMembers, optionalMembers, stream);
}
out << sp << nl << "protected void __readImpl(IceInternal.BasicStream __is)";
out << sb;
out << nl << "__is.startReadSlice();";
- DataMemberList classMembers = p->classDataMembers();
+
int classMemberCount = static_cast<int>(allClassMembers.size() - classMembers.size());
- const bool needCustomPatcher = classMembers.size() > 1 || allClassMembers.size() > 1;
+ const bool needCustomPatcher = classMembers.size() > 1;
iter = 0;
for(DataMemberList::const_iterator d = members.begin(); d != members.end(); ++d)
{
@@ -3697,18 +3738,19 @@ Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
}
out << eb;
+ DataMemberList classMembers = p->classDataMembers();
DataMemberList allClassMembers = p->allClassDataMembers();
- if(allClassMembers.size() != 0)
+
+ if(classMembers.size() != 0)
{
- writePatcher(out, package, allClassMembers, _stream);
+ writePatcher(out, package, classMembers, optionalMembers, _stream);
}
out << sp << nl << "protected void" << nl << "__readImpl(IceInternal.BasicStream __is)";
out << sb;
out << nl << "__is.startReadSlice();";
iter = 0;
- DataMemberList classMembers = p->classDataMembers();
int classMemberCount = static_cast<int>(allClassMembers.size() - classMembers.size());
- const bool needCustomPatcher = classMembers.size() > 1 || allClassMembers.size() > 1;
+ const bool needCustomPatcher = classMembers.size() > 1;
for(DataMemberList::const_iterator d = members.begin(); d != members.end(); ++d)
{
if(!(*d)->optional())
@@ -4046,7 +4088,7 @@ Slice::Gen::TypesVisitor::visitStructEnd(const StructPtr& p)
if(classMembers.size() != 0)
{
- writePatcher(out, package, classMembers, _stream);
+ writePatcher(out, package, classMembers, DataMemberList(), _stream);
}
out << sp << nl << "public void" << nl << "__read(IceInternal.BasicStream __is)";
diff --git a/cpp/src/slice2java/Gen.h b/cpp/src/slice2java/Gen.h
index e4764171406..e4def10d75e 100644
--- a/cpp/src/slice2java/Gen.h
+++ b/cpp/src/slice2java/Gen.h
@@ -86,7 +86,7 @@ protected:
//
// Generate a patcher class.
//
- void writePatcher(::IceUtilInternal::Output&, const std::string&, const DataMemberList&, bool);
+ void writePatcher(::IceUtilInternal::Output&, const std::string&, const DataMemberList&, const DataMemberList&, bool);
//
// Generate dispatch and marshalling methods for a class or interface.
diff --git a/cpp/src/slice2js/Gen.cpp b/cpp/src/slice2js/Gen.cpp
index 0f14a9be27e..a7fdc7913b2 100644
--- a/cpp/src/slice2js/Gen.cpp
+++ b/cpp/src/slice2js/Gen.cpp
@@ -170,23 +170,24 @@ Slice::JsVisitor::writeMarshalUnmarshalParams(const ParamDeclList& params, const
}
void
-Slice::JsVisitor::writeMarshalDataMembers(const DataMemberList& dataMembers)
+Slice::JsVisitor::writeMarshalDataMembers(const DataMemberList& dataMembers, const DataMemberList& optionalMembers)
{
for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
{
- if((*q)->optional())
- {
- writeOptionalMarshalUnmarshalCode(_out, (*q)->type(), "this." + fixId((*q)->name()), (*q)->tag(), true);
- }
- else
+ if(!(*q)->optional())
{
writeMarshalUnmarshalCode(_out, (*q)->type(), "this." + fixId((*q)->name()), true);
}
}
+
+ for(DataMemberList::const_iterator q = optionalMembers.begin(); q != optionalMembers.end(); ++q)
+ {
+ writeOptionalMarshalUnmarshalCode(_out, (*q)->type(), "this." + fixId((*q)->name()), (*q)->tag(), true);
+ }
}
void
-Slice::JsVisitor::writeUnmarshalDataMembers(const DataMemberList& dataMembers)
+Slice::JsVisitor::writeUnmarshalDataMembers(const DataMemberList& dataMembers, const DataMemberList& optionalMembers)
{
for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
{
@@ -199,15 +200,16 @@ Slice::JsVisitor::writeUnmarshalDataMembers(const DataMemberList& dataMembers)
for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
{
- if((*q)->optional())
- {
- writeOptionalMarshalUnmarshalCode(_out, (*q)->type(), "this." + fixId((*q)->name()), (*q)->tag(), false);
- }
- else
+ if(!(*q)->optional())
{
writeMarshalUnmarshalCode(_out, (*q)->type(), "this." + fixId((*q)->name()), false);
}
}
+
+ for(DataMemberList::const_iterator q = optionalMembers.begin(); q != optionalMembers.end(); ++q)
+ {
+ writeOptionalMarshalUnmarshalCode(_out, (*q)->type(), "this." + fixId((*q)->name()), (*q)->tag(), false);
+ }
}
void
@@ -1220,11 +1222,11 @@ Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p)
{
_out << nl << "function(__os)";
_out << sb;
- writeMarshalDataMembers(dataMembers);
+ writeMarshalDataMembers(dataMembers, optionalMembers);
_out << eb << ",";
_out << nl << "function(__is)";
_out << sb;
- writeUnmarshalDataMembers(dataMembers);
+ writeUnmarshalDataMembers(dataMembers, optionalMembers);
_out << eb << ",";
_out << nl;
}
@@ -1543,6 +1545,7 @@ Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p)
const DataMemberList allDataMembers = p->allDataMembers();
const DataMemberList dataMembers = p->dataMembers();
+ const DataMemberList optionalMembers = p->orderedOptionalDataMembers();
vector<string> allParamNames;
for(DataMemberList::const_iterator q = allDataMembers.begin(); q != allDataMembers.end(); ++q)
@@ -1584,11 +1587,11 @@ Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p)
{
_out << nl << "function(__os)";
_out << sb;
- writeMarshalDataMembers(dataMembers);
+ writeMarshalDataMembers(dataMembers, optionalMembers);
_out << eb << ",";
_out << nl << "function(__is)";
_out << sb;
- writeUnmarshalDataMembers(dataMembers);
+ writeUnmarshalDataMembers(dataMembers, optionalMembers);
_out << eb;
}
else
@@ -1653,11 +1656,11 @@ Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p)
_out << ",";
_out << nl << "function(__os)";
_out << sb;
- writeMarshalDataMembers(dataMembers);
+ writeMarshalDataMembers(dataMembers, DataMemberList());
_out << eb << ",";
_out << nl << "function(__is)";
_out << sb;
- writeUnmarshalDataMembers(dataMembers);
+ writeUnmarshalDataMembers(dataMembers, DataMemberList());
_out << eb << "," << nl << p->minWireSize() << ", " << nl << (p->isVariableLength() ? "false" : "true");
_out.dec();
_out << ");";
diff --git a/cpp/src/slice2js/Gen.h b/cpp/src/slice2js/Gen.h
index 3c9781471c7..4d17cf75a90 100644
--- a/cpp/src/slice2js/Gen.h
+++ b/cpp/src/slice2js/Gen.h
@@ -26,8 +26,8 @@ protected:
void writeMarshalUnmarshalParams(const ParamDeclList&, const OperationPtr&, bool);
void writePostUnmarshalParams(const ParamDeclList&, const OperationPtr&);
- void writeMarshalDataMembers(const DataMemberList&);
- void writeUnmarshalDataMembers(const DataMemberList&);
+ void writeMarshalDataMembers(const DataMemberList&, const DataMemberList&);
+ void writeUnmarshalDataMembers(const DataMemberList&, const DataMemberList&);
void writeInitDataMembers(const DataMemberList&, const std::string&);
virtual std::vector<std::string> getParams(const OperationPtr&);
diff --git a/cpp/test/Ice/optional/AllTests.cpp b/cpp/test/Ice/optional/AllTests.cpp
index df84e0a0fde..3e6a1560623 100644
--- a/cpp/test/Ice/optional/AllTests.cpp
+++ b/cpp/test/Ice/optional/AllTests.cpp
@@ -621,6 +621,17 @@ allTests(const Ice::CommunicatorPtr& communicator, bool)
RecursivePtr outer = new Recursive();
outer->value = recursive1;
initial->pingPong(outer);
+
+ GPtr g = new G();
+ g->gg1Opt = new G1("gg1Opt");
+ g->gg2 = new G2(10);
+ g->gg2Opt = new G2(20);
+ g->gg1 = new G1("gg1");
+ GPtr r = initial->opG(g);
+ test("gg1Opt" == r->gg1Opt.get()->a);
+ test(10 == r->gg2->a);
+ test(20 == r->gg2Opt.get()->a);
+ test("gg1" == r->gg1->a);
cout << "ok" << endl;
@@ -1857,6 +1868,5 @@ allTests(const Ice::CommunicatorPtr& communicator, bool)
}
}
cout << "ok" << endl;
-
return initial;
}
diff --git a/cpp/test/Ice/optional/Test.ice b/cpp/test/Ice/optional/Test.ice
index 117706a2525..347983434e2 100644
--- a/cpp/test/Ice/optional/Test.ice
+++ b/cpp/test/Ice/optional/Test.ice
@@ -175,6 +175,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Recursive;
sequence<Recursive> RecursiveSeq;
@@ -285,6 +303,8 @@ class Initial
void sendOptionalClass(bool req, optional(1) OneOptional o);
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/cpp/test/Ice/optional/TestAMD.ice b/cpp/test/Ice/optional/TestAMD.ice
index 73114099033..241f4072898 100644
--- a/cpp/test/Ice/optional/TestAMD.ice
+++ b/cpp/test/Ice/optional/TestAMD.ice
@@ -175,6 +175,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Recursive;
sequence<Recursive> RecursiveSeq;
@@ -286,6 +304,8 @@ class Initial
void sendOptionalClass(bool req, optional(1) OneOptional o);
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/cpp/test/Ice/optional/TestAMDI.cpp b/cpp/test/Ice/optional/TestAMDI.cpp
index 19871bdd1a3..e96934e1b38 100644
--- a/cpp/test/Ice/optional/TestAMDI.cpp
+++ b/cpp/test/Ice/optional/TestAMDI.cpp
@@ -377,6 +377,14 @@ InitialI::returnOptionalClass_async(const ::Test::AMD_Initial_returnOptionalClas
}
void
+InitialI::opG_async(const ::Test::AMD_Initial_opGPtr& cb,
+ const ::Test::GPtr& g,
+ const Ice::Current&)
+{
+ cb->ice_response(g);
+}
+
+void
InitialI::supportsRequiredParams_async(const ::Test::AMD_Initial_supportsRequiredParamsPtr& cb,
const Ice::Current&)
{
diff --git a/cpp/test/Ice/optional/TestAMDI.h b/cpp/test/Ice/optional/TestAMDI.h
index 3213c66ce62..deb0ac96a28 100644
--- a/cpp/test/Ice/optional/TestAMDI.h
+++ b/cpp/test/Ice/optional/TestAMDI.h
@@ -190,6 +190,10 @@ public:
virtual void returnOptionalClass_async(const ::Test::AMD_Initial_returnOptionalClassPtr&,
bool,
const Ice::Current&);
+
+ virtual void opG_async(const ::Test::AMD_Initial_opGPtr&,
+ const ::Test::GPtr&,
+ const Ice::Current&);
virtual void supportsRequiredParams_async(const ::Test::AMD_Initial_supportsRequiredParamsPtr&,
const Ice::Current&);
diff --git a/cpp/test/Ice/optional/TestI.cpp b/cpp/test/Ice/optional/TestI.cpp
index 2aeae5f70b3..6ecf7289a66 100644
--- a/cpp/test/Ice/optional/TestI.cpp
+++ b/cpp/test/Ice/optional/TestI.cpp
@@ -383,6 +383,12 @@ InitialI::returnOptionalClass(bool, Optional<OneOptionalPtr>& o, const Ice::Curr
o = new OneOptional(53);
}
+GPtr
+InitialI::opG(const GPtr& g, const Ice::Current&)
+{
+ return g;
+}
+
bool
InitialI::supportsRequiredParams(const Ice::Current&)
{
diff --git a/cpp/test/Ice/optional/TestI.h b/cpp/test/Ice/optional/TestI.h
index e7a1606640f..9892b218d78 100644
--- a/cpp/test/Ice/optional/TestI.h
+++ b/cpp/test/Ice/optional/TestI.h
@@ -184,6 +184,8 @@ public:
virtual void sendOptionalClass(bool, const IceUtil::Optional<Test::OneOptionalPtr>&, const Ice::Current&);
virtual void returnOptionalClass(bool, IceUtil::Optional<Test::OneOptionalPtr>&, const Ice::Current&);
+
+ virtual ::Test::GPtr opG(const ::Test::GPtr& g, const Ice::Current&);
virtual bool supportsRequiredParams(const Ice::Current&);
diff --git a/csharp/test/Ice/optional/AllTests.cs b/csharp/test/Ice/optional/AllTests.cs
index 6d36d6cebff..ec1f09527b3 100644
--- a/csharp/test/Ice/optional/AllTests.cs
+++ b/csharp/test/Ice/optional/AllTests.cs
@@ -434,6 +434,17 @@ public class AllTests : TestCommon.TestApp
outer.value = recursive1;
initial.pingPong(outer);
+ Test.G g = new Test.G();
+ g.gg1Opt = new Ice.Optional<Test.G1>(new Test.G1("gg1Opt"));
+ g.gg2 = new Test.G2(10);
+ g.gg2Opt = new Ice.Optional<Test.G2>(new Test.G2(20));
+ g.gg1 = new Test.G1("gg1");
+ g = initial.opG(g);
+ test("gg1Opt".Equals(g.gg1Opt.Value.a));
+ test(10 == g.gg2.a);
+ test(20 == g.gg2Opt.Value.a);
+ test("gg1".Equals(g.gg1.a));
+
WriteLine("ok");
Write("testing marshaling of large containers with fixed size elements... ");
diff --git a/csharp/test/Ice/optional/Test.ice b/csharp/test/Ice/optional/Test.ice
index 3bb23ee1ffa..f7ede247a9d 100644
--- a/csharp/test/Ice/optional/Test.ice
+++ b/csharp/test/Ice/optional/Test.ice
@@ -176,10 +176,29 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Recursive;
sequence<Recursive> RecursiveSeq;
-class Recursive {
+class Recursive
+{
optional(0) RecursiveSeq value;
};
@@ -263,6 +282,8 @@ class Initial
void sendOptionalClass(bool req, optional(1) OneOptional o);
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/csharp/test/Ice/optional/TestAMD.ice b/csharp/test/Ice/optional/TestAMD.ice
index 19456c8dab3..42ead625af4 100644
--- a/csharp/test/Ice/optional/TestAMD.ice
+++ b/csharp/test/Ice/optional/TestAMD.ice
@@ -176,6 +176,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Recursive;
sequence<Recursive> RecursiveSeq;
@@ -264,6 +282,8 @@ class Initial
void sendOptionalClass(bool req, optional(1) OneOptional o);
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/csharp/test/Ice/optional/TestAMDI.cs b/csharp/test/Ice/optional/TestAMDI.cs
index 8bde293aa40..00046e657da 100644
--- a/csharp/test/Ice/optional/TestAMDI.cs
+++ b/csharp/test/Ice/optional/TestAMDI.cs
@@ -254,6 +254,11 @@ public class InitialI : Test.Initial
{
cb.ice_response(new Test.OneOptional(53));
}
+
+ public override void opG_async(Test.AMD_Initial_opG cb, Test.G g, Ice.Current current)
+ {
+ cb.ice_response(g);
+ }
public override void supportsRequiredParams_async(Test.AMD_Initial_supportsRequiredParams cb, Ice.Current current)
{
diff --git a/csharp/test/Ice/optional/TestI.cs b/csharp/test/Ice/optional/TestI.cs
index 44e09fcaa92..376b729594c 100644
--- a/csharp/test/Ice/optional/TestI.cs
+++ b/csharp/test/Ice/optional/TestI.cs
@@ -291,6 +291,11 @@ public class InitialI : Test.Initial
{
o = new Test.OneOptional(53);
}
+
+ public override Test.G opG(Test.G g, Ice.Current current)
+ {
+ return g;
+ }
public override bool supportsRequiredParams(Ice.Current current)
{
diff --git a/java/test/src/main/java/test/Ice/optional/AMDInitialI.java b/java/test/src/main/java/test/Ice/optional/AMDInitialI.java
index 74657d5b5c1..f17b5ae113e 100644
--- a/java/test/src/main/java/test/Ice/optional/AMDInitialI.java
+++ b/java/test/src/main/java/test/Ice/optional/AMDInitialI.java
@@ -564,6 +564,13 @@ public final class AMDInitialI extends Initial
{
cb.ice_response(new Ice.Optional<OneOptional>(new OneOptional(53)));
}
+
+ @Override
+ public void
+ opG_async(AMD_Initial_opG cb, G g, Ice.Current current)
+ {
+ cb.ice_response(g);
+ }
@Override
public void
diff --git a/java/test/src/main/java/test/Ice/optional/AllTests.java b/java/test/src/main/java/test/Ice/optional/AllTests.java
index 16411b0bb73..423072dd6d4 100644
--- a/java/test/src/main/java/test/Ice/optional/AllTests.java
+++ b/java/test/src/main/java/test/Ice/optional/AllTests.java
@@ -405,6 +405,17 @@ public class AllTests
outer.setValue(recursive1);
initial.pingPong(outer);
+ G g = new G();
+ g.setGg1Opt(new G1("gg1Opt"));
+ g.gg2 = new G2(10);
+ g.setGg2Opt(new G2(20));
+ g.gg1 = new G1("gg1");
+ g = initial.opG(g);
+ test("gg1Opt".equals(g.getGg1Opt().a));
+ test(10 == g.gg2.a);
+ test(20 == g.getGg2Opt().a);
+ test("gg1".equals(g.gg1.a));
+
out.println("ok");
out.print("testing marshaling of large containers with fixed size elements... ");
diff --git a/java/test/src/main/java/test/Ice/optional/InitialI.java b/java/test/src/main/java/test/Ice/optional/InitialI.java
index 0996befe67f..5c913fd4f06 100644
--- a/java/test/src/main/java/test/Ice/optional/InitialI.java
+++ b/java/test/src/main/java/test/Ice/optional/InitialI.java
@@ -612,6 +612,13 @@ public final class InitialI extends Initial
{
o.set(new OneOptional(53));
}
+
+ @Override
+ public G
+ opG(G g, Ice.Current current)
+ {
+ return g;
+ }
@Override
public boolean
diff --git a/java/test/src/main/java/test/Ice/optional/Test.ice b/java/test/src/main/java/test/Ice/optional/Test.ice
index 1ab1c4935f7..02d6a35e529 100644
--- a/java/test/src/main/java/test/Ice/optional/Test.ice
+++ b/java/test/src/main/java/test/Ice/optional/Test.ice
@@ -172,6 +172,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Recursive;
sequence<Recursive> RecursiveSeq;
@@ -300,6 +318,8 @@ class Initial
["java:optional"]
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/java/test/src/main/java/test/Ice/optional/TestAMD.ice b/java/test/src/main/java/test/Ice/optional/TestAMD.ice
index f76365983dd..c1447f4b531 100644
--- a/java/test/src/main/java/test/Ice/optional/TestAMD.ice
+++ b/java/test/src/main/java/test/Ice/optional/TestAMD.ice
@@ -172,6 +172,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Recursive;
sequence<Recursive> RecursiveSeq;
@@ -301,6 +319,8 @@ class Initial
["java:optional"]
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/js/test/Ice/optional/Client.js b/js/test/Ice/optional/Client.js
index d79c795e607..2d23a42d4a4 100644
--- a/js/test/Ice/optional/Client.js
+++ b/js/test/Ice/optional/Client.js
@@ -341,6 +341,21 @@
).then(
function()
{
+ var g = new Test.G();
+ g.gg1Opt = new Test.G1("gg1Opt");
+ g.gg2 = new Test.G2(new Ice.Long(0, 10));
+ g.gg2Opt = new Test.G2(new Ice.Long(0, 20));
+ g.gg1 = new Test.G1("gg1");
+ return initial.opG(g);
+ }
+ ).then(
+ function(g)
+ {
+ test(g.gg1Opt.a == "gg1Opt");
+ test(g.gg2.a.equals(new Ice.Long(0, 10)));
+ test(g.gg2Opt.a.equals(new Ice.Long(0, 20)));
+ test(g.gg1.a == "gg1");
+
out.writeLine("ok");
out.write("testing marshaling of large containers with fixed size elements... ");
var mc = new Test.MultiOptional();
diff --git a/js/test/Ice/optional/Test.ice b/js/test/Ice/optional/Test.ice
index b6e59c7378a..a1ac4b3287e 100644
--- a/js/test/Ice/optional/Test.ice
+++ b/js/test/Ice/optional/Test.ice
@@ -171,6 +171,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Initial
{
void shutdown();
@@ -283,6 +301,8 @@ class Initial
void sendOptionalClass(bool req, optional(1) OneOptional o);
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/js/test/Ice/optionalBidir/AMDInitialI.js b/js/test/Ice/optionalBidir/AMDInitialI.js
index b11e38f4a16..41302532b24 100644
--- a/js/test/Ice/optionalBidir/AMDInitialI.js
+++ b/js/test/Ice/optionalBidir/AMDInitialI.js
@@ -355,6 +355,10 @@
{
cb.ice_response(new TestAMD.OneOptional(53));
},
+ opG_async: function(cb, g, current)
+ {
+ cb.ice_response(g);
+ },
supportsRequiredParams_async: function(cb, current)
{
cb.ice_response(false);
diff --git a/js/test/Ice/optionalBidir/InitialI.js b/js/test/Ice/optionalBidir/InitialI.js
index 010401d1998..f3d38c8c38f 100644
--- a/js/test/Ice/optionalBidir/InitialI.js
+++ b/js/test/Ice/optionalBidir/InitialI.js
@@ -348,6 +348,10 @@
sendOptionalClass: function(req, current)
{
},
+ opG: function(g, current)
+ {
+ return g
+ },
returnOptionalClass: function(req, current)
{
return new Test.OneOptional(53);
diff --git a/js/test/Ice/optionalBidir/Test.ice b/js/test/Ice/optionalBidir/Test.ice
index 32f21a97695..8ca16a73190 100644
--- a/js/test/Ice/optionalBidir/Test.ice
+++ b/js/test/Ice/optionalBidir/Test.ice
@@ -171,6 +171,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Initial
{
void shutdown();
@@ -283,6 +301,8 @@ class Initial
void sendOptionalClass(bool req, optional(1) OneOptional o);
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/js/test/Ice/optionalBidir/TestAMD.ice b/js/test/Ice/optionalBidir/TestAMD.ice
index d136826465a..0ee848d7de0 100644
--- a/js/test/Ice/optionalBidir/TestAMD.ice
+++ b/js/test/Ice/optionalBidir/TestAMD.ice
@@ -171,6 +171,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
["amd"] class Initial
{
void shutdown();
@@ -283,6 +301,8 @@ class F extends E
void sendOptionalClass(bool req, optional(1) OneOptional o);
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/php/test/Ice/optional/Client.php b/php/test/Ice/optional/Client.php
index a2567f1fec3..39666ff7b13 100644
--- a/php/test/Ice/optional/Client.php
+++ b/php/test/Ice/optional/Client.php
@@ -337,6 +337,22 @@ function allTests($communicator)
test($oo != Ice_Unset);
$initial->ice_encodingVersion($Ice_Encoding_1_0)->returnOptionalClass(true, $oo);
test($oo == Ice_Unset);
+
+
+ $gcls = $NS ? "Test\\G" : "Test_G";
+ $g1cls = $NS ? "Test\\G1" : "Test_G1";
+ $g2cls = $NS ? "Test\\G2" : "Test_G2";
+
+ $g = new $gcls;
+ $g->gg1Opt = new $g1cls("gg1Opt");
+ $g->gg2 = new $g2cls(10);
+ $g->gg2Opt = new $g2cls(20);
+ $g->gg1 = new $g1cls("gg1");
+ $r = $initial->opG($g);
+ test($r->gg1Opt->a == "gg1Opt");
+ test($r->gg2->a == 10);
+ test($r->gg2Opt->a == 20);
+ test($r->gg1->a == "gg1");
echo "ok\n";
diff --git a/php/test/Ice/optional/Test.ice b/php/test/Ice/optional/Test.ice
index 40b5727a70e..d4a93f33410 100644
--- a/php/test/Ice/optional/Test.ice
+++ b/php/test/Ice/optional/Test.ice
@@ -171,6 +171,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Initial
{
void shutdown();
@@ -251,6 +269,8 @@ class Initial
void sendOptionalClass(bool req, optional(1) OneOptional o);
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/python/test/Ice/optional/AllTests.py b/python/test/Ice/optional/AllTests.py
index 051e415e9f4..e84b06a6a2d 100644
--- a/python/test/Ice/optional/AllTests.py
+++ b/python/test/Ice/optional/AllTests.py
@@ -324,6 +324,17 @@ def allTests(communicator):
outer = Test.Recursive()
outer.value = recursive1
initial.pingPong(outer)
+
+ g = Test.G()
+ g.gg1Opt = Test.G1("gg1Opt")
+ g.gg2 = Test.G2(10)
+ g.gg2Opt = Test.G2(20)
+ g.gg1 = Test.G1("gg1")
+ r = initial.opG(g)
+ test(r.gg1Opt.a == "gg1Opt")
+ test(r.gg2.a == 10)
+ test(r.gg2Opt.a == 20)
+ test(r.gg1.a == "gg1")
print("ok")
diff --git a/python/test/Ice/optional/Server.py b/python/test/Ice/optional/Server.py
index 1533bd38b70..94e4886020d 100755
--- a/python/test/Ice/optional/Server.py
+++ b/python/test/Ice/optional/Server.py
@@ -137,6 +137,9 @@ class InitialI(Test.Initial):
def returnOptionalClass(self, req, current=None):
return Test.OneOptional(5)
+
+ def opG(self, g, current=None):
+ return g
def supportsRequiredParams(self, current=None):
return False
diff --git a/python/test/Ice/optional/ServerAMD.py b/python/test/Ice/optional/ServerAMD.py
index edf6701cb0e..ce6081e070c 100755
--- a/python/test/Ice/optional/ServerAMD.py
+++ b/python/test/Ice/optional/ServerAMD.py
@@ -138,6 +138,9 @@ class InitialI(Test.Initial):
def returnOptionalClass_async(self, cb, req, current=None):
cb.ice_response(Test.OneOptional(5))
+
+ def opG_async(self, cb, g, current=None):
+ cb.ice_response(g)
def supportsRequiredParams_async(self, cb, current=None):
cb.ice_response(False)
diff --git a/python/test/Ice/optional/Test.ice b/python/test/Ice/optional/Test.ice
index 2a3d25720b6..f404a231370 100644
--- a/python/test/Ice/optional/Test.ice
+++ b/python/test/Ice/optional/Test.ice
@@ -171,6 +171,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Recursive;
sequence<Recursive> RecursiveSeq;
@@ -258,6 +276,8 @@ class Initial
void sendOptionalClass(bool req, optional(1) OneOptional o);
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/python/test/Ice/optional/TestAMD.ice b/python/test/Ice/optional/TestAMD.ice
index cf6c62ee7f1..bb14fd5c2fa 100644
--- a/python/test/Ice/optional/TestAMD.ice
+++ b/python/test/Ice/optional/TestAMD.ice
@@ -171,6 +171,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Recursive;
sequence<Recursive> RecursiveSeq;
@@ -259,6 +277,8 @@ class Initial
void sendOptionalClass(bool req, optional(1) OneOptional o);
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();
diff --git a/ruby/test/Ice/optional/AllTests.rb b/ruby/test/Ice/optional/AllTests.rb
index 1a4990314b2..fd045400b57 100644
--- a/ruby/test/Ice/optional/AllTests.rb
+++ b/ruby/test/Ice/optional/AllTests.rb
@@ -318,6 +318,18 @@ def allTests(communicator)
outer = Test::Recursive.new
outer.value = recursive1
initial.pingPong(outer)
+
+
+ g = Test::G.new
+ g.gg1Opt = Test::G1.new("gg1Opt")
+ g.gg2 = Test::G2.new(10)
+ g.gg2Opt = Test::G2.new(20)
+ g.gg1 = Test::G1.new("gg1")
+ r = initial.opG(g)
+ test(r.gg1Opt.a == "gg1Opt")
+ test(r.gg2.a == 10)
+ test(r.gg2Opt.a == 20)
+ test(r.gg1.a == "gg1")
puts "ok"
diff --git a/ruby/test/Ice/optional/Test.ice b/ruby/test/Ice/optional/Test.ice
index 65bbbaa18e9..cbcb417aebb 100644
--- a/ruby/test/Ice/optional/Test.ice
+++ b/ruby/test/Ice/optional/Test.ice
@@ -171,6 +171,24 @@ class F extends E
optional(1) A af;
};
+class G1
+{
+ string a;
+};
+
+class G2
+{
+ long a;
+};
+
+class G
+{
+ optional(1) G1 gg1Opt;
+ G2 gg2;
+ optional(0) G2 gg2Opt;
+ G1 gg1;
+};
+
class Recursive;
sequence<Recursive> RecursiveSeq;
@@ -258,6 +276,8 @@ class Initial
void sendOptionalClass(bool req, optional(1) OneOptional o);
void returnOptionalClass(bool req, out optional(1) OneOptional o);
+
+ G opG(G g);
bool supportsRequiredParams();