diff options
526 files changed, 56161 insertions, 100 deletions
@@ -8,9 +8,16 @@ # ********************************************************************** SUBDIRS = cpp java js py rb php -CLEAN_SUBDIRS = js java py rb php cpp -DEPEND_SUBDIRS = cpp py rb php -INSTALL_SUBDIRS = cpp java py rb php js +CLEAN_SUBDIRS = js java py rb php cpp +DEPEND_SUBDIRS = cpp py rb php +INSTALL_SUBDIRS = cpp java py rb php js + +ifeq ($(shell uname),Darwin) +SUBDIRS += objc +CLEAN_SUBDIRS += objc +DEPEND_SUBDIRS += objc +INSTALL_SUBDIRS += objc +endif all:: @for subdir in $(SUBDIRS); \ diff --git a/cpp/config/Make.rules b/cpp/config/Make.rules index 40dc1c522b8..84b126c37ab 100644 --- a/cpp/config/Make.rules +++ b/cpp/config/Make.rules @@ -358,9 +358,9 @@ ifneq ($(SLICE_OBJS),) endif # -# If dependencies has non been created yet make all OBJS depend -# on all SRCS, Slice generated files will be created before C++ -# compilation starts and avoid problems with parallel make +# If dependencies haven't been created yet make all OBJS depend on all +# SRCS, Slice generated files will be created before C++ compilation +# starts. This prevents issues parallel make. # ifneq ($(OBJS),) diff --git a/cpp/include/Slice/ObjCUtil.h b/cpp/include/Slice/ObjCUtil.h new file mode 100644 index 00000000000..5432259a226 --- /dev/null +++ b/cpp/include/Slice/ObjCUtil.h @@ -0,0 +1,125 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#ifndef OBJC_UTIL_H +#define OBJC_UTIL_H + +#include <Slice/Parser.h> +#include <IceUtil/OutputUtil.h> + +namespace Slice +{ + +enum BaseType +{ + BaseTypeNone, + BaseTypeObject, + BaseTypeException +}; + +class SLICE_API ObjCGenerator : private ::IceUtil::noncopyable +{ +public: + + virtual ~ObjCGenerator() {}; + + // + // Validate all metadata in the unit with an "objc:" prefix. + // + static void validateMetaData(const UnitPtr&); + +protected: + struct ModulePrefix + { + ModulePtr m; + std::string name; + }; + + static bool addModule(const ModulePtr&, const std::string&); + static ModulePrefix modulePrefix(const ModulePtr&); + static std::string moduleName(const ModulePtr&); + static ModulePtr findModule(const ContainedPtr&, int = 0, bool = false); + static void modulePrefixError(const ModulePtr&, const std::string&); + static std::string fixId(const std::string&, int = 0, bool = false); + static std::string fixId(const ContainedPtr&, int = 0, bool = false); + static std::string fixName(const ContainedPtr&, int = 0, bool = false); + static std::string fixScoped(const ContainedPtr&, int = 0, bool = false); + static std::string typeToString(const TypePtr&); + static std::string inTypeToString(const TypePtr&, bool, bool = false, bool = false); + static std::string outTypeToString(const TypePtr&, bool, bool = false, bool = false); + static std::string typeToObjCTypeString(const TypePtr&); + static bool isValueType(const TypePtr&); + static bool isString(const TypePtr&); + static bool isClass(const TypePtr&); + static bool mapsToPointerType(const TypePtr&); + static std::string getBuiltinName(const BuiltinPtr&); + static std::string getBuiltinSelector(const BuiltinPtr&, bool); + static std::string getOptionalHelperGetter(const TypePtr&); + static std::string getOptionalStreamHelper(const TypePtr&); + static StringList splitScopedName(const std::string&); + static std::string getOptionalFormat(const TypePtr&); + + // + // Generate code to marshal or unmarshal a type + // + void writeMarshalUnmarshalCode(::IceUtilInternal::Output&, const TypePtr&, const std::string&, bool, bool) const; + void writeOptMemberMarshalUnmarshalCode(::IceUtilInternal::Output&, const TypePtr&, const std::string&, bool) const; + void writeOptParamMarshalUnmarshalCode(::IceUtilInternal::Output&, const TypePtr&, const std::string&, int, + bool) const; + +private: + + class MetaDataVisitor : public ParserVisitor + { + public: + MetaDataVisitor(); + + virtual bool visitUnitStart(const UnitPtr&); + virtual bool visitModuleStart(const ModulePtr&); + virtual void visitModuleEnd(const ModulePtr&); + virtual void visitClassDecl(const ClassDeclPtr&); + virtual bool visitClassDefStart(const ClassDefPtr&); + virtual void visitClassDefEnd(const ClassDefPtr&); + virtual bool visitExceptionStart(const ExceptionPtr&); + virtual void visitExceptionEnd(const ExceptionPtr&); + virtual bool visitStructStart(const StructPtr&); + virtual void visitStructEnd(const StructPtr&); + virtual void visitOperation(const OperationPtr&); + virtual void visitParamDecl(const ParamDeclPtr&); + virtual void visitDataMember(const DataMemberPtr&); + virtual void visitSequence(const SequencePtr&); + virtual void visitDictionary(const DictionaryPtr&); + virtual void visitEnum(const EnumPtr&); + virtual void visitConst(const ConstPtr&); + + private: + + void validate(const ContainedPtr&); + + static Slice::StringList getMetaData(const ContainedPtr&); + static void modulePrefixError(const ModulePtr&, const std::string&); + + static const std::string _objcPrefix; // "objc:" + static const std::string _msg; // "ignoring invalid metadata" + + StringSet _history; + }; + + + // + // Map of module scoped name to ModulePtr. Used to verify that objc:prefix metadata directives are consistent. + // + + typedef std::map<std::string, ModulePrefix> ModuleMap; + static ModuleMap _modules; +}; + +} + +#endif diff --git a/cpp/include/Slice/Preprocessor.h b/cpp/include/Slice/Preprocessor.h index 3ae1225a9e0..6667189aec1 100644 --- a/cpp/include/Slice/Preprocessor.h +++ b/cpp/include/Slice/Preprocessor.h @@ -39,7 +39,7 @@ public: FILE* preprocess(bool, const std::string& = ""); bool close(); - enum Language { CPlusPlus, Java, JavaXML, CSharp, Python, Ruby, PHP, JS }; + enum Language { CPlusPlus, Java, JavaXML, CSharp, Python, Ruby, PHP, JS, ObjC }; bool printMakefileDependencies(Language, const std::vector<std::string>&, const std::string& = "", const std::string& = "cpp", const std::string& = ""); diff --git a/cpp/src/Ice/Makefile b/cpp/src/Ice/Makefile index 7001e0d7a44..2f87cf2123c 100644 --- a/cpp/src/Ice/Makefile +++ b/cpp/src/Ice/Makefile @@ -54,7 +54,7 @@ SLICE_OBJS = BuiltinSequences.o \ SliceChecksumDict.o \ Version.o -OBJS = Acceptor.o \ +OBJS = Acceptor.o \ ACM.o \ Application.o \ AsyncResult.o \ diff --git a/cpp/src/Makefile b/cpp/src/Makefile index 89e7e3c423b..d9cd4c797fa 100644 --- a/cpp/src/Makefile +++ b/cpp/src/Makefile @@ -12,7 +12,7 @@ top_srcdir = .. include $(top_srcdir)/config/Make.rules ifneq ($(findstring MINGW,$(UNAME)),) - SUBDIRS = IceUtil \ + SUBDIRS = IceUtil \ Slice \ slice2cpp \ slice2rb \ @@ -20,7 +20,7 @@ ifneq ($(findstring MINGW,$(UNAME)),) IceSSL \ IceDiscovery else - SUBDIRS = IceUtil \ + SUBDIRS = IceUtil \ Slice \ slice2cpp \ slice2cs \ @@ -31,7 +31,13 @@ else slice2py \ slice2rb \ slice2html \ - slice2js \ + slice2js + +ifeq ($(UNAME),Darwin) + SUBDIRS := $(SUBDIRS) slice2objc +endif + + SUBDIRS := $(SUBDIRS) \ Ice \ IceXML \ IceSSL \ @@ -59,7 +65,7 @@ endif Slice: IceUtil -slice2cpp slice2cs slice2freeze slice2freezej slice2java slice2js slice2php slice2py slice2rb slice2html: Slice +slice2cpp slice2cs slice2freeze slice2freezej slice2java slice2js slice2php slice2py slice2rb slice2html slice2objc: Slice Ice: slice2cpp diff --git a/cpp/src/Slice/Makefile b/cpp/src/Slice/Makefile index d96009fad9e..4e816bc3ccb 100644 --- a/cpp/src/Slice/Makefile +++ b/cpp/src/Slice/Makefile @@ -22,6 +22,7 @@ OBJS = Checksum.o \ JavaUtil.o \ MD5.o \ MD5I.o \ + ObjCUtil.o \ Parser.o \ PHPUtil.o \ Preprocessor.o \ diff --git a/cpp/src/Slice/ObjCUtil.cpp b/cpp/src/Slice/ObjCUtil.cpp new file mode 100644 index 00000000000..cc3abd3b08b --- /dev/null +++ b/cpp/src/Slice/ObjCUtil.cpp @@ -0,0 +1,1204 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Slice/ObjCUtil.h> +#include <Slice/Util.h> +#include <IceUtil/Functional.h> +#include <IceUtil/StringUtil.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef _WIN32 +#include <direct.h> +#endif + +#ifndef _WIN32 +#include <unistd.h> +#endif + +using namespace std; +using namespace Slice; +using namespace IceUtil; +using namespace IceUtilInternal; + +Slice::ObjCGenerator::ModuleMap Slice::ObjCGenerator::_modules; + +static string +lookupKwd(const string& name, int baseType, bool mangleCasts = false) +{ + // + // All lists in this method *must* be kept in case-insensitive + // alphabetical order. + // + static string keywordList[] = + { + "auto", "BOOL", "break", "bycopy", "byref", "case", "char", "const", "continue", + "default", "do", "double", "else", "enum", "extern", "float", "for", "goto", + "id", "if", "IMP", "in", "inline", "inout", "int", "long", "nil", "NO", "oneway", "out", + "register", "return", "SEL", "self", "short", "signed", "sizeof", "static", "struct", "super", "switch", + "typedef", "union", "unsigned", "void", "volatile", "while", "YES" + }; + + static string nsObjectList[] = + { + "autorelease", "class", "classForCoder", "copy", "dealloc", "description", "hash", "init", "isa", + "isProxy", "mutableCopy", "release", "retain", "retainCount", "superclass", "zone" + }; + static string nsExceptionList[] = + { + "callStackReturnAddresses", "name", "raise", "reason", "reserved", "userInfo", + }; + + bool found = binary_search(&keywordList[0], + &keywordList[sizeof(keywordList) / sizeof(*keywordList)], + name, + Slice::CICompare()); + if(!found) + { + switch(baseType) + { + case BaseTypeNone: + break; + + case BaseTypeException: + found = binary_search(&nsExceptionList[0], + &nsExceptionList[sizeof(nsExceptionList) / sizeof(*nsExceptionList)], + name, + Slice::CICompare()); + if(found) + { + break; + } + + case BaseTypeObject: + found = binary_search(&nsObjectList[0], + &nsObjectList[sizeof(nsObjectList) / sizeof(*nsObjectList)], + name, + Slice::CICompare()); + break; + } + } + if(found || (mangleCasts && (name == "checkedCast" || name == "uncheckedCast"))) + { + return name + "_"; + } + return name; +} + +bool +Slice::ObjCGenerator::addModule(const ModulePtr& m, const string& name) +{ + string scoped = m->scoped(); + ModuleMap::const_iterator i = _modules.find(scoped); + if(i != _modules.end()) + { + if(i->second.name != name) + { + return false; + } + } + else + { + ModulePrefix mp; + mp.m = m; + mp.name = name; + _modules[scoped] = mp; + } + return true; +} + +Slice::ObjCGenerator::ModulePrefix +Slice::ObjCGenerator::modulePrefix(const ModulePtr& m) +{ + return _modules[m->scoped()]; +} + +string +Slice::ObjCGenerator::moduleName(const ModulePtr& m) +{ + return _modules[m->scoped()].name; +} + +ModulePtr +Slice::ObjCGenerator::findModule(const ContainedPtr& cont, int baseTypes, bool mangleCasts) +{ + ModulePtr m = ModulePtr::dynamicCast(cont); + ContainerPtr container = cont->container(); + while(container && !m) + { + ContainedPtr contained = ContainedPtr::dynamicCast(container); + container = contained->container(); + m = ModulePtr::dynamicCast(contained); + } + assert(m); + return m; +} + +// +// If the passed name is a scoped name, return the identical scoped +// name, but with all components that are Objective-C keywords +// replaced by their prefixed version; otherwise, if the passed name +// is not scoped, but an Objective-C keyword, return the prefixed +// name; otherwise, check if the name is one of the method names of +// baseTypes; if so, returned the prefixed name; otherwise, return the +// name unchanged. +// +string +Slice::ObjCGenerator::fixId(const string& name, int baseTypes, bool mangleCasts) +{ + if(name.empty()) + { + return name; + } + return lookupKwd(name, baseTypes, mangleCasts); +} + +string +Slice::ObjCGenerator::fixId(const ContainedPtr& cont, int baseTypes, bool mangleCasts) +{ + return fixId(cont->name(), baseTypes, mangleCasts); +} + +string +Slice::ObjCGenerator::fixName(const ContainedPtr& cont, int baseTypes, bool mangleCasts) +{ + return moduleName(findModule(cont, baseTypes, mangleCasts)) + cont->name(); +} + +string +Slice::ObjCGenerator::typeToString(const TypePtr& type) +{ + if(!type) + { + return "void"; + } + + static const char* builtinTable[] = + { + "ICEByte", + "BOOL", + "ICEShort", + "ICEInt", + "ICELong", + "ICEFloat", + "ICEDouble", + "NSString", + "ICEObject", + "id<ICEObjectPrx>", + "id" // Dummy--we don't support Slice local Object + }; + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + return builtinTable[builtin->kind()]; + } + + ProxyPtr proxy = ProxyPtr::dynamicCast(type); + if(proxy) + { + string mName = moduleName(findModule(proxy->_class())); + return "id<" + mName + (proxy->_class()->name()) + "Prx>"; + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + return fixName(seq); + } + + DictionaryPtr d = DictionaryPtr::dynamicCast(type); + if(d) + { + return fixName(d); + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + if(cl && cl->isInterface()) + { + return "ICEObject"; + } + + ContainedPtr contained = ContainedPtr::dynamicCast(type); + if(contained) + { + return fixName(contained); + } + + return "???"; +} + +string +Slice::ObjCGenerator::inTypeToString(const TypePtr& type, bool optional, bool autoreleasing, bool reference) +{ + string s; + if(optional) + { + s = "id"; + } + else + { + s = typeToString(type); + if(mapsToPointerType(type)) + { + s += "*"; + } + } + if(autoreleasing && !isValueType(type)) + { + s += " ICE_AUTORELEASING_QUALIFIER"; + } + if(reference) + { + s += "*"; + } + return s; +} + +string +Slice::ObjCGenerator::outTypeToString(const TypePtr& type, bool optional, bool autoreleasing, bool reference) +{ + if(!type) + { + return "void"; + } + + string s; + if(optional) + { + s = "id"; + } + else + { + SequencePtr seq = SequencePtr::dynamicCast(type); + DictionaryPtr d = DictionaryPtr::dynamicCast(type); + if(isString(type)) + { + s = "NSMutableString"; + } + else if(seq) + { + string prefix = moduleName(findModule(seq)); + s = prefix + "Mutable" + seq->name(); + } + else if(d) + { + string prefix = moduleName(findModule(d)); + s = prefix + "Mutable" + d->name(); + } + else + { + s = typeToString(type); + } + if(mapsToPointerType(type)) + { + s += "*"; + } + } + if(autoreleasing && !isValueType(type)) + { + s += " ICE_AUTORELEASING_QUALIFIER"; + } + if(reference) + { + s += "*"; + } + return s; +} + +string +Slice::ObjCGenerator::typeToObjCTypeString(const TypePtr& type) +{ + ProxyPtr proxy = ProxyPtr::dynamicCast(type); + if(proxy) + { + return moduleName(findModule(proxy->_class())) + (proxy->_class()->name()) + "Prx"; + } + else + { + return typeToString(type); + } +} + +bool +Slice::ObjCGenerator::isValueType(const TypePtr& type) +{ + if(!type) + { + return true; + } + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindString: + case Builtin::KindObject: + case Builtin::KindObjectProxy: + case Builtin::KindLocalObject: + { + return false; + break; + } + default: + { + return true; + break; + } + } + } + if(EnumPtr::dynamicCast(type)) + { + return true; + } + return false; +} + +bool +Slice::ObjCGenerator::isString(const TypePtr& type) +{ + if(!type) + { + return false; + } + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + return builtin && builtin->kind() == Builtin::KindString; +} +bool +Slice::ObjCGenerator::isClass(const TypePtr& type) +{ + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + return builtin->kind() == Builtin::KindObject; + } + return ClassDeclPtr::dynamicCast(type); +} + +bool +Slice::ObjCGenerator::mapsToPointerType(const TypePtr& type) +{ + if(isValueType(type)) + { + return false; + } + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + return builtin->kind() != Builtin::KindObjectProxy; + } + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + if(cl && cl->isInterface()) + { + return true; + } + return !ProxyPtr::dynamicCast(type); +} + +string +Slice::ObjCGenerator::getBuiltinName(const BuiltinPtr& builtin) +{ + switch(builtin->kind()) + { + case Builtin::KindByte: + { + return "Byte"; + } + case Builtin::KindBool: + { + return "Bool"; + } + case Builtin::KindShort: + { + return "Short"; + } + case Builtin::KindInt: + { + return "Int"; + } + case Builtin::KindLong: + { + return "Long"; + } + case Builtin::KindFloat: + { + return "Float"; + } + case Builtin::KindDouble: + { + return "Double"; + } + case Builtin::KindString: + { + return "String"; + } + case Builtin::KindObject: + { + return "Object"; + } + case Builtin::KindObjectProxy: + { + return "Proxy"; + } + default: + { + assert(false); + } + } + return "NO__SUCH__TYPE"; +} + +string +Slice::ObjCGenerator::getOptionalHelperGetter(const TypePtr& type) +{ + if(isValueType(type)) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + return "get" + getBuiltinName(builtin); + } + if(EnumPtr::dynamicCast(type)) + { + return "getInt"; + } + } + return "get"; +} + +// +// Split a scoped name into its components and return the components as a list of (unscoped) identifiers. +// +StringList +Slice::ObjCGenerator::splitScopedName(const string& scoped) +{ + assert(scoped[0] == ':'); + StringList ids; + string::size_type next = 0; + string::size_type pos; + while((pos = scoped.find("::", next)) != string::npos) + { + pos += 2; + if(pos != scoped.size()) + { + string::size_type endpos = scoped.find("::", pos); + if(endpos != string::npos) + { + ids.push_back(scoped.substr(pos, endpos - pos)); + } + } + next = pos; + } + if(next != scoped.size()) + { + ids.push_back(scoped.substr(next)); + } + else + { + ids.push_back(""); + } + + return ids; +} + +string +Slice::ObjCGenerator::getOptionalFormat(const TypePtr& type) +{ + BuiltinPtr bp = BuiltinPtr::dynamicCast(type); + if(bp) + { + switch(bp->kind()) + { + case Builtin::KindByte: + case Builtin::KindBool: + { + return "ICEOptionalFormatF1"; + } + case Builtin::KindShort: + { + return "ICEOptionalFormatF2"; + } + case Builtin::KindInt: + case Builtin::KindFloat: + { + return "ICEOptionalFormatF4"; + } + case Builtin::KindLong: + case Builtin::KindDouble: + { + return "ICEOptionalFormatF8"; + } + case Builtin::KindString: + { + return "ICEOptionalFormatVSize"; + } + case Builtin::KindObject: + { + return "ICEOptionalFormatClass"; + } + case Builtin::KindObjectProxy: + { + return "ICEOptionalFormatFSize"; + } + case Builtin::KindLocalObject: + { + assert(false); + break; + } + } + } + + if(EnumPtr::dynamicCast(type)) + { + return "ICEOptionalFormatSize"; + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + return seq->type()->isVariableLength() ? "ICEOptionalFormatFSize" : "ICEOptionalFormatVSize"; + } + + DictionaryPtr d = DictionaryPtr::dynamicCast(type); + if(d) + { + return (d->keyType()->isVariableLength() || d->valueType()->isVariableLength()) ? + "ICEOptionalFormatFSize" : "ICEOptionalFormatVSize"; + } + + StructPtr st = StructPtr::dynamicCast(type); + if(st) + { + return st->isVariableLength() ? "ICEOptionalFormatFSize" : "ICEOptionalFormatVSize"; + } + + if(ProxyPtr::dynamicCast(type)) + { + return "ICEOptionalFormatFSize"; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + assert(cl); + return "ICEOptionalFormatClass"; +} + +void +Slice::ObjCGenerator::writeMarshalUnmarshalCode(Output &out, const TypePtr& type, const string& param, + bool marshal, bool autoreleased) const +{ + string stream = marshal ? "os_" : "is_"; + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + + if(builtin) + { + string name; + if(builtin->kind() == Builtin::KindObject) + { + if(marshal) + { + out << nl << "[" << stream << " writeObject:" << param << "];"; + } + else + { + if(autoreleased) + { + out << nl << "[" << stream << " readObject:&" << param << "];"; + } + else + { + out << nl << "[" << stream << " newObject:&" << param << "];"; + } + } + } + else if(builtin->kind() == Builtin::KindObjectProxy) + { + if(marshal) + { + out << nl << "[" << stream << " writeProxy:" << param << "];"; + } + else + { + if(autoreleased) + { + out << nl << param << " = [" << stream << " readProxy:[ICEObjectPrx class]];"; + } + else + { + out << nl << param << " = [" << stream << " newProxy:[ICEObjectPrx class]];"; + } + } + } + else + { + if(marshal) + { + out << nl << "[" << stream << " write" << getBuiltinName(builtin) << ":" << param << "];"; + } + else + { + if(autoreleased || isValueType(builtin)) + { + out << nl << param << " = [" << stream << " read" << getBuiltinName(builtin) << "];"; + } + else + { + out << nl << param << " = [" << stream << " new" << getBuiltinName(builtin) << "];"; + } + } + } + return; + } + + ProxyPtr prx = ProxyPtr::dynamicCast(type); + if(prx) + { + if(marshal) + { + out << nl << "[" << stream << " writeProxy:(id<ICEObjectPrx>)" << param << "];"; + } + else + { + string name = moduleName(findModule(prx->_class())) + prx->_class()->name() + "Prx"; + out << nl << param << " = (id<" << name << ">)[" << stream; + if(autoreleased) + { + out << " readProxy:"; + } + else + { + out << " newProxy:"; + } + // + // We use objc_getClass to get the proxy class instead of [name class]. This is to avoid + // a warning if the proxy is forward declared. + // + if(prx->_class()->definition()) + { + out << "[" << name << " class]];"; + } + else + { + out << "objc_getClass(\"" << name << "\")];"; + } + } + return; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + if(cl) + { + if(marshal) + { + // Cast avoids warning for forward-declared classes. + out << nl << "[" << stream << " writeObject:(ICEObject*)" << param << "];"; + } + else + { + if(autoreleased) + { + out << nl << "[" << stream << " " << "readObject:(ICEObject**)&" << param; + } + else + { + out << nl << "[" << stream << " " << "newObject:(ICEObject**)&" << param; + } + + if(cl->isInterface()) + { + out << "];"; + } + else + { + string name = moduleName(findModule(cl)) + cl->name(); + if(cl->definition()) + { + out << " expectedType:[" << name << " class]];"; + } + else + { + out << " expectedType:objc_getClass(\"" << name << "\")];"; + } + } + } + return; + } + + EnumPtr en = EnumPtr::dynamicCast(type); + if(en) + { + if(marshal) + { + out << nl << "[" << stream << " writeEnumerator:" << param << " min:" << en->minValue() + << " max:" << en->maxValue() << "];"; + } + else + { + out << nl << param << " = " << "[" << stream << " readEnumerator:" << en->minValue() + << " max:" << en->maxValue() << "];"; + } + return; + } + + ContainedPtr c = ContainedPtr::dynamicCast(type); + assert(c); + string name = moduleName(findModule(c)) + c->name() + "Helper"; + if(marshal) + { + out << nl << "[" + name << " write:" << param << " stream:" << stream << "];"; + } + else + { + if(autoreleased) + { + out << nl << param << " = [" << name << " read:" << stream << "];"; + } + else + { + out << nl << param << " = [" << name << " readRetained:" << stream << "];"; + } + } +} + +void +Slice::ObjCGenerator::writeOptMemberMarshalUnmarshalCode(Output &out, const TypePtr& type, const string& param, + bool marshal) const +{ + string stream = marshal ? "os_" : "is_"; + string optionalHelper; + string helper; + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + if(builtin->kind() == Builtin::KindObjectProxy) + { + optionalHelper = "ICEVarLengthOptionalHelper"; + helper = "[ICEProxyHelper class]"; + } + else + { + writeMarshalUnmarshalCode(out, type, param, marshal, false); + return; + } + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + if(cl) + { + writeMarshalUnmarshalCode(out, type, param, marshal, false); + return; + } + + EnumPtr en = EnumPtr::dynamicCast(type); + if(en) + { + writeMarshalUnmarshalCode(out, type, param, marshal, false); + return; + } + + ProxyPtr prx = ProxyPtr::dynamicCast(type); + if(prx) + { + optionalHelper = "ICEVarLengthOptionalHelper"; + helper = "objc_getClass(\"" + moduleName(findModule(prx->_class())) + prx->_class()->name() + "PrxHelper\")"; + } + + StructPtr st = StructPtr::dynamicCast(type); + if(st) + { + if(st->isVariableLength()) + { + optionalHelper = "ICEVarLengthOptionalHelper"; + } + else + { + optionalHelper = "ICEFixedLengthOptionalHelper"; + } + helper = "[" + typeToString(st) + "Helper class]"; + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + TypePtr element = seq->type(); + if(element->isVariableLength()) + { + optionalHelper = "ICEVarLengthOptionalHelper"; + } + else if(element->minWireSize() == 1) + { + writeMarshalUnmarshalCode(out, type, param, marshal, false); + return; + } + else + { + optionalHelper = "ICEFixedSequenceOptionalHelper"; + } + helper = "[" + moduleName(findModule(seq)) + seq->name() + "Helper class]"; + } + + DictionaryPtr d = DictionaryPtr::dynamicCast(type); + if(d) + { + if(d->keyType()->isVariableLength() || d->valueType()->isVariableLength()) + { + optionalHelper = "ICEVarLengthOptionalHelper"; + } + else + { + optionalHelper = "ICEFixedDictionaryOptionalHelper"; + } + helper = "[" + moduleName(findModule(d)) + d->name() + "Helper class]"; + } + + out << nl; + if(marshal) + { + out << "[" << optionalHelper << " write:" << param << " stream:" << stream << " helper:" << helper << "];"; + } + else + { + out << param << " = [" << optionalHelper << " readRetained:" << stream << " helper:" << helper << "];"; + } + +} + +void +Slice::ObjCGenerator::writeOptParamMarshalUnmarshalCode(Output &out, const TypePtr& type, const string& param, + int tag, bool marshal) const +{ + string helper; + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + ProxyPtr proxy = ProxyPtr::dynamicCast(type); + if(builtin) + { + helper = "ICE" + getBuiltinName(builtin) + "Helper"; + } + else if(proxy) + { + helper = moduleName(findModule(proxy->_class())) + (proxy->_class()->name()) + "PrxHelper"; + } + else + { + helper = typeToString(type) + "Helper"; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + if(cl) + { + out << nl; + if(marshal) + { + out << "[" << helper << " writeOpt:" << param << " stream:os_ tag:" << tag << "];"; + } + else + { + out << "[" << helper << " readOpt:&" << param << " stream:is_ tag:" << tag << "];"; + } + return; + } + + out << nl; + if(marshal) + { + out << "[" << helper << " writeOpt:" << param << " stream:os_ tag:" << tag << "];"; + } + else + { + out << param << " = [" << helper << " readOpt:is_ tag:" << tag << "];"; + } +} + +void +Slice::ObjCGenerator::validateMetaData(const UnitPtr& u) +{ + MetaDataVisitor visitor; + u->visit(&visitor, true); +} + +const string Slice::ObjCGenerator::MetaDataVisitor::_objcPrefix = "objc:"; +const string Slice::ObjCGenerator::MetaDataVisitor::_msg = "ignoring invalid metadata"; + +Slice::ObjCGenerator::MetaDataVisitor::MetaDataVisitor() +{ +} + +bool +Slice::ObjCGenerator::MetaDataVisitor::visitUnitStart(const UnitPtr& p) +{ + // + // Validate global metadata in the top-level file and all included files. + // + StringList files = p->allFiles(); + + for(StringList::iterator q = files.begin(); q != files.end(); ++q) + { + string file = *q; + DefinitionContextPtr dc = p->findDefinitionContext(file); + assert(dc); + StringList globalMetaData = dc->getMetaData(); + int headerDir = 0; + for(StringList::const_iterator r = globalMetaData.begin(); r != globalMetaData.end(); ++r) + { + string s = *r; + if(_history.count(s) == 0) + { + if(s.find(_objcPrefix) == 0) + { + static const string objcHeaderDirPrefix = "objc:header-dir:"; + if(s.find(objcHeaderDirPrefix) == 0 && s.size() > objcHeaderDirPrefix.size()) + { + headerDir++; + if(headerDir > 1) + { + ostringstream ostr; + ostr << "ignoring invalid global metadata `" << s + << "': directive can appear only once per file"; + emitWarning(file, -1, ostr.str()); + _history.insert(s); + } + continue; + } + ostringstream ostr; + ostr << "ignoring invalid global metadata `" << s << "'"; + emitWarning(file, -1, ostr.str()); + } + _history.insert(s); + } + } + } + + return true; +} + +bool +Slice::ObjCGenerator::MetaDataVisitor::visitModuleStart(const ModulePtr& p) +{ + validate(p); + return true; +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitModuleEnd(const ModulePtr&) +{ +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p) +{ + validate(p); +} + +bool +Slice::ObjCGenerator::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + validate(p); + return true; +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitClassDefEnd(const ClassDefPtr&) +{ +} + +bool +Slice::ObjCGenerator::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p) +{ + validate(p); + return true; +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitExceptionEnd(const ExceptionPtr&) +{ +} + +bool +Slice::ObjCGenerator::MetaDataVisitor::visitStructStart(const StructPtr& p) +{ + validate(p); + return true; +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitStructEnd(const StructPtr&) +{ +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitOperation(const OperationPtr& p) +{ + if(p->hasMetaData("UserException")) + { + ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container()); + if(!cl->isLocal()) + { + ostringstream os; + os << "ignoring invalid metadata `UserException': directive applies only to local operations " + << ": warning: metadata directive `UserException' applies only to local operations " + << "but enclosing " << (cl->isInterface() ? "interface" : "class") << "`" << cl->name() + << "' is not local"; + emitWarning(p->file(), p->line(), os.str()); + } + } + validate(p); +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitParamDecl(const ParamDeclPtr& p) +{ + validate(p); +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) +{ + validate(p); +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitSequence(const SequencePtr& p) +{ + validate(p); +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitDictionary(const DictionaryPtr& p) +{ + validate(p); +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitEnum(const EnumPtr& p) +{ + validate(p); +} + +void +Slice::ObjCGenerator::MetaDataVisitor::visitConst(const ConstPtr& p) +{ + validate(p); +} + +void +Slice::ObjCGenerator::MetaDataVisitor::validate(const ContainedPtr& cont) +{ + ModulePtr m = ModulePtr::dynamicCast(cont); + if(m) + { + bool error = false; + bool foundPrefix = false; + + StringList meta = getMetaData(m); + StringList::const_iterator p; + + for(p = meta.begin(); p != meta.end(); ++p) + { + const string prefix = "prefix:"; + string name; + if(p->substr(_objcPrefix.size(), prefix.size()) == prefix) + { + foundPrefix = true; + name = trim(p->substr(_objcPrefix.size() + prefix.size())); + if(name.empty()) + { + if(_history.count(*p) == 0) + { + string file = m->definitionContext()->filename(); + ostringstream os; + os << _msg << " `" << *p << "'" << endl; + emitWarning(file, m->line(), os.str()); + _history.insert(*p); + } + error = true; + } + else + { + if(!addModule(m, name)) + { + modulePrefixError(m, *p); + } + } + } + else + { + if(_history.count(*p) == 0) + { + string file = m->definitionContext()->filename(); + ostringstream os; + os << _msg << " `" << *p << "'" << endl; + emitWarning(file, m->line(), os.str()); + _history.insert(*p); + } + error = true; + } + } + + if(!error && !foundPrefix) + { + StringList names = splitScopedName(m->scoped()); + string name; + for(StringList::const_iterator i = names.begin(); i != names.end(); ++i) + { + name += *i; + } + if(!addModule(m, name)) + { + modulePrefixError(m, ""); + } + } + } +} + +StringList +Slice::ObjCGenerator::MetaDataVisitor::getMetaData(const ContainedPtr& cont) +{ + StringList ret; + StringList localMetaData = cont->getMetaData(); + StringList::const_iterator p; + + for(p = localMetaData.begin(); p != localMetaData.end(); ++p) + { + if(p->find(_objcPrefix) != string::npos) + { + ret.push_back(*p); + } + } + + return ret; +} + +void +Slice::ObjCGenerator::MetaDataVisitor::modulePrefixError(const ModulePtr& m, const string& metadata) +{ + string file = m->definitionContext()->filename(); + string line = m->line(); + ModulePrefix mp = modulePrefix(m); + string old_file = mp.m->definitionContext()->filename(); + string old_line = mp.m->line(); + ostringstream os; + if(!metadata.empty()) + { + os << _msg << " `" << metadata << "': "; + } + os << "inconsistent module prefix previously defined "; + if(old_file != file) + { + os << "in " << old_file << ":"; + } + else + { + os << "at line "; + } + os << line; + os << " as `" << mp.name << "'" << endl; + emitWarning(file, line, os.str()); +} + diff --git a/cpp/src/Slice/Preprocessor.cpp b/cpp/src/Slice/Preprocessor.cpp index a5593065d1c..30b6d5c6948 100644 --- a/cpp/src/Slice/Preprocessor.cpp +++ b/cpp/src/Slice/Preprocessor.cpp @@ -622,6 +622,16 @@ Slice::Preprocessor::printMakefileDependencies(Language lang, const vector<strin } break; } + case ObjC: + { + string::size_type pos = result.find(suffix); + if(pos != string::npos) + { + string name = result.substr(0, pos); + result.replace(0, pos + suffix.size() - 1, name + ".h " + name + ".m"); + } + break; + } default: { abort(); diff --git a/cpp/src/slice2objc/Gen.cpp b/cpp/src/slice2objc/Gen.cpp new file mode 100644 index 00000000000..763f3f5661a --- /dev/null +++ b/cpp/src/slice2objc/Gen.cpp @@ -0,0 +1,3139 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceUtil/DisableWarnings.h> +#include <IceUtil/Functional.h> +#include <Gen.h> +#include <limits> +#include <sys/stat.h> +#ifndef _WIN32 +#include <unistd.h> +#else +#include <direct.h> +#endif +#include <IceUtil/Iterator.h> +#include <IceUtil/UUID.h> +#include <Slice/Checksum.h> +#include <Slice/FileTracker.h> +#include <Slice/Util.h> +#include <string.h> + +using namespace std; +using namespace Slice; +using namespace IceUtilInternal; + +namespace +{ + +string +sliceModeToIceMode(Operation::Mode opMode) +{ + string mode; + switch(opMode) + { + case Operation::Normal: + { + mode = "ICENormal"; + break; + } + case Operation::Nonmutating: + { + mode = "ICENonmutating"; + break; + } + case Operation::Idempotent: + { + mode = "ICEIdempotent"; + break; + } + default: + { + assert(false); + break; + } + } + return mode; +} + +string +opFormatTypeToString(const OperationPtr& op) +{ + switch(op->format()) + { + case DefaultFormat: + { + return "ICEDefaultFormat"; + break; + } + case CompactFormat: + { + return "ICECompactFormat"; + break; + } + case SlicedFormat: + { + return "ICESlicedFormat"; + break; + } + default: + { + assert(false); + } + } + + return "???"; +} + +class SortParamDeclByTagFn +{ +public: + + static bool compare(const ParamDeclPtr& lhs, const ParamDeclPtr& rhs) + { + return lhs->tag() < rhs->tag(); + } +}; + +} + +Slice::ObjCVisitor::ObjCVisitor(Output& h, Output& m) : _H(h), _M(m) +{ +} + +Slice::ObjCVisitor::~ObjCVisitor() +{ +} + +void +Slice::ObjCVisitor::writeMarshalUnmarshalParams(const ParamDeclList& params, const OperationPtr& op, bool marshal, + bool reference) +{ + ParamDeclList optionals; + for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p) + { + if((*p)->optional()) + { + optionals.push_back(*p); + } + else + { + string name = reference ? "*" + fixId((*p)->name()) : fixId((*p)->name()); + writeMarshalUnmarshalCode(_M, (*p)->type(), name, marshal, true); + } + } + if(op && op->returnType()) + { + if(!op->returnIsOptional()) + { + writeMarshalUnmarshalCode(_M, op->returnType(), "ret_", marshal, true); + } + } + + optionals.sort(SortParamDeclByTagFn::compare); + bool checkReturnType = op && op->returnIsOptional(); + for(ParamDeclList::const_iterator p = optionals.begin(); p != optionals.end(); ++p) + { + if(checkReturnType && op->returnTag() < (*p)->tag()) + { + writeOptParamMarshalUnmarshalCode(_M, op->returnType(), "ret_", op->returnTag(), marshal); + checkReturnType = false; + } + string name = reference ? "*" + fixId((*p)->name()) : fixId((*p)->name()); + writeOptParamMarshalUnmarshalCode(_M, (*p)->type(), name, (*p)->tag(), marshal); + } + if(checkReturnType) + { + writeOptParamMarshalUnmarshalCode(_M, op->returnType(), "ret_", op->returnTag(), marshal); + } +} + +void +Slice::ObjCVisitor::writeDispatchAndMarshalling(const ClassDefPtr& p) +{ + string name = fixName(p); + string scoped = p->scoped(); + ClassList allBases = p->allBases(); + StringList ids; + + transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped)); + + StringList other; + other.push_back(p->scoped()); + other.push_back("::Ice::Object"); + other.sort(); + ids.merge(other); + ids.unique(); + + StringList::const_iterator firstIter = ids.begin(); + StringList::const_iterator scopedIter = find(ids.begin(), ids.end(), scoped); + assert(scopedIter != ids.end()); + StringList::difference_type scopedPos = IceUtilInternal::distance(firstIter, scopedIter); + + _M << sp << nl << "static NSString *" << name << "_ids__[] = "; + _M << sb; + { + StringList::const_iterator q = ids.begin(); + while(q != ids.end()) + { + _M << nl << "@\"" << *q << '"'; + if(++q != ids.end()) + { + _M << ','; + } + } + } + _M << eb << ";"; + + OperationList ops = p->operations(); + OperationList::const_iterator r; + for(r = ops.begin(); r != ops.end(); ++r) + { + OperationPtr op = *r; + ContainerPtr container = op->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + assert(cl); + + string opName = getName(op); + _M << sp << nl << "+(BOOL)" << op->name() << "___:(id<" << name << ">)target_ current:(ICECurrent *)current " + << "is:(id<ICEInputStream>)is_ os:(id<ICEOutputStream>)os_"; + _M << sb; + + _M << nl << "ICEInternalCheckModeAndSelector(target_, " << sliceModeToIceMode(op->mode()) << ", @selector("; + string selector = getSelector(op); + if(!selector.empty()) + { + _M << selector << "current:"; + } + else + { + _M << opName << ":"; + } + _M << "), current);"; + + _M << nl << "ICEEncodingVersion* encoding = [is_ startEncapsulation];"; + ParamDeclList inParams; + ParamDeclList outParams; + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator pli = paramList.begin(); pli != paramList.end(); ++pli) + { + if(!(*pli)->isOutParam()) + { + inParams.push_back(*pli); + } + else + { + outParams.push_back(*pli); + } + } + ExceptionList throws = op->throws(); + throws.sort(); + throws.unique(); + throws.sort(Slice::DerivedToBaseCompare()); + + for(ParamDeclList::const_iterator inp = inParams.begin(); inp != inParams.end(); ++inp) + { + TypePtr type = (*inp)->type(); + string name = (*inp)->name(); + _M << nl << outTypeToString(type, (*inp)->optional(), true) << " " << fixId(name); + if(!isValueType(type)) + { + _M << " = nil"; + } + _M << ";"; + } + writeMarshalUnmarshalParams(inParams, 0, false); + if(op->sendsClasses(false)) + { + _M << nl << "[is_ readPendingObjects];"; + } + _M << nl << "[is_ endEncapsulation];"; + if(!throws.empty()) + { + _M << nl << "@try"; + _M << sb; + } + for(ParamDeclList::const_iterator outp = outParams.begin(); outp != outParams.end(); ++outp) + { + TypePtr type = (*outp)->type(); + string name = (*outp)->name(); + _M << nl << inTypeToString(type, (*outp)->optional(), true) << " " << fixId(name); + if((*outp)->optional()) + { + _M << " = ICENone"; + } + _M << ";"; + } + _M << nl << "[os_ startEncapsulation:encoding format:" << opFormatTypeToString(*r) << "];"; + TypePtr returnType = op->returnType(); + if(returnType) + { + _M << nl << inTypeToString(returnType, op->returnIsOptional(), true) << " ret_ = "; + } + else + { + _M << nl; + } + string args = getServerArgs(op); + _M << "[target_ " << opName << args; + if(!args.empty()) + { + _M << " current"; + } + _M << ":current];"; + writeMarshalUnmarshalParams(outParams, op, true); + if(op->returnsClasses(false)) + { + _M << nl << "[os_ writePendingObjects];"; + } + if(!throws.empty()) + { + _M << eb; + ExceptionList::const_iterator t; + for(t = throws.begin(); t != throws.end(); ++t) + { + string exS = fixName(*t); + _M << nl << "@catch(" << exS << " *ex)"; + _M << sb; + _M << nl << "[os_ writeException:ex];"; + _M << nl << "return NO;"; + _M << eb; + } + _M << nl << "@finally"; + _M << sb; + _M << nl << "[os_ endEncapsulation];"; + _M << eb; + } + else + { + _M << nl << "[os_ endEncapsulation];"; + } + _M << nl << "return YES;"; + _M << eb; + } + + OperationList allOps = p->allOperations(); + if(!allOps.empty()) + { + map<string, string> allOpNames; + for(OperationList::const_iterator p = allOps.begin(); p != allOps.end(); ++p) + { + allOpNames.insert(make_pair((*p)->name(), fixName(ClassDefPtr::dynamicCast((*p)->container())))); + } + + allOpNames["ice_id"] = "ICEObject"; + allOpNames["ice_ids"] = "ICEObject"; + allOpNames["ice_isA"] = "ICEObject"; + allOpNames["ice_ping"] = "ICEObject"; + + map<string, string>::const_iterator q; + + _M << sp << nl << "static NSString *" << name << "_all__[] ="; + _M << sb; + q = allOpNames.begin(); + while(q != allOpNames.end()) + { + _M << nl << "@\"" << q->first << '"'; + if(++q != allOpNames.end()) + { + _M << ','; + } + } + _M << eb << ';'; + + _M << sp << nl << "-(BOOL) dispatch__:(ICECurrent *)current is:(id<ICEInputStream>)is " + << "os:(id<ICEOutputStream>)os"; + _M << sb; + _M << nl << "id target__ = [self target__];"; + _M << nl << "switch(ICEInternalLookupString(" << name << "_all__, sizeof(" << name + << "_all__) / sizeof(NSString*), current.operation))"; + _M << sb; + int i = 0; + for(q = allOpNames.begin(); q != allOpNames.end(); ++q) + { + _M << nl << "case " << i++ << ':'; + _M.inc(); + string target = (q->second == "ICEObject") ? "self" : "target__"; + _M << nl << "return [" << q->second << " " << q->first << "___:(id<" << q->second + << ">)" << target << " current:current is:is os:os];"; + _M.dec(); + } + _M << nl << "default:"; + _M.inc(); + _M << nl << "@throw [ICEOperationNotExistException operationNotExistException:"; + _M.useCurrentPosAsIndent(); + _M << "__FILE__"; + _M << nl << "line:__LINE__"; + _M << nl << "id_:current.id_"; + _M << nl << "facet:current.facet"; + _M << nl << "operation:current.operation];"; + _M.restoreIndent(); + _M.dec(); + _M << eb; + _M << eb; + } + + _M << sp << nl << "+(NSString * const*) staticIds__:(int*)count idIndex:(int*)idx"; + _M << sb; + _M << nl << "*count = sizeof(" << name << "_ids__) / sizeof(NSString *);"; + _M << nl << "*idx = " << scopedPos << ";"; + _M << nl << "return " << name << "_ids__;"; + _M << eb; +} + +string +Slice::ObjCVisitor::getName(const OperationPtr& op) const +{ + if(!op->parameters().empty()) + { + return fixId(op->name(), BaseTypeNone); + } + else + { + return fixId(op->name(), BaseTypeObject); + } +} + +string +Slice::ObjCVisitor::getSelector(const OperationPtr& op) const +{ + string result; + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if(q == paramList.begin()) + { + result += getName(op) + ":"; + } + else + { + result += fixId((*q)->name()) + ":"; + } + } + return result; +} + +string +Slice::ObjCVisitor::getParams(const OperationPtr& op) const +{ + string result; + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + TypePtr type = (*q)->type(); + string typeString; + if((*q)->isOutParam()) + { + typeString = outTypeToString(type, (*q)->optional(), false, true); + } + else + { + typeString = inTypeToString(type, (*q)->optional()); + } + string name = fixId((*q)->name()); + if(q != paramList.begin()) + { + result += " " + name; + } + result += ":(" + typeString + ")" + name; + } + return result; +} + +string +Slice::ObjCVisitor::getMarshalParams(const OperationPtr& op) const +{ + ParamDeclList paramList = op->parameters(); + string result; + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if(!(*q)->isOutParam()) + { + TypePtr type = (*q)->type(); + string name = fixId((*q)->name()); + if(!result.empty()) + { + result += " " + name; + } + result += ":(" + inTypeToString(type, (*q)->optional()) + ")" + name; + } + } + return result; +} + +string +Slice::ObjCVisitor::getUnmarshalParams(const OperationPtr& op) const +{ + string result; + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if((*q)->isOutParam()) + { + TypePtr type = (*q)->type(); + string name = fixId((*q)->name()); + if(!result.empty()) + { + result += " " + name; + } + result += ":(" + outTypeToString(type, (*q)->optional(), false, true) + ")" + name; + } + } + return result; +} + +string +Slice::ObjCVisitor::getServerParams(const OperationPtr& op) const +{ + string result; + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + TypePtr type = (*q)->type(); + string typeString; + if((*q)->isOutParam()) + { + typeString = inTypeToString(type, (*q)->optional(), false, true); + } + else + { + typeString = outTypeToString(type, (*q)->optional()); + } + string name = fixId((*q)->name()); + if(q != paramList.begin()) + { + result += " " + name; + } + result += ":(" + typeString + ")" + name; + } + return result; +} + +string +Slice::ObjCVisitor::getResponseCBSig(const OperationPtr& op) const +{ + string result; + TypePtr returnType = op->returnType(); + if(returnType) + { + result = outTypeToString(returnType, op->returnIsOptional()); + } + + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if((*q)->isOutParam()) + { + TypePtr type = (*q)->type(); + string name = fixId((*q)->name()); + if(!result.empty()) + { + result += ", "; + } + result += outTypeToString(type, (*q)->optional()); + } + } + return "void(^)(" + result + ")"; +} + +string +Slice::ObjCVisitor::getArgs(const OperationPtr& op) const +{ + string result; + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + string name = fixId((*q)->name()); + if(q != paramList.begin()) + { + result += " " + name; + } + result += ":" + name; + } + return result; +} + +string +Slice::ObjCVisitor::getMarshalArgs(const OperationPtr& op) const +{ + string result; + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if(!(*q)->isOutParam()) + { + string name = fixId((*q)->name()); + if(!result.empty()) + { + result += " " + name; + } + result += ":" + name; + } + } + return result; +} + +string +Slice::ObjCVisitor::getUnmarshalArgs(const OperationPtr& op) const +{ + string result; + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + if((*q)->isOutParam()) + { + string name = fixId((*q)->name()); + if(!result.empty()) + { + result += " " + name; + } + result += ":" + name; + } + } + return result; +} + +string +Slice::ObjCVisitor::getServerArgs(const OperationPtr& op) const +{ + string result; + ParamDeclList paramList = op->parameters(); + for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q) + { + string name = fixId((*q)->name()); + if(q != paramList.begin()) + { + result += " " + name; + } + result += ":"; + if((*q)->isOutParam()) + { + result += "&"; + } + result += name; + } + return result; +} + +Slice::Gen::Gen(const string& name, const string& base, const string& include, const vector<string>& includePaths, + const string& dir) + : _base(base), + _include(include), + _includePaths(includePaths) +{ + for(vector<string>::iterator p = _includePaths.begin(); p != _includePaths.end(); ++p) + { + *p = fullPath(*p); + } + + string::size_type pos = _base.find_last_of("/\\"); + if(pos != string::npos) + { + _base.erase(0, pos + 1); + } + + string fileH = _base + ".h"; + string fileM = _base + ".m"; + string fileImplH = _base + "I.h"; + string fileImplM = _base + "I.m"; + + if(!dir.empty()) + { + fileH = dir + '/' + fileH; + fileM = dir + '/' + fileM; + fileImplH = dir + '/' + fileImplH; + fileImplM = dir + '/' + fileImplM; + } + + _H.open(fileH.c_str()); + if(!_H) + { + ostringstream os; + os << "cannot open `" << fileH << "': " << strerror(errno); + throw FileException(__FILE__, __LINE__, os.str()); + } + FileTracker::instance()->addFile(fileH); + printHeader(_H); + _H << nl << "// Generated from file `" << _base << ".ice'"; + + _H << sp << nl << "#import <objc/Ice/Config.h>"; + _H << nl << "#import <objc/Ice/Proxy.h>"; + _H << nl << "#import <objc/Ice/Object.h>"; + _H << nl << "#import <objc/Ice/Current.h>"; + _H << nl << "#import <objc/Ice/Exception.h>"; + _H << nl << "#import <objc/Ice/Stream.h>"; + + _M.open(fileM.c_str()); + if(!_M) + { + ostringstream os; + os << "cannot open `" << fileM << "': " << strerror(errno); + throw FileException(__FILE__, __LINE__, os.str()); + } + FileTracker::instance()->addFile(fileM); + printHeader(_M); + _M << nl << "// Generated from file `" << _base << ".ice'"; +} + +Slice::Gen::~Gen() +{ + if(_H.isOpen()) + { + _H << '\n'; + _M << '\n'; + } +} + +bool +Slice::Gen::operator!() const +{ + if(!_H || !_M) + { + return true; + } + return false; +} + +void +Slice::Gen::generate(const UnitPtr& p) +{ + ObjCGenerator::validateMetaData(p); + + _M << nl << "\n#import <objc/Ice/LocalException.h>"; + _M << nl << "#import <objc/Ice/Stream.h>"; + if(p->hasContentsWithMetaData("preserve-slice")) + { + _H << "\n#import <objc/Ice/SlicedData.h>"; + } + _M << nl << "#import <"; + if(!_include.empty()) + { + _M << _include << "/"; + } + _M << _base << ".h>"; + + // Necessary for objc_getClass use when marshalling/unmarshalling proxies. + _M << nl << "#import <objc/runtime.h>"; + + _M << nl; + + StringList includes = p->includeFiles(); + for(StringList::const_iterator q = includes.begin(); q != includes.end(); ++q) + { + static const string headerDirPrefix = "objc:header-dir:"; + DefinitionContextPtr dc = p->findDefinitionContext(*q); + assert(dc); + string meta = dc->findMetaData(headerDirPrefix); + string headerDir; + if(meta.size() > headerDirPrefix.size()) + { + headerDir = meta.substr(headerDirPrefix.size()); + } + _H << "\n#import <"; + if(!headerDir.empty()) + { + _H << headerDir << "/"; + } + _H << changeInclude(*q, _includePaths) << ".h>"; + } + + UnitVisitor unitVisitor(_H, _M); + p->visit(&unitVisitor, false); + + ObjectDeclVisitor objectDeclVisitor(_H, _M); + p->visit(&objectDeclVisitor, false); + + ProxyDeclVisitor proxyDeclVisitor(_H, _M); + p->visit(&proxyDeclVisitor, false); + + TypesVisitor typesVisitor(_H, _M); + p->visit(&typesVisitor, false); + + ProxyVisitor proxyVisitor(_H, _M); + p->visit(&proxyVisitor, false); + + DelegateMVisitor delegateMVisitor(_H, _M); + p->visit(&delegateMVisitor, false); + + HelperVisitor HelperVisitor(_H, _M); + p->visit(&HelperVisitor, false); +} + +void +Slice::Gen::closeOutput() +{ + _H.close(); + _M.close(); +} + +void +Slice::Gen::printHeader(Output& o) +{ + static const char* header = +"// **********************************************************************\n" +"//\n" +"// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.\n" +"//\n" +"// This copy of Ice is licensed to you under the terms described in the\n" +"// ICE_LICENSE file included in this distribution.\n" +"//\n" +"// **********************************************************************\n" + ; + + o << header; + o << "\n// Ice version " << ICE_STRING_VERSION; +} + +Slice::Gen::UnitVisitor::UnitVisitor(Output& H, Output& M) : + ObjCVisitor(H, M) +{ +} + +bool +Slice::Gen::UnitVisitor::visitModuleStart(const ModulePtr& p) +{ + string dummy; + if(p->findMetaData("objc:prefix", dummy)) + { + _prefixes.push_back(modulePrefix(p)); + } + return true; +} + +void +Slice::Gen::UnitVisitor::visitUnitEnd(const UnitPtr& unit) +{ + string uuid = IceUtil::generateUUID(); + for(string::size_type pos = 0; pos < uuid.size(); ++pos) + { + if(!isalnum(uuid[pos])) + { + uuid[pos] = '_'; + } + } + + if(!_prefixes.empty()) + { + _M << sp << nl << "@implementation ICEInternalPrefixTable(C" << uuid << ")"; + _M << nl << "-(void)addPrefixes_C" << uuid << ":(NSMutableDictionary*)prefixTable"; + _M << sb; + for(vector<Slice::ObjCGenerator::ModulePrefix>::const_iterator p = _prefixes.begin(); p != _prefixes.end(); ++p) + { + _M << nl << "[prefixTable setObject:@\"" << p->name << "\" forKey:@\"" << p->m->scoped() << "\"];"; + } + _M << eb; + _M << nl << "@end"; + } +} + +Slice::Gen::ObjectDeclVisitor::ObjectDeclVisitor(Output& H, Output& M) + : ObjCVisitor(H, M) +{ +} + +void +Slice::Gen::ObjectDeclVisitor::visitClassDecl(const ClassDeclPtr& p) +{ + _H << sp << nl << "@class " << fixName(p) << ";"; + _H << nl << "@protocol " << fixName(p) << ";"; +} + +Slice::Gen::ProxyDeclVisitor::ProxyDeclVisitor(Output& H, Output& M) + : ObjCVisitor(H, M) +{ +} + +void +Slice::Gen::ProxyDeclVisitor::visitClassDecl(const ClassDeclPtr& p) +{ + _H << sp << nl << "@class " << fixName(p) << "Prx;"; + _H << nl << "@protocol " << fixName(p) << "Prx;"; +} + +Slice::Gen::TypesVisitor::TypesVisitor(Output& H, Output& M) + : ObjCVisitor(H, M) +{ +} + +bool +Slice::Gen::TypesVisitor::visitModuleStart(const ModulePtr& p) +{ + string suffix; + StringList names = splitScopedName(p->scoped()); + for(StringList::const_iterator i = names.begin(); i != names.end(); ++i) + { + if(i != names.begin()) + { + suffix += "_"; + } + suffix += *i; + } + string symbol = "ICE_MODULE_PREFIX_"; + symbol += suffix; + return true; +} + +void +Slice::Gen::TypesVisitor::visitModuleEnd(const ModulePtr&) +{ +} + +bool +Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + string name = fixName(p); + ClassList bases = p->bases(); + + _H << sp << nl << "@protocol " << name; + if(!bases.empty()) + { + _H << " <"; + for(ClassList::const_iterator i = bases.begin(); i != bases.end(); ++i) + { + string baseName = fixName(*i); + if(i != bases.begin()) + { + _H << ", "; + } + _H << baseName; + } + _H << ">"; + } + + _M << sp << nl << "@implementation " << name; + + return true; +} + +void +Slice::Gen::TypesVisitor::visitClassDefEnd(const ClassDefPtr& p) +{ + string name = fixName(p); + ClassList bases = p->bases(); + bool basePreserved = p->inheritsMetaData("preserve-slice"); + bool preserved = p->hasMetaData("preserve-slice"); + bool hasBaseClass = !bases.empty() && !bases.front()->isInterface(); + string baseName = hasBaseClass ? fixName(bases.front()) : "ICEObject"; + DataMemberList baseDataMembers; + if(hasBaseClass) + { + baseDataMembers = bases.front()->allDataMembers(); + } + DataMemberList dataMembers = p->dataMembers(); + DataMemberList optionalMembers = p->orderedOptionalDataMembers(); + DataMemberList allDataMembers = p->allDataMembers(); + + _H << nl << "@end"; + + _H << sp << nl << "@interface " << name << " : " << baseName; + + if(!dataMembers.empty() || (preserved && !basePreserved)) + { + // + // Data member declarations. + // + _H << sb; + + if(!dataMembers.empty()) + { + writeMembers(dataMembers, BaseTypeObject); + } + + if(preserved && !basePreserved) + { + _H << nl << "id<ICESlicedData> slicedData__;"; + } + + _H << eb; + _H << sp; + + _M << sp; + } + + // + // @property and @synthesize for each data member. + // + writeProperties(dataMembers, BaseTypeObject); + writeSynthesize(dataMembers, BaseTypeObject); + + // + // Constructor. + // + if(!dataMembers.empty()) + { + _H << sp; + } + if(!p->isInterface() && !dataMembers.empty()) + { + if(p->hasDefaultValues()) + { + _H << nl << "-(id) init;"; + _M << sp << nl << "-(id) init"; + _M << sb; + _M << nl << "self = [super init];"; + _M << nl << "if(!self)"; + _M << sb; + _M << nl << "return nil;"; + _M << eb; + writeMemberDefaultValueInit(dataMembers, BaseTypeObject); + _M << nl << "return self;"; + _M << eb; + } + _H << nl << "-(id) init"; + _M << sp << nl << "-(id) init"; + writeMemberSignature(allDataMembers, BaseTypeObject, Other); + _H << ";"; + _M << sb; + _M << nl << "self = [super init"; + writeMemberCall(baseDataMembers, BaseTypeObject, Other, WithEscape); + _M << "];"; + _M << nl << "if(!self)"; + _M << sb; + _M << nl << "return nil;"; + _M << eb; + writeMemberInit(dataMembers, BaseTypeObject); + _M << nl << "return self;"; + _M << eb; + } + + // + // Convenience constructors. + // + if(!allDataMembers.empty()) + { + string lowerCaseName = fixId(p->name()); + *(lowerCaseName.begin()) = tolower(*lowerCaseName.begin()); + + _H << nl << "+(id) " << lowerCaseName; + _M << sp << nl << "+(id) " << lowerCaseName; + writeMemberSignature(allDataMembers, BaseTypeObject, Other); + _H << ";"; + _M << sb; + + // + // The cast avoids a compiler warning that is emitted if different structs + // have members with the same name but different types. + // + _M << nl << name << " *s__ = [(" << name << " *)[" << name << " alloc] init"; + writeMemberCall(allDataMembers, BaseTypeObject, Other, WithEscape); + _M << "];"; + + _M.zeroIndent(); + _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)"; + _M.restoreIndent(); + _M << nl << "[s__ autorelease];"; + _M.zeroIndent(); + _M << nl << "#endif"; + _M.restoreIndent(); + + _M << nl << "return s__;"; + _M << eb; + + _H << nl << "+(id) " << lowerCaseName << ";"; + _M << sp << nl << "+(id) " << lowerCaseName; + _M << sb; + _M << nl << name << " *s__ = [[" << name << " alloc] init];"; + + _M.zeroIndent(); + _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)"; + _M.restoreIndent(); + _M << nl << "[s__ autorelease];"; + _M.zeroIndent(); + _M << nl << "#endif"; + _M.restoreIndent(); + + _M << nl << "return s__;"; + _M << eb; + } + + if(!p->isInterface()) + { + // + // copyWithZone and dealloc + // + if(!dataMembers.empty()) + { + _M << sp << nl << "-(id) copyWithZone:(NSZone *)zone_p"; + _M << sb; + _M << nl << "return [(" << name << " *)[[self class] allocWithZone:zone_p] init"; + writeMemberCall(allDataMembers, BaseTypeObject, Other, NoEscape); + _M << "];"; + _M << eb; + _H << nl << "// This class also overrides copyWithZone:."; + + writeMemberDealloc(dataMembers, BaseTypeObject, preserved && !basePreserved); + } + } + + // + // Setter, has, clear selectors for optionals + // + writeOptionalDataMemberSelectors(dataMembers, BaseTypeObject); + + // + // If the class uses a compact id we generate a +load method to register the compact id + // with the compact id resolver. + // + if(p->compactId() >= 0) + { + _M << sp << nl << "+(void) load"; + _M << sb; + _M << nl << "[CompactIdMapHelper registerClass:@\"" << p->scoped() << "\" value:" << p->compactId() << "];"; + _M << eb; + } + + // + // Operations + // + OperationList ops = p->operations(); + OperationList::const_iterator r; + for(r = ops.begin(); r != ops.end(); ++r) + { + OperationPtr op = *r; + _H << nl << "+(BOOL)" << op->name() << "___:(id<" << name + << ">)target current:(ICECurrent *)current " + << "is:(id<ICEInputStream>)is_ os:(id<ICEOutputStream>)os_;"; + } + + _M << sp << nl << "+(id)objectWithDelegate:(id)delegate"; + _M << sb; + _M.zeroIndent(); + _M << sp << nl << "#if defined(__clang__) && __has_feature(objc_arc)"; + _M.restoreIndent(); + _M << nl << "return [[" << name << " alloc] initWithDelegate:delegate];"; + _M.zeroIndent(); + _M << nl << "#else"; + _M.restoreIndent(); + _M << nl << "return [[[" << name << " alloc] initWithDelegate:delegate] autorelease];"; + _M.zeroIndent(); + _M << nl << "#endif"; + _M.restoreIndent(); + _M << eb; + + // + // Marshaling/unmarshaling + // + + _M << sp << nl << "-(void) writeImpl__:(id<ICEOutputStream>)os_"; + _M << sb; + _M << nl << "[os_ startSlice:@\"" << p->scoped() << "\" compactId: " << p->compactId() << " lastSlice:" + << (!hasBaseClass ? "YES" : "NO") << "];"; + writeMemberMarshal(dataMembers, optionalMembers, BaseTypeObject); + _M << nl << "[os_ endSlice];"; + if(hasBaseClass) + { + _M << nl << "[super writeImpl__:os_];"; + } + _M << eb; + + _H << nl << "@end"; + + _M << sp << nl << "-(void) readImpl__:(id<ICEInputStream>)is_"; + _M << sb; + _M << nl << "[is_ startSlice];"; + writeMemberUnmarshal(dataMembers, optionalMembers, BaseTypeObject); + _M << nl << "[is_ endSlice];"; + if(hasBaseClass) + { + _M << nl << "[super readImpl__:is_];"; + } + _M << eb; + + writeDispatchAndMarshalling(p); + + if(preserved && !basePreserved) + { + _M << nl << "-(void) write__:(id<ICEOutputStream>)os"; + _M << sb; + _M << nl << "[os startObject:slicedData__];"; + _M << nl << "[self writeImpl__:os];"; + _M << nl << "[os endObject];"; + _M << eb; + + _M << nl << "-(void) read__:(id<ICEInputStream>)is"; + _M << sb; + _M << nl << "[is startObject];"; + _M << nl << "[self readImpl__:is];"; + _M << nl << "slicedData__ = [is endObject:YES];"; + _M << eb; + } + + _M << nl << "@end"; +} + +void +Slice::Gen::TypesVisitor::visitOperation(const OperationPtr& p) +{ + string name = getName(p); + TypePtr returnType = p->returnType(); + string retString = typeToString(returnType); + string params = getServerParams(p); + + + _H << nl << "-(" << inTypeToString(returnType, p->returnIsOptional()) << ") " << name << params; + if(!params.empty()) + { + _H << " current"; + } + _H << ":(ICECurrent *)current;"; +} + +void +Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p) +{ + string prefix = moduleName(findModule(p)); + string name = fixName(p); + + if(isValueType(p->type())) + { + _H << sp << nl << "typedef NSData " << name << ";"; + _H << nl << "typedef NSMutableData " << prefix << "Mutable" << p->name() << ";"; + } + else + { + _H << sp << nl << "typedef NSArray " << name << ";"; + _H << nl << "typedef NSMutableArray " << prefix << "Mutable" << p->name() << ";"; + } +} + +bool +Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p) +{ + string name = fixName(p); + ExceptionPtr base = p->base(); + DataMemberList dataMembers = p->dataMembers(); + bool basePreserved = p->inheritsMetaData("preserve-slice"); + bool preserved = p->hasMetaData("preserve-slice"); + + _H << sp; + + _H << nl << "@interface " << name << " : "; + if(base) + { + _H << fixName(base); + } + else + { + _H << (p->isLocal() ? "ICELocalException" : "ICEUserException"); + } + if(!dataMembers.empty() || (preserved && !basePreserved)) + { + _H << sb; + } + + _M << sp << nl << "@implementation " << name; + + return true; +} + +void +Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p) +{ + string name = fixName(p); + + string lowerCaseName = fixId(p->name()); + *(lowerCaseName.begin()) = tolower(*lowerCaseName.begin()); + bool basePreserved = p->inheritsMetaData("preserve-slice"); + bool preserved = p->hasMetaData("preserve-slice"); + DataMemberList dataMembers = p->dataMembers(); + DataMemberList optionalMembers = p->orderedOptionalDataMembers(); + DataMemberList allDataMembers = p->allDataMembers(); + DataMemberList::const_iterator q; + + DataMemberList baseDataMembers; + if(p->base()) + { + baseDataMembers = p->base()->allDataMembers(); + } + + if(!dataMembers.empty() || (preserved && !basePreserved)) + { + // + // Data member declarations. + // + if(!dataMembers.empty()) + { + writeMembers(dataMembers, BaseTypeException); + } + + if(preserved && !basePreserved) + { + _H << nl << "id<ICESlicedData> slicedData__;"; + } + + _H << eb; + _H << sp; + _M << sp; + + // + // @property and @synthesize for each data member. + // + if(!dataMembers.empty()) + { + writeProperties(dataMembers, BaseTypeException); + writeSynthesize(dataMembers, BaseTypeException); + } + _H << sp; + } + + // + // ice_name + // + _H << nl << "-(NSString *) ice_name;"; + _M << sp << nl << "-(NSString *) ice_name"; + _M << sb; + _M << nl << "return @\"" << p->scoped().substr(2) << "\";"; + _M << eb; + + // + // Constructors. + // + if(p->isLocal() && !dataMembers.empty()) + { + _H << nl << "-(id) init:(const char*)file__p line:(int)line__p;"; + _M << sp << nl << "-(id) init:(const char*)file__p line:(int)line__p"; + _M << sb; + _M << nl << "self = [super init:file__p line:line__p];"; + _M << nl << "if(!self)"; + _M << sb; + _M << nl << "return nil;"; + _M << eb; + _M << nl << "return self;"; + _M << eb; + } + if(!dataMembers.empty()) + { + if(!p->base() || p->hasDefaultValues()) + { + _H << sp << nl << "-(id) init;"; + _M << sp << nl << "-(id) init"; + _M << sb; + _M << nl << "self = "; + if(!p->base()) + { + _M << "[super initWithName:[self ice_name] reason:nil userInfo:nil];"; + } + else + { + _M << nl << "[super init];"; + } + _M << nl << "if(!self)"; + _M << sb; + _M << nl << "return nil;"; + _M << eb; + if(p->hasDefaultValues()) + { + writeMemberDefaultValueInit(dataMembers, BaseTypeObject); + } + _M << nl << "return self;"; + _M << eb; + } + + _H << nl << "-(id) init"; + _M << sp << nl << "-(id) init"; + writeMemberSignature(allDataMembers, BaseTypeException, p->isLocal() ? LocalException : Other); + _H << ";"; + _M << sb; + _M << nl << "self = "; + if(!p->base()) + { + _M << nl << "[super initWithName:[self ice_name] reason:nil userInfo:nil];"; + } + else + { + _M << nl << "[super init"; + if(p->isLocal()) + { + _M << ":file__p line:line__p "; + } + writeMemberCall(baseDataMembers, BaseTypeException, p->isLocal() ? LocalException : Other, WithEscape); + _M << "];"; + } + _M << nl << "if(!self)"; + _M << sb; + _M << nl << "return nil;"; + _M << eb; + if(!dataMembers.empty()) + { + writeMemberInit(dataMembers, BaseTypeException); + } + _M << nl << "return self;"; + _M << eb; + } + + // + // Convenience constructors. + // + _H << nl << "+(id) " << lowerCaseName; + _M << sp << nl << "+(id) " << lowerCaseName; + writeMemberSignature(allDataMembers, BaseTypeException, p->isLocal() ? LocalException : Other); + _H << ";"; + + // + // The cast avoids a compiler warning that is emitted if different exceptions + // have members with the same name but different types. + // + _M << sb; + _M << nl << name << " *s__ = [(" << name << " *)[" << name << " alloc] init"; + if(p->isLocal()) + { + _M << ":file__p line:line__p"; + } + writeMemberCall(allDataMembers, BaseTypeException, p->isLocal() ? LocalException : Other, WithEscape); + _M << "];"; + _M.zeroIndent(); + _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)"; + _M.restoreIndent(); + _M << nl << "[s__ autorelease];"; + _M.zeroIndent(); + _M << nl << "#endif"; + _M.restoreIndent(); + _M << nl << "return s__;"; + _M << eb; + + if(!allDataMembers.empty()) + { + _H << nl << "+(id) " << lowerCaseName; + _M << sp << nl << "+(id) " << lowerCaseName; + if(p->isLocal()) + { + _H << ":(const char*)file__p line:(int)line__p"; + _M << ":(const char*)file__p line:(int)line__p"; + } + _H << ";"; + _M << sb; + _M << nl << name << " *s__ = [[" << name << " alloc] init"; + if(p->isLocal()) + { + _M << ":file__p line:line__p"; + } + _M << "];"; + _M.zeroIndent(); + _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)"; + _M.restoreIndent(); + _M << nl << "[s__ autorelease];"; + _M.zeroIndent(); + _M << nl << "#endif"; + _M.restoreIndent(); + _M << nl << "return s__;"; + _M << eb; + } + + // + // copyWithZone and dealloc + // + if(!dataMembers.empty()) + { + _M << sp << nl << "-(id) copyWithZone:(NSZone *)zone_p"; + _M << sb; + _M << nl << "return [(" << name << " *)[[self class] allocWithZone:zone_p] init"; + if(p->isLocal()) + { + _M << ":file line:line"; + } + writeMemberCall(allDataMembers, BaseTypeException, p->isLocal() ? LocalException : Other, NoEscape); + _M << "];"; + _M << eb; + _H << nl << "// This class also overrides copyWithZone:."; + + writeMemberDealloc(dataMembers, BaseTypeException, preserved && !basePreserved); + } + + // + // Setter, has, clear selectors for optionals + // + writeOptionalDataMemberSelectors(dataMembers, BaseTypeObject); + + // + // Marshaling/unmarshaling + // + ExceptionPtr base = p->base(); + if(!p->allClassDataMembers().empty()) + { + if(!base || (base && !base->usesClasses(false))) + { + _M << sp << nl << "-(BOOL) usesClasses__"; + _M << sb; + _M << nl << "return YES;"; + _M << eb; + } + } + + if(!p->isLocal()) + { + _M << sp << nl << "-(void) writeImpl__:(id<ICEOutputStream>)os_"; + _M << sb; + _M << nl << "[os_ startSlice:@\"" << p->scoped() << "\" compactId:-1 lastSlice:" + << (!base ? "YES" : "NO") << "];"; + writeMemberMarshal(dataMembers, optionalMembers, BaseTypeException); + _M << nl << "[os_ endSlice];"; + if(base) + { + _M << nl << "[super writeImpl__:os_];"; + } + _M << eb; + + _M << sp << nl << "-(void) readImpl__:(id<ICEInputStream>)is_"; + _M << sb; + _M << nl << "[is_ startSlice];"; + writeMemberUnmarshal(dataMembers, optionalMembers, BaseTypeException); + _M << nl << "[is_ endSlice];"; + if(base) + { + _M << nl << "[super readImpl__:is_];"; + } + _M << eb; + + if(preserved && !basePreserved) + { + _M << nl << nl << "-(void) write__:(id<ICEOutputStream>)os"; + _M << sb; + _M << nl << "[os startException:slicedData__];"; + _M << nl << "[self writeImpl__:os];"; + _M << nl << "[os endException];"; + _M << eb; + + _M << nl << nl << "-(void) read__:(id<ICEInputStream>)is"; + _M << sb; + _M << nl << "[is startException];"; + _M << nl << "[self readImpl__:is];"; + _M << nl << "slicedData__ = [is endException:YES];"; + _M << eb; + } + } + + _H << nl << "@end"; + _M << nl << "@end"; +} + +bool +Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p) +{ + string name = fixName(p); + + _H << sp; + + _H << nl << "@interface " << name << " : NSObject <NSCopying>"; + _H << sb; + _H << nl << "@private"; + _H.inc(); + + _M << sp << nl << "@implementation " << name << sp; + + return true; +} + +void +Slice::Gen::TypesVisitor::visitStructEnd(const StructPtr& p) +{ + string name = fixName(p); + DataMemberList dataMembers = p->dataMembers(); + DataMemberList::const_iterator q; + + // + // Data member declarations. + // + writeMembers(dataMembers, BaseTypeObject); + + _H.dec(); + _H << eb; + + _H << sp; + + // + // @property and @synthesize for each data member. + // + writeProperties(dataMembers, BaseTypeObject); + writeSynthesize(dataMembers, BaseTypeObject); + + // + // Constructor. + // + if(p->hasDefaultValues()) + { + _H << sp << nl << "-(id) init;"; + _M << sp << nl << "-(id) init"; + _M << sb; + _M << nl << "self = [super init];"; + _M << nl << "if(!self)"; + _M << sb; + _M << nl << "return nil;"; + _M << eb; + writeMemberDefaultValueInit(dataMembers, BaseTypeObject); + _M << nl << "return self;"; + _M << eb; + } + _H << sp << nl << "-(id) init"; + _M << sp << nl << "-(id) init"; + writeMemberSignature(dataMembers, BaseTypeObject, Other); + _H << ";"; + _M << sb; + _M << nl << "self = [super init];"; + _M << nl << "if(!self)"; + _M << sb; + _M << nl << "return nil;"; + _M << eb; + writeMemberInit(dataMembers, BaseTypeObject); + _M << nl << "return self;"; + _M << eb; + + // + // Convenience constructor. + // + string lowerCaseName = fixId(p->name()); + *(lowerCaseName.begin()) = tolower(*lowerCaseName.begin()); + + _H << nl << "+(id) " << lowerCaseName; + _M << sp << nl << "+(id) " << lowerCaseName; + writeMemberSignature(dataMembers, BaseTypeObject, Other); + _H << ";"; + _M << sb; + + // + // The cast avoids a compiler warning that is emitted if different structs + // have members with the same name but different types. + // + _M << nl << name << " *s__ = [(" << name << "* )[" << name << " alloc] init"; + writeMemberCall(dataMembers, BaseTypeObject, Other, WithEscape); + _M << "];"; + _M.zeroIndent(); + _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)"; + _M.restoreIndent(); + _M << nl << "[s__ autorelease];"; + _M.zeroIndent(); + _M << nl << "#endif"; + _M.restoreIndent(); + _M << nl << "return s__;"; + _M << eb; + + _H << nl << "+(id) " << lowerCaseName << ";"; + _M << sp << nl << "+(id) " << lowerCaseName; + _M << sb; + _M << nl << name << " *s__ = [[" << name << " alloc] init];"; + _M.zeroIndent(); + _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)"; + _M.restoreIndent(); + _M << nl << "[s__ autorelease];"; + _M.zeroIndent(); + _M << nl << "#endif"; + _M.restoreIndent(); + _M << nl << "return s__;"; + _M << eb; + + // + // copyWithZone + // + _M << sp << nl << "-(id) copyWithZone:(NSZone *)zone_p"; + _M << sb; + _M << nl << "return [(" << name << " *)[[self class] allocWithZone:zone_p] init"; + writeMemberCall(dataMembers, BaseTypeObject, Other, NoEscape); + _M << "];"; + _M << eb; + + // + // hash + // + writeMemberHashCode(dataMembers, BaseTypeObject); + + // + // isEqual + // + _M << sp << nl << "-(BOOL) isEqual:(id)o_"; + _M << sb; + _M << nl << "if(self == o_)"; + _M << sb; + _M << nl << "return YES;"; + _M << eb; + _M << nl << "if(!o_ || ![o_ isKindOfClass:[self class]])"; + _M << sb; + _M << nl << "return NO;"; + _M << eb; + writeMemberEquals(dataMembers, BaseTypeObject); + _M << eb; + + _H << nl << "// This class also overrides copyWithZone:, hash, and isEqual:"; + + // + // dealloc + // + writeMemberDealloc(dataMembers, BaseTypeObject); + + // + // Marshaling/unmarshaling + // + _H << nl << "-(void) write__:(id<ICEOutputStream>)os_;"; + _H << nl << "-(void) read__:(id<ICEInputStream>)is_;"; + + _M << sp << nl << "-(void) write__:(id<ICEOutputStream>)os_"; + _M << sb; + writeMemberMarshal(dataMembers, DataMemberList(), BaseTypeObject); + _M << eb; + + _M << sp << nl << "-(void) read__:(id<ICEInputStream>)is_"; + _M << sb; + writeMemberUnmarshal(dataMembers, DataMemberList(), BaseTypeObject); + _M << eb; + + _H << nl << "@end"; + _M << nl << "@end"; +} + +void +Slice::Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p) +{ + string prefix = moduleName(findModule(p)); + string name = fixName(p); + + _H << sp << nl << "typedef NSDictionary " << name << ";"; + _H << nl << "typedef NSMutableDictionary " << prefix << "Mutable" << p->name() << ";"; +} + +void +Slice::Gen::TypesVisitor::visitEnum(const EnumPtr& p) +{ + string name = fixName(p); + EnumeratorList enumerators = p->getEnumerators(); + _H << sp; + + // + // Check if any of the enumerators were assigned an explicit value. + // + const bool explicitValue = p->explicitValue(); + + _H << nl << "typedef enum : ICEInt"; + _H << sb; + EnumeratorList::const_iterator en = enumerators.begin(); + while(en != enumerators.end()) + { + _H << nl << fixName(*en); + // + // If any of the enumerators were assigned an explicit value, we emit + // an explicit value for *all* enumerators. + // + if(explicitValue) + { + _H << " = " << int64ToString((*en)->value()); + } + if(++en != enumerators.end()) + { + _H << ','; + } + } + _H << eb << " " << name << ";"; +} + +void +Slice::Gen::TypesVisitor::visitConst(const ConstPtr& p) +{ + _H << sp; + if(isString(p->type())) + { + _H << nl << "static NSString * const"; + } + else + { + _H << nl << "static const " << typeToString(p->type()); + } + _H << " " << fixName(p) << " = "; + writeConstantValue(_H, p->type(), p->value()); + _H << ';'; +} + +void +Slice::Gen::TypesVisitor::writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const string& val) const +{ + if(isString(type)) + { + // + // Expand strings into the basic source character set. We can't use isalpha() and the like + // here because they are sensitive to the current locale. + // + static const string basicSourceChars = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "_{}[]#()<>%:;.?*+-/^&|~!=,\\\"' "; + static const set<char> charSet(basicSourceChars.begin(), basicSourceChars.end()); + + out << "@\""; // Opening @" + + for(string::const_iterator c = val.begin(); c != val.end(); ++c) + { + if(charSet.find(*c) == charSet.end()) + { + unsigned char uc = *c; // char may be signed, so make it positive + ostringstream s; + s << "\\"; // Print as octal if not in basic source character set + s.width(3); + s.fill('0'); + s << oct; + s << static_cast<unsigned>(uc); + out << s.str(); + } + else + { + out << *c; // Print normally if in basic source character set + } + } + + out << "\""; // Closing " + } + else + { + EnumPtr ep = EnumPtr::dynamicCast(type); + if(ep) + { + out << moduleName(findModule(ep)) << val; + } + else + { + if(val == "true") + { + out << "YES"; + } + else if(val == "false") + { + out << "NO"; + } + else + { + out << val; + } + } + } +} + +void +Slice::Gen::TypesVisitor::writeMembers(const DataMemberList& dataMembers, int baseType) const +{ + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + TypePtr type = (*q)->type(); + string name = fixId((*q)->name(), baseType); + + _H << nl << typeToString(type) << " "; + if(mapsToPointerType(type)) + { + _H << "*"; + } + _H << name << ";"; + + if((*q)->optional()) + { + _H << nl << "BOOL has_" << name << "__;"; + } + } +} + +void +Slice::Gen::TypesVisitor::writeMemberSignature(const DataMemberList& dataMembers, int baseType, + ContainerType ct) const +{ + if(ct == LocalException) + { + _H << ":(const char*)file__p line:(int)line__p"; + _M << ":(const char*)file__p line:(int)line__p"; + } + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + TypePtr type = (*q)->type(); + string typeString = inTypeToString(type, (*q)->optional()); + string name = fixId((*q)->name(), baseType); + + if(q != dataMembers.begin() || ct == LocalException) + { + _H << " " << name; + _M << " " << name; + } + _H << ":(" << typeString << ")" << fixId((*q)->name()); + _M << ":(" << typeString << ")" << fixId((*q)->name()) << "_p"; + } +} + +void +Slice::Gen::TypesVisitor::writeMemberCall(const DataMemberList& dataMembers, int baseType, + ContainerType ct, Escape esc) const +{ + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + string name = (*q)->name(); + + if(q != dataMembers.begin() || ct == LocalException) + { + _M << " " << fixId(name, baseType); + } + + name = esc == NoEscape ? fixId(name, baseType) : fixId(name); + if(esc == NoEscape) + { + if((*q)->optional()) + { + if(isValueType((*q)->type())) + { + _M << ":" << "(self->has_" << name << "__ ? @(self->" << name << ") : ICENone)"; + } + else + { + _M << ":" << "(self->has_" << name << "__ ? self->" << name << " : ICENone)"; + } + } + else + { + _M << ":" << name; + } + } + else + { + _M << ":" << name << "_p"; + } + } +} + +void +Slice::Gen::TypesVisitor::writeMemberDefaultValueInit(const DataMemberList& dataMembers, int baseType) const +{ + for(DataMemberList::const_iterator p = dataMembers.begin(); p != dataMembers.end(); ++p) + { + if((*p)->defaultValueType()) + { + string name = fixId((*p)->name(), baseType); + if((*p)->optional()) + { + _M << nl << "self->has_" << name << "__ = YES;"; + } + _M << nl << "self->" << name << " = "; + writeConstantValue(_M, (*p)->type(), (*p)->defaultValue()); + _M << ";"; + } + } +} + +void +Slice::Gen::TypesVisitor::writeMemberInit(const DataMemberList& dataMembers, int baseType) const +{ + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + TypePtr type = (*q)->type(); + string name = fixId((*q)->name()); + if((*q)->optional()) + { + if(isValueType(type)) + { + _M << nl << "self->has_" << name << "__ = [ICEOptionalGetter " << getOptionalHelperGetter(type) << ":"; + _M << name << "_p value:&self->" << fixId((*q)->name(), baseType) << "];"; + } + else + { + _M << nl << "self->has_" << name << "__ = [ICEOptionalGetter getRetained:"; + _M << name << "_p value:&self->" << fixId((*q)->name(), baseType); + _M << " type:[" << typeToObjCTypeString(type) << " class]];"; + } + } + else + { + if(isValueType(type)) + { + _M << nl << "self->" << fixId((*q)->name(), baseType) << " = " << name << "_p;"; + } + else + { + _M.zeroIndent(); + _M << nl << "#if defined(__clang__) && __has_feature(objc_arc)"; + _M.restoreIndent(); + _M << nl << "self->" << fixId((*q)->name(), baseType) << " = " << name << "_p;"; + _M.zeroIndent(); + _M << nl << "#else"; + _M.restoreIndent(); + _M << nl << "self->" << fixId((*q)->name(), baseType) << " = [" << name << "_p retain];"; + _M.zeroIndent(); + _M << nl << "#endif"; + _M.restoreIndent(); + } + } + } +} + +void +Slice::Gen::TypesVisitor::writeProperties(const DataMemberList& dataMembers, int baseType) const +{ + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + TypePtr type = (*q)->type(); + string name = fixId((*q)->name(), baseType); + + string typeString = typeToString(type); + bool isValue = isValueType(type); + + _H << nl << "@property(nonatomic, "; + if(isValue) + { + _H << "assign"; + } + else + { + _H << "ICE_STRONG_ATTR"; + } + _H << ") " << typeString << " "; + if(mapsToPointerType(type)) + { + _H << "*"; + } + _H << name << ";"; + } +} + +void +Slice::Gen::TypesVisitor::writeSynthesize(const DataMemberList& dataMembers, int baseType) const +{ + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + string name = fixId((*q)->name(), baseType); + _M << nl << "@synthesize " << name << ";"; + } +} + +void +Slice::Gen::TypesVisitor::writeOptionalDataMemberSelectors(const DataMemberList& dataMembers, int baseType) const +{ + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + if(!(*q)->optional()) + { + continue; + } + + TypePtr type = (*q)->type(); + string typeString = inTypeToString(type, false); + + string name = fixId((*q)->name(), baseType); + + string capName = (*q)->name(); + capName[0] = toupper(static_cast<unsigned char>(capName[0])); + + _H << nl << "-(void)set" << capName << ":(" << typeString << ")" << name << "_p;"; + + _M << nl << "-(void)set" << capName << ":(" << typeString << ")" << name << "_p"; + _M << sb; + _M << nl << "self->has_" << name << "__ = YES;"; + bool isValue = isValueType(type); + if(isValue) + { + _M << nl << "self->" << name << " = " << name << "_p;"; + } + else + { + _M.zeroIndent(); + _M << nl << "#if defined(__clang__) && __has_feature(objc_arc)"; + _M.restoreIndent(); + _M << nl << "self->" << name << " = " << name << "_p;"; + _M.zeroIndent(); + _M << nl << "#else"; + _M.restoreIndent(); + _M << nl << "[self->" << name << " release];"; + _M << nl << "self->" << name << " = [" << name << "_p retain];"; + _M.zeroIndent(); + _M << nl << "#endif"; + _M.restoreIndent(); + } + _M << eb; + + _H << nl << "-(BOOL)has" << capName << ";"; + _M << nl << "-(BOOL)has" << capName; + _M << sb; + _M << nl << "return self->has_" << name << "__;"; + _M << eb; + + _H << nl << "-(void)clear" << capName << ";"; + _M << nl << "-(void)clear" << capName; + _M << sb; + _M << nl << "self->has_" << name << "__ = NO;"; + if(!isValue) + { + _M.zeroIndent(); + _M << nl << "#if defined(__clang__) && __has_feature(objc_arc)"; + _M.restoreIndent(); + _M << nl << "self->" << name << " = nil;"; + _M.zeroIndent(); + _M << nl << "#else"; + _M.restoreIndent(); + _M << nl << "[self->" << name << " release];"; + _M << nl << "self->" << name << " = nil;"; + _M.zeroIndent(); + _M << nl << "#endif"; + _M.restoreIndent(); + } + _M << eb; + } +} + +void +Slice::Gen::TypesVisitor::writeMemberHashCode(const DataMemberList& dataMembers, int baseType) const +{ + _M << sp << nl << "-(NSUInteger) hash"; + _M << sb; + _M << nl << "NSUInteger h_ = 5381;"; + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + TypePtr type = (*q)->type(); + string name = fixId((*q)->name(), baseType); + + _M << nl << "h_ = ((h_ << 5) + h_) ^ "; + if(isValueType(type)) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + if(builtin->kind() == Builtin::KindFloat || builtin->kind() == Builtin::KindDouble) + { + _M << "(2654435761u * (uint)" << name << ");"; + } + else + { + _M << "(2654435761u * " << name << ");"; + } + } + else + { + _M << name << ";"; + } + } + else + { + _M << "[self->" << name << " hash];"; + } + } + _M << nl << "return h_;"; + _M << eb; +} + +void +Slice::Gen::TypesVisitor::writeMemberEquals(const DataMemberList& dataMembers, int baseType) const +{ + if(!dataMembers.empty()) + { + ContainerPtr container = (*dataMembers.begin())->container(); + ContainedPtr contained = ContainedPtr::dynamicCast(container); + string containerName = fixName(contained); + _M << nl << containerName << " *obj_ = (" << containerName << " *)o_;"; + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + TypePtr type = (*q)->type(); + string name = fixId((*q)->name(), baseType); + + if(isValueType(type)) + { + _M << nl << "if(" << name << " != obj_->" << name << ")"; + _M << sb; + _M << nl << "return NO;"; + _M << eb; + } + else + { + _M << nl << "if(!" << name << ")"; + _M << sb; + _M << nl << "if(obj_->" << name << ")"; + _M << sb; + _M << nl << "return NO;"; + _M << eb; + _M << eb; + _M << nl << "else"; + _M << sb; + _M << nl << "if(![self." << name << " "; + _M << (isString(type) ? "isEqualToString" : "isEqual"); + _M << ":obj_->" << name << "])"; + _M << sb; + _M << nl << "return NO;"; + _M << eb; + _M << eb; + } + } + } + _M << nl << "return YES;"; +} + +void +Slice::Gen::TypesVisitor::writeMemberDealloc(const DataMemberList& dataMembers, int baseType, bool slicedData) const +{ + bool once = false; + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + TypePtr type = (*q)->type(); + if(!isValueType(type)) + { + if(!once) + { + once = true; + _M << sp; + _M.zeroIndent(); + _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)"; + _M.restoreIndent(); + _M << nl << "-(void) dealloc"; + _M << sb; + } + + bool isValue = isValueType(type); + if(!isValue) + { + _M << nl << "[self->" << fixId((*q)->name(), baseType) << " release];"; + } + } + } + if(once) + { + if(slicedData) + { + _M << nl << "[(NSObject*)slicedData__ release];"; + } + _M << nl << "[super dealloc];"; + _M << eb; + _M.zeroIndent(); + _M << nl << "#endif"; + _M.restoreIndent(); + _H << nl << "// This class also overrides dealloc."; + } +} + +void +Slice::Gen::TypesVisitor::writeMemberMarshal(const DataMemberList& dataMembers, const DataMemberList& optionalMembers, + int baseType) const +{ + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + if(!(*q)->optional()) + { + writeMarshalUnmarshalCode(_M, (*q)->type(), "self->" + fixId((*q)->name(), baseType), true, false); + } + } + for(DataMemberList::const_iterator q = optionalMembers.begin(); q != optionalMembers.end(); ++q) + { + string name = fixId((*q)->name(), baseType); + string frmt = getOptionalFormat((*q)->type()); + _M << nl << "if(self->has_" << name << "__ && [os_ writeOptional:" << (*q)->tag() << " format:" << frmt << "])"; + _M << sb; + writeOptMemberMarshalUnmarshalCode(_M, (*q)->type(), "self->" + name, true); + _M << eb; + } +} + +void +Slice::Gen::TypesVisitor::writeMemberUnmarshal(const DataMemberList& dataMembers, const DataMemberList& optionalMembers, + int baseType) const +{ + for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q) + { + if(!(*q)->optional()) + { + writeMarshalUnmarshalCode(_M, (*q)->type(), "self->" + fixId((*q)->name(), baseType), false, false); + } + } + for(DataMemberList::const_iterator q = optionalMembers.begin(); q != optionalMembers.end(); ++q) + { + string name = fixId((*q)->name(), baseType); + string frmt = getOptionalFormat((*q)->type()); + _M << nl << "if([is_ readOptional:" << (*q)->tag() << " format:" << frmt << "])"; + _M << sb; + _M << nl << "self->has_" << name << "__ = YES;"; + writeOptMemberMarshalUnmarshalCode(_M, (*q)->type(), "self->" + name, false); + _M << eb; + _M << nl << "else"; + _M << sb; + _M << nl << "self->has_" << name << "__ = NO;"; + _M << eb; + } +} + +Slice::Gen::ProxyVisitor::ProxyVisitor(Output& H, Output& M) + : ObjCVisitor(H, M) +{ +} + +bool +Slice::Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + string name = fixName(p); + ClassList bases = p->bases(); + + _H << sp << nl << "@protocol " << name << "Prx <"; + if(bases.empty()) + { + _H << "ICEObjectPrx"; + } + else + { + ClassList::const_iterator q = bases.begin(); + while(q != bases.end()) + { + _H << fixName(*q) + "Prx"; + if(++q != bases.end()) + { + _H << ", "; + } + } + } + _H << ">"; + + return true; +} + +void +Slice::Gen::ProxyVisitor::visitClassDefEnd(const ClassDefPtr&) +{ + _H << nl << "@end"; +} + +void +Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) +{ + string name = getName(p); + TypePtr returnType = p->returnType(); + string retString = outTypeToString(returnType, p->returnIsOptional()); + string params = getParams(p); + string marshalParams = getMarshalParams(p); + string unmarshalParams = getUnmarshalParams(p); + + // + // Write two versions of the operation--with and without a + // context parameter. + // + _H << nl << "-(" << retString << ") " << name << params << ";"; + + _H << nl << "-(" << retString << ") " << name << params; + if(!params.empty()) + { + _H << " context"; + } + _H << ":(ICEContext *)context;"; + + _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams << ";"; + _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams; + if(!marshalParams.empty()) + { + _H << " context"; + } + _H << ":(ICEContext *)context;"; + + _H << nl << "-(" << retString << ") end_" << p->name() << unmarshalParams; + if(!unmarshalParams.empty()) + { + _H << " result"; + } + _H << ":(id<ICEAsyncResult>)result;"; + + string responseCBSig = getResponseCBSig(p); + _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams; + if(!marshalParams.empty()) + { + _H << " response"; + } + _H << ":(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_;"; + + _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams; + if(!marshalParams.empty()) + { + _H << " context"; + } + _H << ":(ICEContext *)context"; + _H << " response:(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_;"; + + _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams; + if(!marshalParams.empty()) + { + _H << " response"; + } + _H << ":(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_ sent:(void(^)(BOOL))sent_;"; + + _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams; + if(!marshalParams.empty()) + { + _H << " context"; + } + _H << ":(ICEContext *)context"; + _H << " response:(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_ sent:(void(^)(BOOL))sent_;"; +} + +Slice::Gen::HelperVisitor::HelperVisitor(Output& H, Output& M) : + ObjCVisitor(H, M) +{ +} + +bool +Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + // + // Proxy helper + // + { + string name = moduleName(findModule(p)) + p->name() + "PrxHelper"; + _H << sp << nl << "@interface " << name << " : ICEProxyHelper"; + _H << nl << "@end"; + + _M << sp << nl << "@implementation " << name; + _M << nl << "+(id) readRetained:(id<ICEInputStream>)stream"; + _M << sb; + _M << nl << "return [stream newProxy:[" << fixName(p) << "Prx class]];"; + _M << eb; + _M << nl << "@end"; + } + + // + // Class helper + // + { + string name = moduleName(findModule(p)) + p->name() + "Helper"; + if(p->isInterface()) + { + _H << sp << nl << "typedef ICEObjectHelper " << name << ";"; + } + else + { + _H << sp << nl << "@interface " << name << " : ICEObjectHelper"; + _H << nl << "@end"; + + _M << sp << nl << "@implementation " << name; + _M << nl << "+(void) readRetained:(ICEObject*ICE_STRONG_QUALIFIER*)obj stream:(id<ICEInputStream>)stream"; + _M << sb; + _M << nl << "[stream newObject:obj expectedType:[" << fixName(p) << " class]];"; + _M << eb; + _M << nl << "@end"; + } + } + return false; +} + +void +Slice::Gen::HelperVisitor::visitEnum(const EnumPtr& p) +{ + string name = moduleName(findModule(p)) + p->name() + "Helper"; + + _H << sp << nl << "@interface " << name << " : ICEEnumHelper"; + _H << nl << "@end"; + + _M << sp << nl << "@implementation " << name; + _M << nl << "+(ICEInt) getMinValue"; + _M << sb; + _M << nl << "return " << p->minValue() << ";"; + _M << eb; + _M << nl << "+(ICEInt) getMaxValue"; + _M << sb; + _M << nl << "return " << p->maxValue() << ";"; + _M << eb; + _M << nl << "@end"; +} + +void +Slice::Gen::HelperVisitor::visitSequence(const SequencePtr& p) +{ + string name = moduleName(findModule(p)) + p->name() + "Helper"; + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type()); + if(builtin) + { + _H << sp << nl << "typedef ICE" << getBuiltinName(builtin) << "SequenceHelper " << name << ";"; + return; + } + + EnumPtr en = EnumPtr::dynamicCast(p->type()); + if(en) + { + _H << sp << nl << "@interface " << name << " : ICEEnumSequenceHelper"; + _H << nl << "@end"; + + string typeS = typeToString(en); + int min = en->minValue(); + int max = en->maxValue(); + _M << sp << nl << "@implementation " << name; + _M << nl << "+(id) readRetained:(id<ICEInputStream>)stream"; + _M << sb; + _M << nl << "return [stream newEnumSeq:" << min << " max:" << max << "];"; + _M << eb; + _M << nl << "+(void) write:(id)obj stream:(id<ICEOutputStream>)stream"; + _M << sb; + _M << nl << "[stream writeEnumSeq:obj min:" << min << " max:" << max << "];"; + _M << eb; + _M << nl << "@end"; + return; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(p->type()); + if(cl) + { + _H << sp << nl << "@interface " << name << " : ICEObjectSequenceHelper"; + _H << nl << "@end"; + + _M << sp << nl << "@implementation " << name; + _M << nl << "+(id) readRetained:(id<ICEInputStream>)stream"; + _M << sb; + _M << nl << "return [stream newObjectSeq:[" << fixName(cl) << " class]];"; + _M << eb; + _M << nl << "@end"; + return; + } + + ProxyPtr proxy = ProxyPtr::dynamicCast(p->type()); + ContainedPtr contained = ContainedPtr::dynamicCast(p->type()); + _H << sp << nl << "@interface " << name << " : ICEArraySequenceHelper"; + _H << nl << "@end"; + + _M << sp << nl << "@implementation " << name; + _M << nl << "+(Class) getElementHelper"; + _M << sb; + if(proxy) + { + string name = moduleName(findModule(proxy->_class())) + proxy->_class()->name(); + _M << nl << "return [" << name << "PrxHelper class];"; + } + else + { + assert(contained); + _M << nl << "return [" << moduleName(findModule(contained)) + contained->name() + "Helper class];"; + } + _M << eb; + _M << nl << "+(Class) getOptionalHelper"; + _M << sb; + if(p->type()->isVariableLength()) + { + _M << nl << "return [ICEVarLengthOptionalHelper class];"; + } + else if(p->type()->minWireSize() == 1) + { + _M << nl << "return [ICEFixedSize1SequenceOptionalHelper class];"; + } + else + { + _M << nl << "return [ICEFixedSequenceOptionalHelper class];"; + } + _M << eb; + _M << nl << "@end"; +} + +void +Slice::Gen::HelperVisitor::visitDictionary(const DictionaryPtr& p) +{ + string name = moduleName(findModule(p)) + p->name() + "Helper"; + + TypePtr keyType = p->keyType(); + string keyS; + BuiltinPtr keyBuiltin = BuiltinPtr::dynamicCast(keyType); + if(keyBuiltin) + { + keyS = "ICE" + getBuiltinName(BuiltinPtr::dynamicCast(keyType)) + "Helper"; + } + else + { + ContainedPtr contained = ContainedPtr::dynamicCast(keyType); + keyS = moduleName(findModule(contained)) + contained->name() + "Helper"; + } + + string valueS; + TypePtr valueType = p->valueType(); + BuiltinPtr valueBuiltin = BuiltinPtr::dynamicCast(valueType); + ClassDeclPtr valueClass = ClassDeclPtr::dynamicCast(valueType); + if((valueBuiltin && valueBuiltin->kind() == Builtin::KindObject) || valueClass) + { + _H << sp << nl << "@interface " << name << " : ICEObjectDictionaryHelper"; + _H << nl << "@end"; + + _M << sp << nl << "@implementation " << name; + _M << nl << "+(id) readRetained:(id<ICEInputStream>)stream"; + _M << sb; + if(valueClass && !valueClass->isInterface()) + { + valueS = fixName(valueClass); + _M << nl << "return [stream newObjectDict:[" << keyS << " class] expectedType:[" << valueS << " class]];"; + } + else + { + _M << nl << "return [stream newObjectDict:[" << keyS << " class] expectedType:[ICEObject class]];"; + } + _M << eb; + _M << nl << "+(void) write:(id)obj stream:(id<ICEOutputStream>)stream"; + _M << sb; + _M << nl << "[stream writeObjectDict:obj helper:[" << keyS << " class]];"; + _M << eb; + _M << nl << "@end"; + return; + } + + ProxyPtr valueProxy = ProxyPtr::dynamicCast(valueType); + if(valueBuiltin) + { + valueS = "ICE" + getBuiltinName(BuiltinPtr::dynamicCast(valueType)) + "Helper"; + } + else if(valueProxy) + { + valueS = moduleName(findModule(valueProxy->_class())) + valueProxy->_class()->name() + "PrxHelper"; + } + else + { + ContainedPtr contained = ContainedPtr::dynamicCast(valueType); + valueS = moduleName(findModule(contained)) + contained->name() + "Helper"; + } + _H << sp << nl << "@interface " << name << " : ICEDictionaryHelper"; + _H << nl << "@end"; + + _M << sp << nl << "@implementation " << name; + _M << nl << "+(ICEKeyValueTypeHelper) getKeyValueHelper"; + _M << sb; + _M << nl << "ICEKeyValueTypeHelper c;"; + _M << nl << "c.key = [" << keyS << " class];"; + _M << nl << "c.value = [" << valueS << " class];"; + _M << nl << "return c;"; + _M << eb; + _M << nl << "+(Class) getOptionalHelper"; + _M << sb; + if(keyType->isVariableLength() || valueType->isVariableLength()) + { + _M << nl << "return [ICEVarLengthOptionalHelper class];"; + } + else + { + _M << nl << "return [ICEFixedDictionaryOptionalHelper class];"; + } + _M << eb; + _M << nl << "@end"; +} + + +bool +Slice::Gen::HelperVisitor::visitStructStart(const StructPtr& p) +{ + string name = fixName(p); + + _H << sp << nl << "@interface " << name << "Helper : ICEStructHelper"; + _H << nl << "@end"; + + _M << sp << nl << "@implementation " << name << "Helper"; + + _M << nl << "+(Class) getType"; + _M << sb; + _M << nl << "return [" << name << " class];"; + _M << eb; + _M << nl << "+(Class) getOptionalHelper"; + _M << sb; + if(p->isVariableLength()) + { + _M << nl << "return [ICEVarLengthOptionalHelper class];"; + } + else + { + _M << nl << "return [ICEFixedLengthOptionalHelper class];"; + } + _M << eb; + + _M << nl << "+(ICEInt) minWireSize"; + _M << sb; + _M << nl << "return " << p->minWireSize() << ";"; + _M << eb; + + _M << nl << "@end"; + return false; +} + +Slice::Gen::DelegateMVisitor::DelegateMVisitor(Output& H, Output& M) + : ObjCVisitor(H, M) +{ +} + +bool +Slice::Gen::DelegateMVisitor::visitModuleStart(const ModulePtr& p) +{ + return true; +} + +void +Slice::Gen::DelegateMVisitor::visitModuleEnd(const ModulePtr&) +{ +} + +bool +Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p) +{ + string name = fixName(p); + ClassList bases = p->bases(); + OperationList ops = p->allOperations(); + OperationList::const_iterator r; + + _H << sp << nl << "@interface " << name << "Prx : ICEObjectPrx <" << name << "Prx>"; + _H << nl << "+(NSString *) ice_staticId;"; + + _M << sp << nl << "@implementation " << name << "Prx"; + for(r = ops.begin(); r != ops.end(); ++r) + { + string opName = getName(*r); + TypePtr returnType = (*r)->returnType(); + string retString = outTypeToString(returnType, (*r)->returnIsOptional()); + string params = getParams(*r); + string args = getArgs(*r); + + ParamDeclList inParams; + ParamDeclList outParams; + ParamDeclList paramList = (*r)->parameters(); + for(ParamDeclList::const_iterator pli = paramList.begin(); pli != paramList.end(); ++pli) + { + if((*pli)->isOutParam()) + { + outParams.push_back(*pli); + } + else + { + inParams.push_back(*pli); + } + } + + ContainerPtr container = (*r)->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + string className = fixName(cl); + + // + // Write context-less operation that forwards to the version with a context. + // + _M << sp << nl << "-(" << retString << ") " << opName << params; + _M << sb; + _M << nl; + if(returnType) + { + _M << "return "; + } + _M << "[self " << opName << args << (args.empty() ? ":nil" : " context:nil") << "];"; + _M << eb; + + // + // Write version with context. + // + _M << sp << nl << "-(" << retString << ") " << opName << params; + if(!params.empty()) + { + _M << " context"; + } + _M << ":(ICEContext *)ctx_"; + _M << sb; + if(returnType) + { + _M << nl << "__block " << retString << " ret_"; + if(!isValueType(returnType)) + { + _M << " = nil;"; + } + else + { + _M << ";"; + } + } + + string marshal; + string marshalArgs = getMarshalArgs(*r); + string marshalParams = getMarshalParams(*r); + if(!inParams.empty()) + { + _M << nl << "ICEMarshalCB marshal_ = ^(id<ICEOutputStream> os_) "; + _M << "{ [" << className << "Prx " << (*r)->name() << "_marshal___" << marshalArgs; + _M << (marshalArgs.empty() ? ":os_" : " os:os_") << "]; };"; + marshal = "marshal_"; + } + else + { + marshal = "nil"; + } + + string unmarshal; + string unmarshalArgs = getUnmarshalArgs(*r); + string unmarshalParams = getUnmarshalParams(*r); + if((*r)->returnsData()) + { + _M << nl << "ICEUnmarshalCB unmarshal_ = ^(id<ICEInputStream> is_, BOOL ok_) "; + if(returnType) + { + _M << "{ ret_ = "; + } + else + { + _M << "{ "; + } + _M << "[" << className << "Prx " << (*r)->name() << "_unmarshal___" << unmarshalArgs; + _M << (unmarshalArgs.empty() ? ":is_" : " is:is_") << " ok:ok_]; };"; + unmarshal = "unmarshal_"; + } + else + { + unmarshal = "nil"; + } + + _M << nl << "[self invoke__:@\"" << (*r)->name() << "\" mode:" << sliceModeToIceMode((*r)->sendMode()) + << " format:" << opFormatTypeToString(*r) << " marshal:" << marshal + << " unmarshal:" << unmarshal << " context:ctx_];"; + if(returnType) + { + _M << nl << "return ret_;"; + } + _M << eb; + + // + // Write begin_ context-less operation that forwards to the version with a context. + // + _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams; + _M << sb; + _M << nl << "return [self begin_" << (*r)->name() << marshalArgs; + _M << (marshalArgs.empty() ? "" : " context") << ":nil];"; + _M << eb; + + // + // Write begin_ version with context. + // + _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams; + _M << (marshalParams.empty() ? "" : " context") << ":(ICEContext *)ctx_"; + _M << sb; + if(!inParams.empty()) + { + _M << nl << "ICEMarshalCB marshal_ = ^(id<ICEOutputStream> os_) "; + _M << "{ [" << className << "Prx " << (*r)->name() << "_marshal___" << marshalArgs; + _M << (marshalArgs.empty() ? "" : " os") << ":os_]; };"; + } + _M << nl << "return [self begin_invoke__:@\"" << (*r)->name() << "\" mode:" + << sliceModeToIceMode((*r)->sendMode()) << " format:" << opFormatTypeToString(*r) + << " marshal:" << marshal + << " returnsData:" << ((*r)->returnsData() ? "YES" : "NO") + << " context:ctx_];"; + _M << eb; + + // + // Write end_ operation + // + _M << sp << nl << "-(" << retString << ") end_" << (*r)->name() << unmarshalParams; + if(!unmarshalParams.empty()) + { + _M << " result"; + } + _M << ":(id<ICEAsyncResult>)result_"; + _M << sb; + if(returnType) + { + _M << nl << "__block " << retString << " ret_"; + if(!isValueType(returnType)) + { + _M << " = nil;"; + } + else + { + _M << ";"; + } + } + if((*r)->returnsData()) + { + _M << nl << "ICEUnmarshalCB unmarshal_ = ^(id<ICEInputStream> is_, BOOL ok_) "; + if(returnType) + { + _M << "{ ret_ = "; + } + else + { + _M << "{ "; + } + _M << "[" << className << "Prx " << (*r)->name() << "_unmarshal___" << unmarshalArgs; + _M << (unmarshalArgs.empty() ? ":is_" : " is:is_") << " ok:ok_]; };"; + } + _M << nl << "[self end_invoke__:@\"" << (*r)->name() << "\" unmarshal:" << unmarshal << " result:result_];"; + if(returnType) + { + _M << nl << "return ret_;"; + } + _M << eb; + + // + // Write begin_ operations with callbacks + // + string responseCBSig = getResponseCBSig(*r); + + _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams; + _M << (marshalParams.empty() ? "" : " response") << ":(" << responseCBSig << ")response_"; + _M << " exception:(void(^)(ICEException*))exception_"; + _M << sb; + _M << nl << "return [self begin_" << (*r)->name() << marshalArgs; + _M << (marshalArgs.empty() ? "" : " context") << ":nil response:response_ exception:exception_ sent:nil];"; + _M << eb; + + _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams; + _M << (marshalParams.empty() ? "" : " response") << ":(" << responseCBSig << ")response_"; + _M << " exception:(void(^)(ICEException*))exception_ sent:(void(^)(BOOL))sent_"; + _M << sb; + _M << nl << "return [self begin_" << (*r)->name() << marshalArgs; + _M << (marshalArgs.empty() ? "" : " context") << ":nil response:response_ exception:exception_ sent:sent_];"; + _M << eb; + + _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams; + _M << (marshalParams.empty() ? "" : " context") << ":(ICEContext*)ctx_"; + _M << " response:(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_ "; + _M << sb; + _M << nl << "return [self begin_" << (*r)->name() << marshalArgs; + _M << (marshalArgs.empty() ? "" : " context") << ":ctx_ response:response_ exception:exception_ sent:nil];"; + _M << eb; + + _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams; + _M << (marshalParams.empty() ? "" : " context") << ":(ICEContext*)ctx_"; + _M << " response:(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_ "; + _M << " sent:(void(^)(BOOL))sent_"; + _M << sb; + if(!inParams.empty()) + { + _M << nl << "ICEMarshalCB marshal_ = ^(id<ICEOutputStream> os_) "; + _M << "{ [" << className << "Prx " << (*r)->name() << "_marshal___" << marshalArgs; + _M << (marshalArgs.empty() ? "" : " os") << ":os_]; };"; + } + if((*r)->returnsData()) + { + _M << nl << "void(^completed_)(id<ICEInputStream>, BOOL) = ^(id<ICEInputStream> is_, BOOL ok_)"; + _M << sb; + string responseCallArgs; + string unmarshalCallArgs; + if(!outParams.empty() || returnType) + { + if(returnType) + { + responseCallArgs += "ret_"; + } + + for(ParamDeclList::const_iterator op = outParams.begin(); op != outParams.end(); ++op) + { + string name = fixId((*op)->name()); + _M << nl << outTypeToString((*op)->type(), (*op)->optional(), true) << " " << name; + if(!isValueType((*op)->type())) + { + _M << " = nil"; + } + _M << ";"; + + if(!unmarshalCallArgs.empty()) + { + unmarshalCallArgs += " " + name; + } + unmarshalCallArgs += ":&" + name; + + if(!responseCallArgs.empty()) + { + responseCallArgs += ", "; + } + responseCallArgs += name; + } + if(returnType) + { + _M << nl << outTypeToString(returnType, (*r)->returnIsOptional(), true) << " ret_"; + if(!isValueType(returnType)) + { + _M << " = nil"; + } + _M << ";"; + } + } + _M << nl << "@try"; + _M << sb; + _M << nl; + if(returnType) + { + _M << "ret_ = "; + } + _M << "[" << className << "Prx " << (*r)->name() << "_unmarshal___" << unmarshalCallArgs; + _M << (unmarshalCallArgs.empty() ? ":is_" : " is:is_") << " ok:ok_];"; + _M << eb; + _M << nl << "@catch(ICEException* ex)"; + _M << sb; + _M << nl << "if(exception_)"; + _M << sb; + _M << nl << "exception_(ex);"; + _M << eb; + _M << nl << "return;"; + _M << eb; + _M << nl << "if(response_)"; + _M << sb; + _M << nl << "response_(" << responseCallArgs << ");"; + _M << eb; + _M << eb << ";"; + if(returnType || !outParams.empty()) + { + _M << nl << "return [self begin_invoke__:@\"" << (*r)->name() << "\" mode:" + << sliceModeToIceMode((*r)->sendMode()) << " format:" << opFormatTypeToString(*r) + << " marshal:" << marshal + << " completed:completed_ response:(response_ != nil) exception:exception_ sent:sent_ context:ctx_];"; + } + else + { + _M << nl << "return [self begin_invoke__:@\"" << (*r)->name() << "\" mode:" + << sliceModeToIceMode((*r)->sendMode()) << " format:" << opFormatTypeToString(*r) + << " marshal:" << marshal << " completed:completed_ response:YES exception:exception_ sent:sent_ context:ctx_];"; + } + } + else + { + _M << nl << "return [self begin_invoke__:@\"" << (*r)->name() << "\" mode:" + << sliceModeToIceMode((*r)->sendMode()) << " format:" << opFormatTypeToString(*r) + << " marshal:" << marshal << " response:response_ exception:exception_ sent:sent_ context:ctx_];"; + } + _M << eb; + } + + _M << sp << nl << "+(NSString *) ice_staticId"; + _M << sb; + _M << nl << "return @\"" << p->scoped() << "\";"; + _M << eb; + + return true; +} + +void +Slice::Gen::DelegateMVisitor::visitClassDefEnd(const ClassDefPtr& p) +{ + _H << nl << "@end"; + _M << nl << "@end"; +} + +void +Slice::Gen::DelegateMVisitor::visitOperation(const OperationPtr& p) +{ + TypePtr returnType = p->returnType(); + string retString = outTypeToString(returnType, p->returnIsOptional()); + string params = getParams(p); + string args = getParams(p); + string marshalParams = getMarshalParams(p); + string unmarshalParams = getUnmarshalParams(p); + + ParamDeclList inParams; + ParamDeclList outParams; + ParamDeclList paramList = p->parameters(); + for(ParamDeclList::const_iterator pli = paramList.begin(); pli != paramList.end(); ++pli) + { + if((*pli)->isOutParam()) + { + outParams.push_back(*pli); + } + else + { + inParams.push_back(*pli); + } + } + + // + // Write class method to invoke each operation. + // + ContainerPtr container = p->container(); + ClassDefPtr cl = ClassDefPtr::dynamicCast(container); + string className = fixName(cl); + if(!inParams.empty()) + { + _H << nl << "+(void) " << p->name() << "_marshal___" << marshalParams; + if(!marshalParams.empty()) + { + _H << " os"; + } + _H << ":(id<ICEOutputStream>)os_;"; + + _M << sp << nl << "+(void) " << p->name() << "_marshal___" << marshalParams; + if(!marshalParams.empty()) + { + _M << " os"; + } + _M << ":(id<ICEOutputStream>)os_"; + _M << sb; + writeMarshalUnmarshalParams(inParams, 0, true); + if(p->sendsClasses(false)) + { + _M << nl << "[os_ writePendingObjects];"; + } + _M << eb; + } + + if(p->returnsData()) + { + _H << nl << "+(" << retString << ")" << p->name() << "_unmarshal___" << unmarshalParams; + if(!unmarshalParams.empty()) + { + _H << " is"; + } + _H << ":(id<ICEInputStream>)is_ ok:(BOOL)ok_;"; + + _M << nl << "+(" << retString << ")" << p->name() << "_unmarshal___" << unmarshalParams; + if(!unmarshalParams.empty()) + { + _M << " is"; + } + _M << ":(id<ICEInputStream>)is_ ok:(BOOL)ok_"; + _M << sb; + if(returnType) + { + _M << nl << outTypeToString(returnType, p->returnIsOptional(), true) << " ret_"; + if(!isValueType(returnType)) + { + _M << " = nil;"; + } + else + { + _M << ";"; + } + } + if(p->returnsData()) + { + for(ParamDeclList::const_iterator op = outParams.begin(); op != outParams.end(); ++op) + { + if(!isValueType((*op)->type())) + { + _M << nl << "*" << fixId((*op)->name()) << " = nil;"; + } + } + } + _M << nl << "if(!ok_)"; + _M << sb; + _M << nl << "@try"; + _M << sb; + _M << nl << "[is_ startEncapsulation];"; + _M << nl << "[is_ throwException];"; + _M << eb; + // + // Arrange exceptions into most-derived to least-derived order. If we don't + // do this, a base exception handler can appear before a derived exception + // handler, causing compiler warnings and resulting in the base exception + // being marshaled instead of the derived exception. + // + ExceptionList throws = p->throws(); + throws.sort(); + throws.unique(); + throws.sort(Slice::DerivedToBaseCompare()); + + for(ExceptionList::const_iterator e = throws.begin(); e != throws.end(); ++e) + { + _M << nl << "@catch(" << fixName(*e) << " *ex_)"; + _M << sb; + _M << nl << "[is_ endEncapsulation];"; + _M << nl << "@throw;"; + _M << eb; + } + _M << nl << "@catch(ICEUserException *ex_)"; + _M << sb; + _M << nl << "[is_ endEncapsulation];"; + _M << nl << "@throw [ICEUnknownUserException unknownUserException:__FILE__ line:__LINE__ " + << "unknown:[ex_ ice_name]];"; + _M << eb; + _M << eb; + + if(returnType || !outParams.empty()) + { + _M << nl << "else"; + _M << sb; + _M << nl << "[is_ startEncapsulation];"; + writeMarshalUnmarshalParams(outParams, p, false, true); + if(p->returnsClasses(false)) + { + _M << nl << "[is_ readPendingObjects];"; + } + _M << nl << "[is_ endEncapsulation];"; + _M << eb; + } + + if(returnType) + { + _M << nl << "return ret_;"; + } + _M << eb; + } +} + diff --git a/cpp/src/slice2objc/Gen.h b/cpp/src/slice2objc/Gen.h new file mode 100644 index 00000000000..2126057137e --- /dev/null +++ b/cpp/src/slice2objc/Gen.h @@ -0,0 +1,186 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#ifndef GEN_H +#define GEN_H + +#include <Slice/ObjCUtil.h> + +namespace Slice +{ + + +class ObjCVisitor : public ObjCGenerator, public ParserVisitor +{ +public: + + ObjCVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&); + virtual ~ObjCVisitor(); + +protected: + + virtual void writeDispatchAndMarshalling(const ClassDefPtr&); + virtual void writeMarshalUnmarshalParams(const ParamDeclList&, const OperationPtr&, bool, bool = false); + virtual std::string getName(const OperationPtr&) const; + virtual std::string getSelector(const OperationPtr&) const; + virtual std::string getParams(const OperationPtr&) const; + virtual std::string getMarshalParams(const OperationPtr&) const; + virtual std::string getUnmarshalParams(const OperationPtr&) const; + virtual std::string getServerParams(const OperationPtr&) const; + virtual std::string getResponseCBSig(const OperationPtr&) const; + virtual std::string getArgs(const OperationPtr&) const; + virtual std::string getMarshalArgs(const OperationPtr&) const; + virtual std::string getUnmarshalArgs(const OperationPtr&) const; + virtual std::string getServerArgs(const OperationPtr&) const; + + ::IceUtilInternal::Output& _H; + ::IceUtilInternal::Output& _M; +}; + +class Gen : private ::IceUtil::noncopyable +{ +public: + + Gen(const std::string&, + const std::string&, + const std::string&, + const std::vector<std::string>&, + const std::string&); + ~Gen(); + + bool operator!() const; // Returns true if there was a constructor error + + void generate(const UnitPtr&); + void closeOutput(); + +private: + + IceUtilInternal::Output _H; + IceUtilInternal::Output _M; + + std::string _base; + std::string _include; + std::vector<std::string> _includePaths; + + void printHeader(::IceUtilInternal::Output&); + + class UnitVisitor : public ObjCVisitor + { + public: + + UnitVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&); + + virtual bool visitModuleStart(const ModulePtr&); + virtual void visitUnitEnd(const UnitPtr&); + + private: + + std::vector<Slice::ObjCGenerator::ModulePrefix> _prefixes; + }; + + class ObjectDeclVisitor : public ObjCVisitor + { + public: + + ObjectDeclVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&); + + virtual void visitClassDecl(const ClassDeclPtr&); + }; + + class ProxyDeclVisitor : public ObjCVisitor + { + public: + + ProxyDeclVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&); + + virtual void visitClassDecl(const ClassDeclPtr&); + }; + + class TypesVisitor : public ObjCVisitor + { + public: + + TypesVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&); + + virtual bool visitModuleStart(const ModulePtr&); + virtual void visitModuleEnd(const ModulePtr&); + virtual bool visitClassDefStart(const ClassDefPtr&); + virtual void visitOperation(const OperationPtr&); + virtual void visitClassDefEnd(const ClassDefPtr&); + virtual bool visitExceptionStart(const ExceptionPtr&); + virtual void visitExceptionEnd(const ExceptionPtr&); + virtual bool visitStructStart(const StructPtr&); + virtual void visitStructEnd(const StructPtr&); + virtual void visitSequence(const SequencePtr&); + virtual void visitDictionary(const DictionaryPtr&); + virtual void visitEnum(const EnumPtr&); + virtual void visitConst(const ConstPtr&); + + private: + + enum Escape { NoEscape, WithEscape }; + enum ContainerType { LocalException, Other }; + + void writeConstantValue(IceUtilInternal::Output&, const TypePtr&, const std::string&) const; + void writeMembers(const DataMemberList&, int) const; + void writeMemberSignature(const DataMemberList&, int, ContainerType) const; + void writeMemberCall(const DataMemberList&, int, ContainerType, Escape) const; + void writeMemberDefaultValueInit(const DataMemberList&, int) const; + void writeMemberInit(const DataMemberList&, int) const; + void writeProperties(const DataMemberList&, int) const; + void writeSynthesize(const DataMemberList&, int) const; + void writeOptionalDataMemberSelectors(const DataMemberList&, int) const; + void writeMemberHashCode(const DataMemberList&, int) const; + void writeMemberEquals(const DataMemberList&, int) const; + void writeMemberDealloc(const DataMemberList&, int, bool slicedData = false) const; + void writeMemberMarshal(const DataMemberList&, const DataMemberList&, int) const; + void writeMemberUnmarshal(const DataMemberList&, const DataMemberList&, int) const; + }; + + class ProxyVisitor : public ObjCVisitor + { + public: + + ProxyVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + virtual void visitClassDefEnd(const ClassDefPtr&); + virtual void visitOperation(const OperationPtr&); + }; + + class HelperVisitor : public ObjCVisitor + { + public: + + HelperVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&); + + virtual bool visitClassDefStart(const ClassDefPtr&); + virtual void visitEnum(const EnumPtr&); + virtual void visitSequence(const SequencePtr&); + virtual void visitDictionary(const DictionaryPtr&); + virtual bool visitStructStart(const StructPtr&); + }; + + class DelegateMVisitor : public ObjCVisitor + { + public: + + DelegateMVisitor(::IceUtilInternal::Output&, ::IceUtilInternal::Output&); + + virtual bool visitModuleStart(const ModulePtr&); + virtual void visitModuleEnd(const ModulePtr&); + virtual bool visitClassDefStart(const ClassDefPtr&); + virtual void visitClassDefEnd(const ClassDefPtr&); + virtual void visitOperation(const OperationPtr&); + }; +}; + +} + +#endif diff --git a/cpp/src/slice2objc/Main.cpp b/cpp/src/slice2objc/Main.cpp new file mode 100644 index 00000000000..529c54134b2 --- /dev/null +++ b/cpp/src/slice2objc/Main.cpp @@ -0,0 +1,290 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceUtil/Options.h> +#include <Slice/Preprocessor.h> +#include <Slice/FileTracker.h> +#include <IceUtil/CtrlCHandler.h> +#include <IceUtil/Mutex.h> +#include <IceUtil/MutexPtrLock.h> +#include <Slice/Util.h> +#include <Gen.h> + +using namespace std; +using namespace Slice; + +namespace +{ + +IceUtil::Mutex* globalMutex = 0; +bool interrupted = false; + +class Init +{ +public: + + Init() + { + globalMutex = new IceUtil::Mutex; + } + + ~Init() + { + delete globalMutex; + globalMutex = 0; + } +}; + +Init init; + +} + +void +interruptedCallback(int signal) +{ + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(globalMutex); + interrupted = true; +} + +void +usage(const char* n) +{ + cerr << "Usage: " << n << " [options] slice-files...\n"; + cerr << + "Options:\n" + "-h, --help Show this message.\n" + "-v, --version Display the Ice version.\n" + "-DNAME Define NAME as 1.\n" + "-DNAME=DEF Define NAME as DEF.\n" + "-UNAME Remove any definition for NAME.\n" + "-IDIR Put DIR in the include file search path.\n" + "-E Print preprocessor output on stdout.\n" + "--include-dir DIR Use DIR as the header include directory in source files.\n" + "--output-dir DIR Create files in the directory DIR.\n" + "--depend Generate Makefile dependencies.\n" + "--depend-xml Generate dependencies in XML format.\n" + "-d, --debug Print debug messages.\n" + "--ice Permit `Ice' prefix (for building Ice source code only)\n" + "--underscore Permit underscores in Slice identifiers.\n" + ; + // Note: --case-sensitive is intentionally not shown here! +} + +int +main(int argc, char* argv[]) +{ + IceUtilInternal::Options opts; + opts.addOpt("h", "help"); + opts.addOpt("v", "version"); + opts.addOpt("D", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); + opts.addOpt("U", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); + opts.addOpt("I", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); + opts.addOpt("E"); + opts.addOpt("", "include-dir", IceUtilInternal::Options::NeedArg); + opts.addOpt("", "output-dir", IceUtilInternal::Options::NeedArg); + opts.addOpt("", "depend"); + opts.addOpt("", "depend-xml"); + opts.addOpt("d", "debug"); + opts.addOpt("", "ice"); + opts.addOpt("", "underscore"); + opts.addOpt("", "case-sensitive"); + + vector<string> args; + try + { + args = opts.parse(argc, (const char**)argv); + } + catch(const IceUtilInternal::BadOptException& e) + { + cerr << argv[0] << ": " << e.reason << endl; + usage(argv[0]); + return EXIT_FAILURE; + } + + if(opts.isSet("help")) + { + usage(argv[0]); + return EXIT_SUCCESS; + } + + if(opts.isSet("version")) + { + cout << ICE_STRING_VERSION << endl; + return EXIT_SUCCESS; + } + + vector<string> cppArgs; + vector<string> optargs = opts.argVec("D"); + vector<string>::const_iterator i; + for(i = optargs.begin(); i != optargs.end(); ++i) + { + cppArgs.push_back("-D" + *i); + } + + optargs = opts.argVec("U"); + for(i = optargs.begin(); i != optargs.end(); ++i) + { + cppArgs.push_back("-U" + *i); + } + + vector<string> includePaths = opts.argVec("I"); + for(i = includePaths.begin(); i != includePaths.end(); ++i) + { + cppArgs.push_back("-I" + Preprocessor::normalizeIncludePath(*i)); + } + + bool preprocess = opts.isSet("E"); + + string include = opts.optArg("include-dir"); + + string output = opts.optArg("output-dir"); + + bool depend = opts.isSet("depend"); + bool dependxml = opts.isSet("depend-xml"); + + bool debug = opts.isSet("debug"); + + bool ice = opts.isSet("ice"); + + bool underscore = opts.isSet("underscore"); + + if(args.empty()) + { + getErrorStream() << argv[0] << ": no input file" << endl; + usage(argv[0]); + return EXIT_FAILURE; + } + + int status = EXIT_SUCCESS; + + if(dependxml) + { + cout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<dependencies>" << endl; + } + + IceUtil::CtrlCHandler ctrlCHandler; + ctrlCHandler.setCallback(interruptedCallback); + + for(i = args.begin(); i != args.end(); ++i) + { + if(depend || dependxml) + { + PreprocessorPtr icecpp = Preprocessor::create(argv[0], *i, cppArgs); + FILE* cppHandle = icecpp->preprocess(false, "-D__SLICE2OBJC__"); + + if(cppHandle == 0) + { + return EXIT_FAILURE; + } + + UnitPtr u = Unit::createUnit(false, false, ice, underscore); + int parseStatus = u->parse(*i, cppHandle, debug); + u->destroy(); + + if(parseStatus == EXIT_FAILURE) + { + return EXIT_FAILURE; + } + + if(!icecpp->printMakefileDependencies(depend ? Preprocessor::ObjC : Preprocessor::JavaXML, + includePaths, "-D__SLICE2OBJC__")) + { + return EXIT_FAILURE; + } + + if(!icecpp->close()) + { + return EXIT_FAILURE; + } + } + else + { + PreprocessorPtr icecpp = Preprocessor::create(argv[0], *i, cppArgs); + FILE* cppHandle = icecpp->preprocess(false, "-D__SLICE2OBJC__"); + + if(cppHandle == 0) + { + return EXIT_FAILURE; + } + + if(preprocess) + { + char buf[4096]; + while(fgets(buf, static_cast<int>(sizeof(buf)), cppHandle) != NULL) + { + if(fputs(buf, stdout) == EOF) + { + return EXIT_FAILURE; + } + } + if(!icecpp->close()) + { + return EXIT_FAILURE; + } + } + else + { + UnitPtr u = Unit::createUnit(false, false, ice, underscore); + int parseStatus = u->parse(*i, cppHandle, debug); + + if(!icecpp->close()) + { + u->destroy(); + return EXIT_FAILURE; + } + + if(parseStatus == EXIT_FAILURE) + { + status = EXIT_FAILURE; + } + else + { + try + { + Gen gen(argv[0], icecpp->getBaseName(), include, includePaths, output); + if(!gen) + { + u->destroy(); + return EXIT_FAILURE; + } + gen.generate(u); + } + catch(const Slice::FileException& ex) + { + // If a file could not be created, then + // cleanup any created files. + FileTracker::instance()->cleanup(); + u->destroy(); + getErrorStream() << argv[0] << ": error: " << ex.reason() << endl; + return EXIT_FAILURE; + } + } + + u->destroy(); + } + } + + { + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(globalMutex); + + if(interrupted) + { + FileTracker::instance()->cleanup(); + return EXIT_FAILURE; + } + } + } + + if(dependxml) + { + cout << "</dependencies>\n"; + } + + return status; +} diff --git a/cpp/src/slice2objc/Makefile b/cpp/src/slice2objc/Makefile new file mode 100644 index 00000000000..bd540f310b2 --- /dev/null +++ b/cpp/src/slice2objc/Makefile @@ -0,0 +1,31 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = ../.. + +NAME = $(bindir)/slice2objc$(EXE_EXT) + +TARGETS = $(NAME) + +OBJS = Gen.o \ + Main.o + +RPATH_DIR = $(LOADER_PATH)/../$(libsubdir) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. $(CPPFLAGS) + +$(NAME): $(OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(OBJS) $(SLICE_LIBS) $(MCPP_RPATH_LINK) + +install:: all + $(call installprogram,$(NAME),$(DESTDIR)$(install_bindir)) + $(call installdata,$(top_srcdir)/../man/man1/slice2objc.1,$(DESTDIR)$(install_mandir)) diff --git a/demoscript/Util.py b/demoscript/Util.py index 6f6412f0699..88767def2a9 100644 --- a/demoscript/Util.py +++ b/demoscript/Util.py @@ -292,7 +292,7 @@ def configurePaths(): # Setting the library path is necessary for interpreters to find # the IceSSL library. # - if not isWin32() and iceHome != "/usr" and getMapping() in ["py", "rb", "php"]: + if not isWin32() and iceHome != "/usr" and getMapping() in ["py", "rb", "php", "objc"]: libDir = os.path.join(getIceDir("cpp"), "lib") if isUbuntu(): libDir = os.path.join(libDir, "x86_64-linux-gnu" if x64 else "i386-linux-gnu") @@ -731,7 +731,7 @@ def spawn(command, cwd = None, mapping = None): command = command.replace("java", "java -d64", 1) if javaCmd != "java": command = command.replace("java", javaCmd, 1) - elif mapping == "cpp": + elif (mapping == "cpp" or mapping == "objc"): if cwd != None: desc = os.path.join(cwd, desc) if isWin32(): diff --git a/man/man1/slice2objc.1 b/man/man1/slice2objc.1 new file mode 100644 index 00000000000..64672953a8c --- /dev/null +++ b/man/man1/slice2objc.1 @@ -0,0 +1,127 @@ +.TH slice2objc 1 + +.SH NAME + +slice2objc - The Slice to Objective-C compiler. + +.SH SYNOPSIS + +slice2objc [options] [files] + +.SH DESCRIPTION + +slice2objc compiles Slice files to Objective-C. + +Full documentation for slice2objc is available online at: +.br +"http://doc.zeroc.com/display/Ice/slice2objc+Command-Line+Options". + +.SH OPTIONS + +.TP +.BR \-h ", " \-\-help\fR +.br +Displays help message. + +.TP +.BR \-v ", " \-\-version\fR +Displays the compiler version. + +.TP +.BR \-DNAME\fR +.br +Defines the preprocessor symbol NAME. + +.TP +.BR \-DNAME=DEF\fR +.br +Defines the preprocessor symbol NAME with the value DEF. + +.TP +.BR \-UNAME\fR +.br +Undefines the preprocessor symbol NAME. + +.TP +.BR \-IDIR\fR +.br +Add the directory DIR to the search path for #include directives. + +.TP +.BR \-E\fR +.br +Print the preprocessor output on stdout. + +.TP +.BR \-\-output-dir " " DIR\fR +.br +Place the generated files into directory DIR. + +.TP +.BR \-d ", " \-\-debug\fR +.br +Print debug information showing the operation of the Slice parser. + +.TP +.BR \-\-ice\fR +.br +Permit use of the normally reserved prefix Ice for identifiers. Use this +option only when compiling the source code for the Ice run time. + +.TP +.BR \-\-underscore\fR +.br +Permit use of underscores in Slice identifiers. + +.TP +.BR \-\-header-ext " " EXT\fR +.br +Changes the file extension for the generated header files from the default h +to EXT. + +.TP +.BR \-\-source-ext " " EXT\fR +.br +Changes the file extension for the generated source files from the default +m to EXT. + +.TP +.BR \-\-add-header " " HDR[,GUARD] +.br +This option adds an include directive for the specified header at the +beginning of the generated source file (preceding any other include +directives). If GUARD is specified, the include directive is protected by the +specified guard. + +.TP +.BR \-\-include-dir " " DIR\fR +.br +Modifies #include directives in source files to prepend the path name of each +header file with the directory DIR. + +.TP +.BR \-\-impl\fR +.br +Generate sample implementation files. This option will not overwrite an +existing file. + +.TP +.BR \-\-depend\fR +Prints makefile dependency information to standard output. + +.TP +.BR \-\-checksum\fR +.br +Generate checksums for Slice definitions. + +.SH SEE ALSO + +.BR slice2cpp (1), +.BR slice2cs (1), +.BR slice2freeze (1), +.BR slice2freezej (1), +.BR slice2html (1), +.BR slice2java (1), +.BR slice2php (1), +.BR slice2py (1), +.BR slice2rb (1) diff --git a/objc/Makefile b/objc/Makefile new file mode 100644 index 00000000000..23a6e75bb65 --- /dev/null +++ b/objc/Makefile @@ -0,0 +1,53 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = . + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = src include + +ifneq ($(MAKECMDGOALS),install) + SUBDIRS := $(SUBDIRS) test demo +endif + +INSTALL_SUBDIRS = $(install_libdir)$(cpp11libdirsuffix) $(install_includedir) + +install:: install-common + @for subdir in $(INSTALL_SUBDIRS); \ + do \ + if test ! -d $(DESTDIR)$$subdir ; \ + then \ + echo "Creating $(DESTDIR)$$subdir..." ; \ + mkdir -p $(DESTDIR)$$subdir ; \ + chmod a+rx $(DESTDIR)$$subdir ; \ + fi ; \ + done +ifeq ($(create_runpath_symlink),yes) + @if test -h $(embedded_runpath_prefix) ; \ + then \ + if `\rm -f $(embedded_runpath_prefix) 2>/dev/null`; \ + then echo "Removed symbolic link $(embedded_runpath_prefix)"; fi \ + fi + @if ! test -d $(embedded_runpath_prefix) ; \ + then \ + if `ln -s $(prefix) $(embedded_runpath_prefix) 2>/dev/null`; \ + then echo "Created symbolic link $(embedded_runpath_prefix) --> $(prefix)"; fi \ + fi +endif + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done + +test:: + @python $(top_srcdir)/allTests.py diff --git a/objc/allDemos.py b/objc/allDemos.py new file mode 100755 index 00000000000..56b8230a2f9 --- /dev/null +++ b/objc/allDemos.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +for toplevel in [".", "..", "../..", "../../..", "../../../.."]: + toplevel = os.path.abspath(toplevel) + if os.path.exists(os.path.join(toplevel, "demoscript")): + break +else: + raise RuntimeError("can't find toplevel directory!") + +sys.path.append(os.path.join(toplevel)) +from demoscript import Util + +# +# List of all basic demos. +# +demos = [ + "Ice/hello", + "Ice/minimal", + "Manual/simple_filesystem", + "Manual/printer"] + +if __name__ == "__main__": + Util.run(demos) diff --git a/objc/allTests.py b/objc/allTests.py new file mode 100755 index 00000000000..60b114d195c --- /dev/null +++ b/objc/allTests.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +import os, sys, re, getopt + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") + +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +# +# List of all basic tests. +# +tests = [ + ("Slice/keyword", []), + ("Ice/proxy", ["core"]), + ("Ice/ami", ["core"]), + ("Ice/operations", ["core"]), + ("Ice/exceptions", ["core"]), + ("Ice/inheritance", ["core"]), + ("Ice/invoke", ["core"]), + ("Ice/metrics", ["core", "nossl", "noipv6", "nocompress"]), + ("Ice/facets", ["core"]), + ("Ice/objects", ["core"]), + ("Ice/optional", ["core"]), + ("Ice/interceptor", ["core"]), + ("Ice/dispatcher", ["core"]), + ("Ice/defaultServant", ["core"]), + ("Ice/defaultValue", ["core"]), + ("Ice/binding", ["core"]), + ("Ice/stream", ["core"]), + ("Ice/hold", ["core"]), + ("Ice/faultTolerance", ["core"]), + ("Ice/location", ["core"]), + ("Ice/adapterDeactivation", ["core"]), + ("Ice/slicing/exceptions", ["core"]), + ("Ice/slicing/objects", ["core"]), + ("Ice/retry", ["core"]), + ("Ice/timeout", ["core"]), + ("Ice/hash", ["core"]), + ("Ice/info", ["core", "noipv6", "nocompress"]), + ("Ice/enums", ["once"]), + ] + +if __name__ == "__main__": + TestUtil.run(tests) diff --git a/objc/config/Make.rules b/objc/config/Make.rules new file mode 100644 index 00000000000..cd0847e0612 --- /dev/null +++ b/objc/config/Make.rules @@ -0,0 +1,194 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described +# in the ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +# +# Select an installation base directory. The directory will be created +# if it does not exist. +# +prefix ?= /opt/Ice-$(VERSION) + +# +# Define OPTIMIZE as yes if you want to build with +# optimization. Otherwise Ice is build with debug information. +# +#OPTIMIZE = yes + +# +# The "root directory" for runpath embedded in executables. Can be set +# to change the runpath added to Ice executables. The default is +# platform dependent. +# +#embedded_runpath_prefix ?= /opt/Ice-$(VERSION_MAJOR).$(VERSION_MINOR) + +# +# Define create_runpath_symlink as yes if you would like 'make install' +# to automatically create a symbolic link for the embedded runpath +# directory. Only applies if embedded_runpath_prefix is also set. +# +create_runpath_symlink ?= no + +# +# Define embedded_runpath as no if you don't want any RPATH added to +# the executables. +# +embedded_runpath ?= yes + +# +# The build architectures for gcc/llvm based builds. The format of +# these build flags are OS dependent. For example, under OS X to +# build binaries which support both i386 and x86_64 you would use +# "-arch i386 -arch x86_64". The default is OS version dependent. Be +# aware that this value may conflict with the setting of LP64 above. +# +#OBJCARCHFLAGS = -arch i386 -arch x86_64 + +# ---------------------------------------------------------------------- +# Don't change anything below this line! +# ---------------------------------------------------------------------- + +# +# Common definitions +# +ice_language = objc +slice_translator = slice2objc + +ifeq ($(shell test -f $(top_srcdir)/config/Make.common.rules && echo 0),0) + include $(top_srcdir)/config/Make.common.rules +else + include $(top_srcdir)/../config/Make.common.rules +endif + +bindir = $(top_srcdir)/bin +ifdef ice_src_dist + libdir = $(top_srcdir)/lib + includedir = $(top_srcdir)/include +else + libdir = $(ice_dir)/$(libsubdir) + includedir = $(ice_dir)/include +endif +headerdir = $(top_srcdir)/include + +install_includedir := $(prefix)/include +install_libdir := $(prefix)/$(libsubdir) +install_bindir := $(prefix)/$(binsubdir) + +# +# Platform specific definitions +# +include $(top_srcdir)/config/Make.rules.$(UNAME) + +ICECPPFLAGS = -I$(slicedir) +SLICE2OBJCFLAGS = $(ICECPPFLAGS) +FLEXFLAGS = +BISONFLAGS = -dvt + +OBJDIR = . + +CPPFLAGS += -I$(includedir) +LDFLAGS = $(OBJCFLAGS) -L$(libdir) + +ifdef ice_src_dist + ifeq ($(ice_cpp_dir), $(ice_dir)/cpp) + SLICE2OBJC = $(ice_cpp_dir)/bin/slice2objc + else + SLICE2OBJC = $(ice_cpp_dir)/$(binsubdir)/slice2objc + endif +else + SLICE2OBJC = $(ice_dir)/$(binsubdir)/slice2objc +endif + +# This cannot use .cpp:.o as we have multiple types of source files. + +EVERYTHING = all clean install +EVERYTHING_EXCEPT_ALL = clean install + +.SUFFIXES: +.SUFFIXES: .mm .m .o .cpp .c + +ifneq ($(SLICE_OBJS),) +-include $(addprefix .depend/, $(SLICE_OBJS:.o=.ice.d)) +endif + +ifneq ($(OBJS),) +-include $(addprefix .depend/, $(OBJS:.o=.d)) +endif + +ifeq ($(wildcard .depend/*.d),) +ifneq ($(OBJCXX_OBJS),) +$(OBJS): $(OBJC_OBJS:.o=.m) $(OBJCXX_OBJS:.o=.mm) +else +$(OBJS): $(OBJS:.o=.m) +endif +endif + +all:: $(TARGETS) + +.m.o: + $(CC) -c $(ARCFLAGS) $(CPPFLAGS) $(OBJCFLAGS) $< + @mkdir -p .depend + @$(CXX) -DMAKEDEPEND -M $(CPPFLAGS) $< > .depend/$(*F).d + +.mm.o: + $(CXX) -c $(ARCFLAGS) $(CPPFLAGS) $(OBJCFLAGS) $< + @mkdir -p .depend + @$(CXX) -DMAKEDEPEND -M $(CPPFLAGS) $< > .depend/$(*F).d + +$(HDIR)/%F.h: $(SDIR)/%F.ice $(SLICE2OBJC) + rm -f $(HDIR)/$(*F)F.h $(*F)F.m + $(SLICE2OBJC) $(SLICE2OBJCFLAGS) $< + mv $(*F)F.h $(HDIR) + @touch $(*F)F.m + @mkdir -p .depend + @$(SLICE2OBJC) $(SLICE2OBJCFLAGS) --depend $< | $(ice_dir)/config/makedepend.py "\$$(HDIR)/" > .depend/$(*F)F.ice.d + +$(HDIR)/%.h %.m: $(SDIR)/%.ice $(SLICE2OBJC) + rm -f $(HDIR)/$(*F).h $(*F).m + $(SLICE2OBJC) $(SLICE2OBJCFLAGS) $< + mv $(*F).h $(HDIR) + @touch $(*F).m + @mkdir -p .depend + @$(SLICE2OBJC) $(SLICE2OBJCFLAGS) --depend $< | $(ice_dir)/config/makedepend.py "\$$(HDIR)/" > .depend/$(*F).ice.d + +%.h %.m: %.ice $(SLICE2OBJC) + rm -f $(*F).h $(*F).m + $(SLICE2OBJC) $(SLICE2OBJCFLAGS) $< + @touch $(*F).m + @mkdir -p .depend + @$(SLICE2OBJC) $(SLICE2OBJCFLAGS) --depend $(*F).ice > .depend/$(*F).ice.d + +%.h %.m: %.y + rm -f $(*F).h $(*F).c + bison $(BISONFLAGS) $< + mv $(*F).tab.c $(*F).m + mv $(*F).tab.h $(*F).h + rm -f $(*F).output + +%.m: %.l + flex $(FLEXFLAGS) $< + rm -f $@ + cat lex.yy.c >> $@ + rm -f lex.yy.c + +clean:: + -rm -f $(TARGETS) + -rm -f core *.o *.bak + -rm -rf .depend + +ifneq ($(SLICE_OBJS),) +clean:: + rm -f $(addsuffix .m, $(basename $(notdir $(SLICE_OBJS)))) + rm -f $(addsuffix .h, $(basename $(notdir $(SLICE_OBJS)))) +endif + +ifneq ($(HDIR),) +clean:: + rm -f $(addprefix $(HDIR)/, $(addsuffix .h, $(basename $(SLICE_OBJS)))) +endif + +install:: diff --git a/objc/config/Make.rules.Darwin b/objc/config/Make.rules.Darwin new file mode 100644 index 00000000000..af8d74ae7ae --- /dev/null +++ b/objc/config/Make.rules.Darwin @@ -0,0 +1,101 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +# +# This file is included by Make.rules when uname is Darwin. +# + +OSX_TARGET_MIN_SDK_VERSION = 10.9 + +CC = xcrun clang +CXX = xcrun clang++ + +CPPFLAGS += -pthread +OBJCFLAGS += -Wall -Werror -mmacosx-version-min=$(OSX_TARGET_MIN_SDK_VERSION) + + +# +# By default we build x86_64 binaries. +# +ifeq ($(OBJCARCHFLAGS),) +OBJCARCHFLAGS := -arch x86_64 +endif + +ifeq ($(OPTIMIZE),yes) + OBJCFLAGS := $(OBJCARCHFLAGS) -O2 -DNDEBUG $(OBJCFLAGS) +else + OBJCFLAGS := $(OBJCARCHFLAGS) -g $(OBJCFLAGS) +endif + +# +# If embedded_runpath is not set to yes we do not add +# an rpath dir. +# +ifeq ($(embedded_runpath),yes) + LOADER_PATH = @loader_path + + # + # If embedded_runpath_prefix is set it has preference + # + ifneq ($(embedded_runpath_prefix),) + RPATH_DIR = $(embedded_runpath_prefix) + endif + + ifeq ($(RPATH_DIR),) + ifdef ice_src_dist + RPATH_DIR = @loader_path/$(libdir) + else + RPATH_DIR = $(ice_dir)/$(libsubdir) + endif + endif + + # + # Clear rpath setting when doing a system install + # + ifeq ($(ice_dir),/usr) + RPATH_DIR = + endif + + ifneq ($(RPATH_DIR),) + LDEXEFLAGS = -Wl,-rpath,$(RPATH_DIR) + endif +endif + +ifdef ice_src_dist +rpathlink = -Wl,-rpath,$(1) +endif + +# +# Enable ARC for targets in demo/ and test/ subdirectories +# when COMPILE_WITH_ARC is defined. +# +ifneq ($(findstring demo/,${CURDIR}),) +TARGET_SUPPORT_ARC = yes +endif + +ifneq ($(findstring test/,${CURDIR}),) +TARGET_SUPPORT_ARC = yes +endif + +ifeq ($(TARGET_SUPPORT_ARC),yes) + ifeq ($(COMPILE_WITH_ARC),yes) + # + # Don't add these to OBJCFLAGS flex and bison generated files used in + # some demos doesn't support ARC. + # + ARCFLAGS = -fobjc-arc -fobjc-arc-exceptions + endif +endif + +mklib = libtool -static -o $(1) $(2) +mkshlib = $(CXX) -dynamiclib $(LDFLAGS) -o $(1) -install_name @rpath/$(2) $(3) $(4) + +BASELIBS = -L$(ice_cpp_dir)/$(libsubdir) -lIce -lIceUtil -framework Foundation +LIBS = -lIceObjC$(libsuffix) -framework Foundation +TEST_LIBS = -lTestCommon $(LIBS) diff --git a/objc/config/makegitignore.py b/objc/config/makegitignore.py new file mode 100755 index 00000000000..27e149c99db --- /dev/null +++ b/objc/config/makegitignore.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys, shutil, fnmatch, re, time, getopt + +# +# NOTE: This scripts generates .gitignore files in directories +# containing Makefile files with targets. The content of the +# .gitignore file is generated by parsing the output of make -n +# clean. +# +# In other words, the .gitignore file contains ignore rules for files +# produced by the Makefile and supposed to be cleaned by make clean. +# + +progname = os.path.basename(sys.argv[0]) +preamble = "// Generated by " + progname +preamble = preamble + """ + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +""" + +# +# Find files matching a pattern. +# +def find(path, patt): + result = [ ] + files = os.listdir(path) + for x in files: + fullpath = os.path.join(path, x); + if os.path.isdir(fullpath) and not os.path.islink(fullpath): + result.extend(find(fullpath, patt)) + elif fnmatch.fnmatch(x, patt): + result.append(fullpath) + return result + + +def createGitIgnore(filename, gitIgnoreFiles): + file = open(filename, "r") + lines = file.readlines() + cwd = os.getcwd() + cwdStack = [] # Working directory stack + newLines = [ ] + ignore = ["*.o", "*.bak", "core"] + + for x in lines: + x = x.strip() + if x.startswith("rm -f"): + x = x.replace("rm -f", "", 1) + elif x.startswith("rm -rf"): + x = x.replace("rm -rf", "", 1) + elif x.startswith("making clean in"): + # Don't clean sub-directories + break + else: + continue + + if len(x) == 0: + continue + + files = x.split() + for f in files: + if f in ignore: + continue + + if f.startswith(".."): + k = os.path.join(cwd, os.path.dirname(f), ".gitignore") + v = os.path.basename(f) + "\n" + else: + k = os.path.join(cwd, ".gitignore") + v = f + "\n" + + if v.find(".so.") > 0: + continue + elif v.endswith(".so\n"): + v = v.replace(".so", ".*") + elif v.endswith(".dylib\n"): + v = v.replace(".dylib", ".*") + if v.find('.', 0, len(v) - 3) > 0: + continue + + k = os.path.normpath(k) + if not gitIgnoreFiles.has_key(k): + gitIgnoreFiles[k] = [ ] + gitIgnoreFiles[k].append(v) + + file.close() + +def usage(): + print "Usage: " + sys.argv[0] + " [options]" + print + print "Options:" + print "-e Run for Ice-E." + print "-h Show this message." + print + +icee = False +try: + opts, args = getopt.getopt(sys.argv[1:], "he") +except getopt.GetoptError: + usage() + sys.exit(1) +for o, a in opts: + if o == "-h": + usage() + sys.exit(0) + elif o == "-e": + icee = True +if len(args) != 0: + usage() + sys.exit(1) + + +# +# Find where the root of the tree is. +# +for toplevel in [".", "..", "../..", "../../..", "../../../.."]: + toplevel = os.path.abspath(toplevel) + if os.path.exists(os.path.join(toplevel, "objc", "config", "makegitignore.py")): + break +else: + print("cannot find top-level directory") + sys.exit(1) + +makefiles = find(os.path.join(toplevel, "objc"), "Makefile") +cwd = os.getcwd() +gitIgnoreFiles = { } +for i in makefiles: + os.chdir(os.path.dirname(i)) + if not os.system('grep -q TARGETS Makefile'): + try: + os.system("make -n clean > .tmp-gitignore") + createGitIgnore(".tmp-gitignore", gitIgnoreFiles) + os.remove(".tmp-gitignore") + except: + os.remove(".tmp-gitignore") + raise + os.chdir(cwd) + +os.chdir(cwd) + +excludePath = [ os.path.join(toplevel, "objc", "bin"), os.path.join(toplevel, "objc", "lib") ] +for (path, files) in gitIgnoreFiles.iteritems(): + if os.path.dirname(path) in excludePath: + continue + if not os.path.exists(path): + print files + gitIgnore = open(path, "w") + gitIgnore.write(preamble); + gitIgnore.writelines(files) + gitIgnore.close() + diff --git a/objc/demo/Database/Makefile b/objc/demo/Database/Makefile new file mode 100644 index 00000000000..5c67c5fb6ea --- /dev/null +++ b/objc/demo/Database/Makefile @@ -0,0 +1,21 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = library + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done diff --git a/objc/demo/Database/README b/objc/demo/Database/README new file mode 100644 index 00000000000..2a61b68c0f7 --- /dev/null +++ b/objc/demo/Database/README @@ -0,0 +1,5 @@ +Demos in this directory: + +- library + + This demo is a client for the java Database/library JDBC demo. diff --git a/objc/demo/Database/library/.gitignore b/objc/demo/Database/library/.gitignore new file mode 100644 index 00000000000..d5e7554b52d --- /dev/null +++ b/objc/demo/Database/library/.gitignore @@ -0,0 +1,14 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +.depend +Library.m +Session.m +Glacier2Session.m +Library.h +Session.h +Glacier2Session.h +Grammar.m +Grammar.h +Scanner.m diff --git a/objc/demo/Database/library/Client.m b/objc/demo/Database/library/Client.m new file mode 100644 index 00000000000..0dca77cf622 --- /dev/null +++ b/objc/demo/Database/library/Client.m @@ -0,0 +1,57 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> + +#import <stdio.h> + + +int runParser(int, char**, id<ICECommunicator>); + +int +main(int argc, char* argv[]) +{ + int status = 0; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = [ICEUtil createProperties ]; + [initData.properties load: @"config.client" ]; + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + if(argc > 1) + { + fprintf(stderr, "%s: too many arguments\n", argv[0]); + return 1; + } + runParser(argc, argv, communicator); + } + @catch(ICELocalException* ex) + { + fprintf(stderr, "%s\n", [[ex description] UTF8String]); + status = 1; + } + + if(communicator != nil) + { + @try + { + [communicator destroy]; + } + @catch(ICELocalException* ex) + { + fprintf(stderr, "%s\n", [[ex description] UTF8String]); + status = 1; + } + } + } + return status; +} diff --git a/objc/demo/Database/library/Glacier2Session.ice b/objc/demo/Database/library/Glacier2Session.ice new file mode 100644 index 00000000000..1960983caef --- /dev/null +++ b/objc/demo/Database/library/Glacier2Session.ice @@ -0,0 +1,47 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Glacier2/Session.ice> + +module Demo +{ + +/* Forward declaration. */ +interface Library; + +/** + * + * The session object. This is used to retrieve a per-session library + * on behalf of the client. If the session is not refreshed on a + * periodic basis, it will be automatically destroyed. + * + */ +interface Glacier2Session extends Glacier2::Session +{ + /** + * + * Get the library object. + * + * @return A proxy for the new library. + * + **/ + Library* getLibrary(); + + /** + * + * Refresh a session. If a session is not refreshed on a regular + * basis by the client, it will be automatically destroyed. + * + **/ + idempotent void refresh(); +}; + +}; diff --git a/objc/demo/Database/library/Grammar.y b/objc/demo/Database/library/Grammar.y new file mode 100644 index 00000000000..c8a9015e243 --- /dev/null +++ b/objc/demo/Database/library/Grammar.y @@ -0,0 +1,131 @@ +%{ + +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Parser.h> + +void +yyerror(const char* s) +{ + [parser error: s]; +} + +%} + +%pure_parser + +%token TOK_HELP +%token TOK_EXIT +%token TOK_ADD_BOOK +%token TOK_FIND_ISBN +%token TOK_FIND_AUTHORS +%token TOK_FIND_TITLE +%token TOK_NEXT_FOUND_BOOK +%token TOK_PRINT_CURRENT +%token TOK_RENT_BOOK +%token TOK_RETURN_BOOK +%token TOK_REMOVE_CURRENT +%token TOK_STRING + +%% + +// ---------------------------------------------------------------------- +start +// ---------------------------------------------------------------------- +: commands +{ +} +| +{ +} +; + +// ---------------------------------------------------------------------- +commands +// ---------------------------------------------------------------------- +: commands command +{ +} +| command +{ +} +; + +// ---------------------------------------------------------------------- +command +// ---------------------------------------------------------------------- +: TOK_HELP ';' +{ + [parser usage]; +} +| TOK_EXIT ';' +{ + return 0; +} +| TOK_ADD_BOOK strings ';' +{ + [parser addBook: $2]; +} +| TOK_FIND_ISBN strings ';' +{ + [parser findIsbn: $2]; +} +| TOK_FIND_AUTHORS strings ';' +{ + [parser findAuthors: $2]; +} +| TOK_FIND_TITLE strings ';' +{ + [parser findTitle: $2]; +} +| TOK_NEXT_FOUND_BOOK ';' +{ + [parser nextFoundBook]; +} +| TOK_PRINT_CURRENT ';' +{ + [parser printCurrent]; +} +| TOK_RENT_BOOK strings ';' +{ + [parser rentCurrent: $2]; +} +| TOK_RETURN_BOOK ';' +{ + [parser returnCurrent]; +} +| TOK_REMOVE_CURRENT ';' +{ + [parser removeCurrent]; +} +| error ';' +{ + yyerrok; +} +| ';' +{ +} +; + +// ---------------------------------------------------------------------- +strings +// ---------------------------------------------------------------------- +: TOK_STRING strings +{ + $$ = $2; + [$$ addObject: [$1 objectAtIndex:0]]; +} +| TOK_STRING +{ + $$ = $1; +} +; + +%% diff --git a/objc/demo/Database/library/Library.ice b/objc/demo/Database/library/Library.ice new file mode 100644 index 00000000000..e4ed7f485f2 --- /dev/null +++ b/objc/demo/Database/library/Library.ice @@ -0,0 +1,285 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Ice/BuiltinSequences.ice> + +module Demo +{ + +/** + * + * This local exception is used internally if a java.sql.SQLException + * is raised. + * + **/ +local exception JDBCException +{ +}; + +/** + * + * This exception is raised if the book already exists. + * + **/ +exception BookExistsException +{ +}; + +/** + * + * This exception is raised if a book has already been rented. + * + **/ +exception BookRentedException +{ + string renter; +}; + +/** + * + * This exception is raised if a customer name is invalid. + * + **/ +exception InvalidCustomerException +{ +}; + +/** + * + * This exception is raised if the book has not been rented. + * + **/ +exception BookNotRentedException +{ +}; + +/** Forward declaration for the interface Book. */ +interface Book; + +/** + * + * A description of a book. + * + **/ +struct BookDescription +{ + /** The ISBN number of the book. */ + string isbn; + + /** The title of the book. */ + string title; + + /** The authors of the book. */ + ["java:type:java.util.LinkedList<String>:java.util.List<String>"] Ice::StringSeq authors; + + /** The customer name of the renter. */ + string rentedBy; + + /** A proxy to the associated book. */ + Book* proxy; +}; + +/** A sequence of book descriptions. */ +["java:type:java.util.LinkedList<BookDescription>:java.util.List<BookDescription>"] +sequence<BookDescription> BookDescriptionSeq; + +/** + * + * This interface represents a book. + * + **/ +interface Book +{ + /** + * + * Get a description of the book. + * + * @return The book description. + * + **/ + idempotent BookDescription describe(); + + /** + * + * Set the title of a book. + * + * @param title The book title. + * + **/ + void setTitle(string title); + + /** + * + * Set the book authors. + * + * @param authors The book authors. + * + **/ + void setAuthors(["java:type:java.util.LinkedList<String>:java.util.List<String>"] Ice::StringSeq authors); + + /** + * + * Rent the book to the specified customer. + * + * @param customer The customer. + * + * @throws BookRentedException Raised if the book has already been + * rented. + * + * @throws InvalidCustomerException Raised if the customer is invalid. + * + **/ + void rentBook(string name) + throws InvalidCustomerException, BookRentedException; + + /** + * + * Get the renter. + * + * @return The current rental customer. + * + * @throws BookNotRentedException Raised if the book is not + * currently rented. + * + **/ + idempotent string getRenter() + throws BookNotRentedException; + + /** + * + * Return the book. + * + * @throws BookNotRentedException Raised if the book is not + * currently rented. + * + **/ + void returnBook() + throws BookNotRentedException; + + /** + * + * Destroy the book. + * + **/ + void destroy(); +}; + +/** + * + * Interface to get query results. + * + **/ +interface BookQueryResult +{ + /** + * + * Get more query results. + * + * @param n The maximum number of results to return. + * + * @param destroyed There are no more results, and the query has + * been destroyed. + * + * @returns A sequence of up to n results. + * + **/ + BookDescriptionSeq next(int n, out bool destroyed); + + /** + * + * Destroy the query result. + * + **/ + void destroy(); +}; + +/** + * + * An interface to the library. + * + **/ +interface Library +{ + /** + * + * Query based on isbn number. The query is a partial match at the + * start of the isbn number. + * + * @param isbn The ISBN number. + * + * @param n The number of rows to retrieve in the initial request. + + * @param first The first set of results, up to n results. + * + * @param nrows The total number of rows. + * + * @param result The remainder of the results. If there are no + * further results, a null proxy is returned. + * + **/ + void queryByIsbn(string isbn, int n, out BookDescriptionSeq first, out int nrows, out BookQueryResult* result); + + /** + * + * Query based on the author name. The query is a partial match of + * the author's name. + * + * @param author The authors name. + * + * @param n The number of rows to retrieve in the initial request. + + * @param first The first set of results, up to n results. + * + * @param nrows The total number of rows. + * + * @param result The remainder of the results. If there are no + * further results, a null proxy is returned. + * + **/ + void queryByAuthor(string author, int n, out BookDescriptionSeq first, out int nrows, out BookQueryResult* result); + + /** + * + * Query based on the book title. The query is a partial match of + * the book title. + * + * @param author The authors name. + * + * @param n The number of rows to retrieve in the initial request. + + * @param first The first set of results, up to n results. + * + * @param nrows The total number of rows. + * + * @param result The remainder of the results. If there are no + * further results, a null proxy is returned. + * + **/ + void queryByTitle(string title, int n, out BookDescriptionSeq first, out int nrows, out BookQueryResult* result); + + /** + * + * Create a book with the given description. + * + * @param description The book description. + * + * @return A proxy for the new book. + * + * @throws BookExistsException Raised if a book with the same ISBN + * number already exists. + * + **/ + Book* createBook(string isbn, string title, + ["java:type:java.util.LinkedList<String>:java.util.List<String>"] Ice::StringSeq authors) + throws BookExistsException; +}; + +}; diff --git a/objc/demo/Database/library/Makefile b/objc/demo/Database/library/Makefile new file mode 100644 index 00000000000..63d1578c319 --- /dev/null +++ b/objc/demo/Database/library/Makefile @@ -0,0 +1,47 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client + +TARGETS = $(CLIENT) + +SLICE_OBJS = Library.o \ + Session.o \ + Glacier2Session.o + +COBJS = Client.o \ + Grammar.o \ + Scanner.o \ + Parser.o \ + RunParser.o + +OBJS = $(SLICE_OBJS) $(COBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. $(CPPFLAGS) + +# +# Flex and bison generated files doesn't support ARC. +# +Grammar.o: Grammar.m + $(CC) -c $(CPPFLAGS) $(OBJCFLAGS) $(CFLAGS) $< + +Scanner.o: Scanner.m + $(CC) -c $(CPPFLAGS) $(OBJCFLAGS) $(CFLAGS) $< + +$(CLIENT): $(SLICE_OBJS) $(COBJS) + rm -f $@ + $(CXX) $(LDFLAGS) -o $@ $(SLICE_OBJS) $(COBJS) -lGlacier2ObjC $(LIBS) + +clean:: + -rm -f Grammar.m Grammar.h + -rm -f Scanner.m diff --git a/objc/demo/Database/library/Parser.h b/objc/demo/Database/library/Parser.h new file mode 100644 index 00000000000..a96518c049a --- /dev/null +++ b/objc/demo/Database/library/Parser.h @@ -0,0 +1,80 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <Library.h> +#import <Foundation/NSArray.h> + +// +// Stuff for flex and bison +// + +#define YYSTYPE NSMutableArray* +#define YY_DECL int yylex(YYSTYPE* yylvalp) +YY_DECL; +int yyparse(); + +// +// I must set the initial stack depth to the maximum stack depth to +// disable bison stack resizing. The bison stack resizing routines use +// simple malloc/alloc/memcpy calls, which do not work for the +// YYSTYPE, since YYSTYPE is a C++ type, with constructor, destructor, +// assignment operator, etc. +// +#define YYMAXDEPTH 10000 // 10000 should suffice. Bison default is 10000 as maximum. +#define YYINITDEPTH YYMAXDEPTH // Initial depth is set to max depth, for the reasons described above. + +// +// Newer bison versions allow to disable stack resizing by defining +// yyoverflow. +// +#define yyoverflow(a, b, c, d, e, f) yyerror(a) + + +@interface Parser : NSObject +{ +@private + +DemoBookQueryResultPrx* query; +DemoBookDescription* current; +id<DemoLibraryPrx> library; + +BOOL cont; +int errors; +} + +-(id)initWithLibrary:(id<DemoLibraryPrx>) library; ++(id)parserWithLibrary:(id<DemoLibraryPrx>) library; + +-(void) usage; + +-(void) addBook:(NSArray*) data; +-(void) findIsbn:(NSArray*)data; +-(void) findAuthors:(NSArray*)data; +-(void) findTitle:(NSArray*)data; +-(void) nextFoundBook; +-(void) printCurrent; +-(void) rentCurrent:(NSArray*)data; +-(void) returnCurrent; +-(void) removeCurrent; + +-(int) getInput:(char*)buf max:(int)max; +-(void) continueLine; + +-(void) error:(const char*) s; +-(void) errorWithString:(NSString*) s; + +-(void) warning:(const char*) s; +-(void) warningWithString:(NSString*) s; + +-(int)parse; + +@end + +extern Parser* parser; // The current parser for bison/flex diff --git a/objc/demo/Database/library/Parser.m b/objc/demo/Database/library/Parser.m new file mode 100644 index 00000000000..d9f50abe999 --- /dev/null +++ b/objc/demo/Database/library/Parser.m @@ -0,0 +1,486 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <Parser.h> +#import <string.h> +#import <stdio.h> + +extern FILE* yyin; +Parser* parser; + +@interface Parser() + +@property(nonatomic, retain) DemoBookQueryResultPrx* query; +@property(nonatomic, retain) DemoBookDescription* current; +@property(nonatomic, retain) id<DemoLibraryPrx> library; + +@end + +@implementation Parser + +@synthesize query; +@synthesize current; +@synthesize library; + +-(id)initWithLibrary:(id<DemoLibraryPrx>)lib +{ + if((self = [super init])) + { + self.library = lib; + } + return self; +} + ++(id)parserWithLibrary:(id<DemoLibraryPrx>)library +{ + return [[Parser alloc] initWithLibrary:library]; +} + +-(void)usage +{ + printf("help Print this message.\n" + "exit, quit Exit this program.\n" + "add isbn title authors Create new book.\n" + "isbn NUMBER Find all books that start with the given ISBN number.\n" + "authors NAME Find all books by the given authors.\n" + "title NAME Find all books which have the given title.\n" + "next Set the current book to the next one that was found.\n" + "current Display the current book.\n" + "rent NAME Rent the current book for customer NAME.\n" + "return Return the currently rented book.\n" + "remove Permanently remove the current book from the library.\n"); +} + +-(void)addBook:(NSArray*)args +{ + if(args.count != 3) + { + [self errorWithString:@"`add' requires exactly three arguments (type `help' for more info)"]; + return; + } + + @try + { + NSString* isbn = [args objectAtIndex:0]; + NSString* title = [args objectAtIndex:1]; + + NSArray* authors = [[args objectAtIndex:2] componentsSeparatedByString:@","]; + [library createBook:isbn title:title authors:authors]; + printf("added new book with isbn %s\n", [isbn UTF8String]); + } + @catch(DemoBookExistsException* ex) + { + [self errorWithString:@"the book already exists"]; + } + @catch(ICELocalException* ex) + { + [self errorWithString:[ex description]]; + } +} +-(void)findIsbn:(NSArray*)args +{ + if(args.count != 1) + { + [self errorWithString:@"`isbn' requires exactly one argument (type `help' for more info)"]; + return; + } + + @try + { + if(query != nil) + { + @try + { + [query destroy]; + } + @catch(ICEException* e) + { + // Ignore + } + + self.query = nil; + self.current = nil; + } + + id<DemoBookQueryResultPrx> q; + DemoMutableBookDescriptionSeq *results; + int nrows; + [library queryByIsbn:[args objectAtIndex:0] n:1 first:&results nrows:&nrows result:&q]; + + printf("%d results\n", nrows); + if(nrows == 0) + { + return; + } + + self.current = [results objectAtIndex:0]; + self.query = q; + + [self printCurrent]; + } + @catch(ICELocalException* ex) + { + [self errorWithString:[ex description]]; + } +} + +-(void)findAuthors:(NSArray*)args +{ + if(args.count != 1) + { + [self errorWithString:@"`authors' requires exactly one argument (type `help' for more info)"]; + return; + } + + @try + { + if(query != nil) + { + @try + { + [query destroy]; + } + @catch(ICEException* e) + { + // Ignore + } + self.query = nil; + self.current = nil; + } + + id<DemoBookQueryResultPrx> q; + DemoMutableBookDescriptionSeq *results; + int nrows; + [library queryByAuthor:[args objectAtIndex:0] n:1 first:&results nrows:&nrows result:&q]; + + printf("%d results\n", nrows); + if(nrows == 0) + { + return; + } + + self.current = [results objectAtIndex:0]; + self.query = q; + + [self printCurrent]; + } + @catch(ICELocalException* ex) + { + [self errorWithString:[ex description]]; + } +} + +-(void)findTitle:(NSArray*)args +{ + if(args.count != 1) + { + [self errorWithString:@"`title' requires exactly one argument (type `help' for more info)"]; + return; + } + + @try + { + if(query != nil) + { + @try + { + [query destroy]; + } + @catch(ICEException* e) + { + // Ignore + } + self.query = nil; + self.current = nil; + } + + id<DemoBookQueryResultPrx> q; + DemoMutableBookDescriptionSeq *results; + int nrows; + [library queryByTitle:[args objectAtIndex:0] n:1 first:&results nrows:&nrows result:&q]; + + printf("%d results\n", nrows); + if(nrows == 0) + { + return; + } + + self.current = [results objectAtIndex:0]; + self.query = q; + [self printCurrent]; + } + @catch(ICELocalException* ex) + { + [self errorWithString:[ex description]]; + } +} + +-(void)nextFoundBook +{ + if(query == nil) + { + printf("no next book\n"); + return; + } + + @try + { + BOOL destroyed; + NSArray* next = [query next:1 destroyed:&destroyed]; + if(next.count > 0) + { + self.current = [next objectAtIndex:0]; + } + else + { + NSAssert(destroyed, @""); + self.current = nil; + } + + if(destroyed) + { + self.query = nil; + } + + [self printCurrent]; + } + @catch(ICEObjectNotExistException* ex) + { + printf("the query object no longer exists\n"); + } + @catch(ICELocalException* ex) + { + [self errorWithString:[ex description]]; + } +} + +-(void)printCurrent +{ + if(current != nil) + { + printf("current book is:\n"); + printf("isbn: %s\n", [current.isbn UTF8String]); + printf("title: %s\n", [current.title UTF8String]); + NSMutableString* auth = [[NSMutableString alloc] init]; + for(NSString* s in current.authors) + { + if(s != [current.authors objectAtIndex:0]) + { + [auth appendString:@", "]; + } + [auth appendString:s]; + } + printf("authors: %s\n", [auth UTF8String]); + if([current.rentedBy length] > 0) + { + printf("rented: %s\n", [current.rentedBy UTF8String]); + } + } + else + { + printf("no current book\n"); + } +} + +-(void)rentCurrent:(NSArray*)args +{ + if(args.count != 1) + { + [self errorWithString:@"`rent' requires exactly one argument (type `help' for more info)"]; + return; + } + + @try + { + if(current != nil) + { + [current.proxy rentBook:[args objectAtIndex:0]]; + printf("the book is now rented by `%s'\n", [[args objectAtIndex:0] UTF8String]); + self.current = [current.proxy describe]; + } + else + { + printf("no current book\n"); + } + } + @catch(DemoBookRentedException* ex) + { + printf("the book has already been rented.\n"); + } + @catch(ICEObjectNotExistException* ex) + { + printf("current book no longer exists\n"); + } + @catch(ICELocalException* ex) + { + [self errorWithString:[ex description]]; + } +} + +-(void)returnCurrent +{ + @try + { + if(current != nil) + { + [current.proxy returnBook]; + printf( "the book has been returned.\n"); + self.current = [current.proxy describe]; + } + else + { + printf("no current book\n"); + } + } + @catch(DemoBookNotRentedException* ex) + { + printf("the book is not currently rented.\n"); + } + @catch(ICEObjectNotExistException* ex) + { + printf("current book no longer exists\n"); + } + @catch(ICELocalException* ex) + { + [self errorWithString:[ex description]]; + } +} + +-(void)removeCurrent +{ + @try + { + if(current != nil) + { + [current.proxy destroy]; + self.current = nil; + printf("removed current book\n"); + } + else + { + printf("no current book\n"); + } + } + @catch(ICEObjectNotExistException* ex) + { + printf("current book no longer exists\n"); + } + @catch(ICELocalException* ex) + { + [self errorWithString:[ex description]]; + } +} + +-(const char*)getPrompt +{ + if(cont) + { + cont = NO; + return "(cont) "; + } + else + { + return ">>> "; + } +} + +-(int)getInput:(char*)buf max:(int)max +{ + printf("%s", self.getPrompt); + fflush(stdout); + + NSMutableData* line = [[ NSMutableData alloc] init]; + while(true) + { + char c = (char)(getc(yyin)); + if(c == EOF) + { + if([line length]) + { + c = '\n'; + [line appendBytes:&c length:1]; + } + break; + } + + [line appendBytes:&c length:1]; + + if(c == '\n') + { + break; + } + } + NSString* ss = [[NSString alloc] initWithData:line encoding:NSUTF8StringEncoding]; + int len; + const char* utf8 = [ss UTF8String]; + + len = strlen(utf8); + if(len > max) + { + [self errorWithString:@"input line too long"]; + buf[0] = EOF; + return 1; + } + else + { + strcpy(buf, utf8); + } + + return len; +} + +-(void)continueLine +{ + cont = YES; +} + +-(void)error:(const char*)s +{ + fprintf(stderr, "error: %s\n", s); +} + +-(void)errorWithString:(NSString*)s +{ + fprintf(stderr, "error: %s\n", [s UTF8String]); +} + +-(void)warning:(const char*)s +{ + fprintf(stderr, "warning: %s\n", s); +} + +-(void)warningWithString:(NSString*)s +{ + fprintf(stderr, "warning: %s\n", [s UTF8String]); +} + +-(int)parse +{ + NSAssert(!parser, @""); + parser = self; + + errors = 0; + yyin = stdin; + NSAssert(yyin, @""); + + cont = false; + + self.query = nil; + self.current = nil; + + int status = yyparse(); + if(errors) + { + status = EXIT_FAILURE; + } + + parser = nil; + return status; +} +@end diff --git a/objc/demo/Database/library/README b/objc/demo/Database/library/README new file mode 100644 index 00000000000..67b558bb87d --- /dev/null +++ b/objc/demo/Database/library/README @@ -0,0 +1,14 @@ +This demo is an Ice Touch client for the Java library demo located +at demoj/Database/library in the Ice distribution. This application +provides a command line interface to the library server. It permits +you to: + + - Create and delete books + - Query for books by ISBN, author or title + - Rent and return books + +ZeroC hosts a server for this demo on demo2.zeroc.com, which is the +default host used by this client. The deployment on demo2.zeroc.com +accepts both secure and non-secure connections using Glacier2. Direct +connections to the library session manager are not permitted on +demo2.zeroc.com. diff --git a/objc/demo/Database/library/RunParser.m b/objc/demo/Database/library/RunParser.m new file mode 100644 index 00000000000..8e61c7ea02d --- /dev/null +++ b/objc/demo/Database/library/RunParser.m @@ -0,0 +1,215 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <objc/Glacier2.h> +#import <Library.h> +#import <Session.h> +#import <Glacier2Session.h> +#import <Parser.h> +#import <stdio.h> +#import <string.h> + +#import <Foundation/NSThread.h> +#import <Foundation/NSLock.h> + +@interface SessionRefreshThread : NSThread +{ +@private + id<ICELogger> logger; + id session; + NSCondition* cond; + + long timeout; +} + +-(id)initWithLogger:(id<ICELogger>) logger timeout:(long)timeout session:(id)session; ++(id)sessionRefreshThreadWithLogger:(id<ICELogger>)logger timeout:(long)timeout session:(id)session; +@end + +@interface SessionRefreshThread() +@property (nonatomic, retain) id<ICELogger> logger; +@property (nonatomic, retain) id session; +@property (nonatomic, retain) NSCondition* cond; +@end + +@implementation SessionRefreshThread + +@synthesize logger; +@synthesize session; +@synthesize cond; + +-(id)initWithLogger:(id<ICELogger>)l timeout:(long)t session:(id)s +{ + if((self = [super init])) + { + self.logger = l; + self.session = s; + self.cond = [[NSCondition alloc] init]; + timeout = t; + } + return self; +} + ++(id)sessionRefreshThreadWithLogger:(id<ICELogger>)logger timeout:(long)timeout session:(id)session +{ + return [[SessionRefreshThread alloc] initWithLogger:logger timeout:timeout session:session]; +} + +-(void)main +{ + [cond lock]; + @try + { + while(!self.isCancelled) + { + [cond waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:timeout]]; + if(!self.isCancelled) + { + @try + { + [session refresh]; + } + @catch(ICELocalException* ex) + { + NSString* warning = [NSString stringWithFormat:@"SessionRefreshThread: %@", [ex description]]; + [logger warning:warning]; + [super cancel]; + } + } + } + } + @finally + { + [cond unlock]; + } +} + +-(void)cancel +{ + [super cancel]; + [cond lock]; + @try + { + [cond signal]; + } + @finally + { + [cond unlock]; + } +} + +@end + +int +runParser(int argc, char* argv[], id<ICECommunicator> communicator) +{ + id<GLACIER2RouterPrx> router = [GLACIER2RouterPrx uncheckedCast:[communicator getDefaultRouter]]; + ICELong timeout; + id<DemoLibraryPrx> library; + id session; + if(router != nil) + { + printf("This demo accepts any user-id / password combination.\n"); + + while(true) + { + char id[1024]; + printf("user id: "); + fflush(stdout); + fgets(id, sizeof(id), stdin); + int len = strlen(id); + if(id[len-1] == '\n') + { + id[len-1] = '\0'; + } + printf("password: "); + fflush(stdout); + char pw[1024]; + fgets(pw, sizeof(pw), stdin); + len = strlen(pw); + if(pw[len-1] == '\n') + { + pw[len-1] = '\0'; + } + + @try + { + session = [DemoGlacier2SessionPrx uncheckedCast: + [router createSession:[NSString stringWithCString:id encoding:NSUTF8StringEncoding] + password:[NSString stringWithCString:pw encoding:NSUTF8StringEncoding]]]; + break; + } + @catch(GLACIER2PermissionDeniedException* ex) + { + printf("permission denied:\n%s\n", [ex.reason UTF8String]); + } + @catch(GLACIER2CannotCreateSessionException* ex) + { + printf("cannot create session:\n%s\n", [ex.reason UTF8String]); + } + } + timeout = [router getSessionTimeout]/2; + library = [session getLibrary]; + } + else + { + id<DemoSessionFactoryPrx> factory = [DemoSessionFactoryPrx checkedCast:[ + communicator propertyToProxy:@"SessionFactory.Proxy"] ]; + if(factory == nil) + { + fprintf(stderr, "%s: invalid object reference", argv[0]); + return 1; + } + + session = [factory create]; + timeout = [factory getSessionTimeout]/2; + library = [session getLibrary]; + } + + SessionRefreshThread* refresh = [SessionRefreshThread sessionRefreshThreadWithLogger:[communicator getLogger] + timeout:timeout/2 session:session]; + [refresh start]; + + Parser* parser = [Parser parserWithLibrary:library]; + + int rc = [parser parse]; + + [refresh cancel]; + + // No join. + while(!refresh.isFinished) + { + [NSThread sleepForTimeInterval:0.1]; + } + + if(router) + { + @try + { + [router destroySession]; + } + @catch(GLACIER2SessionNotExistException* ex) + { + NSLog(@"%@\n", [ex description]); + } + @catch(ICEConnectionLostException* ex) + { + // + // Expected: the router closed the connection. + // + } + } + else + { + [session destroy]; + } + + return rc; +} diff --git a/objc/demo/Database/library/Scanner.l b/objc/demo/Database/library/Scanner.l new file mode 100644 index 00000000000..5c87279c213 --- /dev/null +++ b/objc/demo/Database/library/Scanner.l @@ -0,0 +1,257 @@ +%{ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Parser.h> +#include <Grammar.h> +#include <ctype.h> + +#import <Foundation/NSString.h> +#import <Foundation/NSData.h> + +#define YY_INPUT(buf, result, maxSize) \ + { \ + result = [parser getInput: buf max: maxSize ]; \ + } + +%} + +WS [ \t\v\f\r] +NL [\n] + +%option noyywrap +%option always-interactive + +%% + +"//" { + // C++-style comment + int c; + do + { + c = input(); + } + while(c != '\n' && c != EOF); +} + +"/*" { + // C-style comment + while(true) + { + int c = input(); + if(c == '*') + { + int next = input(); + if(next == '/') + { + break; + } + else + { + unput(next); + } + } + else if(c == EOF) + { + [parser warning: "EOF in comment"]; + break; + } + } +} + +"help" { + return TOK_HELP; +} + +"quit"|"exit" { + return TOK_EXIT; +} + +"add" { + return TOK_ADD_BOOK; +} + +"isbn" { + return TOK_FIND_ISBN; +} + +"authors" { + return TOK_FIND_AUTHORS; +} + +"title" { + return TOK_FIND_TITLE; +} + +"next" { + return TOK_NEXT_FOUND_BOOK; +} + +"current" { + return TOK_PRINT_CURRENT; +} + +"rent" { + return TOK_RENT_BOOK; +} + +"return" { + return TOK_RETURN_BOOK; +} + +"remove" { + return TOK_REMOVE_CURRENT; +} + +{WS}*(\\{WS}*{NL})? { + size_t len = strlen(yytext); + size_t i; + for(i = 0; i < len; ++i) + { + if(yytext[i] == '\\') + { + [parser continueLine]; + } + } +} + +{NL}|; { + return ';'; +} + +\" { + // "..."-type strings + NSMutableData* s = [ [ NSMutableData alloc] init]; + while(true) + { + char c = (char)(input()); + if(c == '"') + { + break; + } + else if(c == EOF) + { + [parser warning: "EOF in string"]; + break; + } + else if(c == '\\') + { + char next = (char)(input()); + switch(next) + { + case '\\': + case '"': + { + c = next; + break; + } + + case 'n': + { + c = '\n'; + break; + } + + case 'r': + { + c = '\r'; + break; + } + + case 't': + { + c = '\t'; + break; + } + + case 'v': + { + c = '\v'; + break; + } + + case 'f': + { + c = '\f'; + break; + } + + default: + { + unput(next); + } + } + } + [s appendBytes: &c length: 1]; + } + + *yylvalp = [NSMutableArray array]; + NSString* ss = [ [NSString alloc] initWithData: s encoding: NSUTF8StringEncoding ]; + [s release]; + [*yylvalp addObject: ss]; + [ss release]; + return TOK_STRING; +} + +\' { + // '...'-type strings + NSMutableData* s = [ [ NSMutableData alloc] init]; + while(true) + { + char c = (char)(input()); + if(c == '\'') + { + break; + } + else if(c == EOF) + { + [parser warning: "EOF in string"]; + break; + } + else + { + [s appendBytes: &c length: 1]; + } + } + *yylvalp = [NSMutableArray array]; + NSString* ss = [ [NSString alloc] initWithData: s encoding: NSUTF8StringEncoding ]; + [s release]; + [*yylvalp addObject: ss]; + [ss release]; + return TOK_STRING; +} + +. { + // Simple strings + NSMutableData* s = [ [ NSMutableData alloc] init]; + [s appendBytes: yytext length: 1]; + while(true) + { + char c = (char)(input()); + if(c == EOF) + { + break; + } + else if(isspace(c) || c == ';') + { + unput(c); + break; + } + + [s appendBytes: &c length: 1]; + } + *yylvalp = [NSMutableArray array]; + NSString* ss = [ [NSString alloc] initWithData: s encoding: NSUTF8StringEncoding ]; + [s release]; + [*yylvalp addObject: ss]; + [ss release]; + return TOK_STRING; +} + +%% diff --git a/objc/demo/Database/library/Session.ice b/objc/demo/Database/library/Session.ice new file mode 100644 index 00000000000..3592981f45b --- /dev/null +++ b/objc/demo/Database/library/Session.ice @@ -0,0 +1,79 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Demo +{ + +/* Forward declaration. */ +interface Library; + +/** + * + * The session object. This is used to retrieve a per-session library + * on behalf of the client. If the session is not refreshed on a + * periodic basis, it will be automatically destroyed. + * + */ +interface Session +{ + /** + * + * Get the library object. + * + * @return A proxy for the new library. + * + **/ + Library* getLibrary(); + + /** + * + * Refresh a session. If a session is not refreshed on a regular + * basis by the client, it will be automatically destroyed. + * + **/ + idempotent void refresh(); + + /** + * + * Destroy the session. + * + **/ + void destroy(); +}; + +/** + * + * Interface to create new sessions. + * + **/ +interface SessionFactory +{ + /** + * + * Create a session. + * + * @return A proxy to the session. + * + **/ + Session* create(); + + /** + * + * Get the value of the session timeout. Sessions are destroyed + * if they see no activity for this period of time. + * + * @return The timeout (in seconds). + * + **/ + ["nonmutating", "cpp:const"] idempotent long getSessionTimeout(); +}; + +}; diff --git a/objc/demo/Database/library/config.client b/objc/demo/Database/library/config.client new file mode 100644 index 00000000000..a43a5cd0ef2 --- /dev/null +++ b/objc/demo/Database/library/config.client @@ -0,0 +1,68 @@ +# +# The client reads this property to create the reference to the +# "SessionFactory" object in the server. +# +#SessionFactory.Proxy=SessionFactory:default -p 10000 + +# +# The proxy to the Glacier2 router for all outgoing connections. This +# must match the value of Glacier2.Client.Endpoints in config.glacier2. +# +Ice.Default.Router=DemoGlacier2/router:ssl -p 4064 -h demo2.zeroc.com -t 10000 + +# +# If you want to use a local demo server, uncomment this line and change +# the SSL setup below. +# +#Ice.Default.Router=DemoGlacier2/router:ssl -p 4064 -h 127.0.0.1 -t 10000 + +# +# No active connection management is permitted because of the session +# interfaces. Connections must remain established. +# +Ice.ACM.Client=0 + +# +# Connection retry is not possible because of the session +# interfaces. Connections must remain established. +# +Ice.RetryIntervals=-1 + +# +# Warn about connection exceptions +# +#Ice.Warn.Connections=1 + +# +# Network Tracing +# +# 0 = no network tracing +# 1 = trace connection establishment and closure +# 2 = like 1, but more detailed +# 3 = like 2, but also trace data transfer +# +#Ice.Trace.Network=1 + +# +# Protocol Tracing +# +# 0 = no protocol tracing +# 1 = trace protocol messages +# +#Ice.Trace.Protocol=1 + +# +# Security Tracing +# +# 0 = no security tracing +# 1 = trace messages +# +#IceSSL.Trace.Security=1 + +# +# SSL Configuration +# +IceSSL.CertAuthFile=cacert.pem +IceSSL.DefaultDir=../../../../certs +IceSSL.TrustOnly.Client=CN="127.0.0.1" +IceSSL.CheckCertName=0 diff --git a/objc/demo/Ice/Makefile b/objc/demo/Ice/Makefile new file mode 100644 index 00000000000..ebe1e47f7e4 --- /dev/null +++ b/objc/demo/Ice/Makefile @@ -0,0 +1,21 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = minimal hello helloRouter optional + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done diff --git a/objc/demo/Ice/README b/objc/demo/Ice/README new file mode 100644 index 00000000000..77bae89714f --- /dev/null +++ b/objc/demo/Ice/README @@ -0,0 +1,20 @@ +Demos in this directory: + +- hello + + This demo illustrates how to invoke ordinary (twoway) operations, as + well as how to invoke oneway operations, use datagrams, secure + invocations, and how to use batched invocations. + +- helloRouter + + This demo illustrates how to use the hello demo server from your + Mac with the iPhone router demo (demo/iPhone/router). + +- minimal + + This demo illustrates a minimal Ice application. + +- optional + + This demo shows the use of the optional keyword. diff --git a/objc/demo/Ice/hello/.gitignore b/objc/demo/Ice/hello/.gitignore new file mode 100644 index 00000000000..652acdba5de --- /dev/null +++ b/objc/demo/Ice/hello/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +Hello.m +Hello.h diff --git a/objc/demo/Ice/hello/Client.m b/objc/demo/Ice/hello/Client.m new file mode 100644 index 00000000000..7897f0f6e1a --- /dev/null +++ b/objc/demo/Ice/hello/Client.m @@ -0,0 +1,246 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <Hello.h> + +#import <stdio.h> + +void +menu() +{ + printf("usage:\n" + "t: send greeting as twoway\n" + "o: send greeting as oneway\n" + "O: send greeting as batch oneway\n" + "d: send greeting as datagram\n" + "D: send greeting as batch datagram\n" + "f: flush all batch requests\n" + "T: set a timeout\n" + "P: set server delay\n" + "S: switch secure mode on/off\n" + "s: shutdown server\n" + "x: exit\n" + "?: help\n"); +} + +int +run(int argc, char* argv[], id<ICECommunicator> communicator) +{ + if(argc > 1) + { + fprintf(stderr, "%s: too many arguments\n", argv[0]); + return EXIT_FAILURE; + } + + id<DemoHelloPrx> twoway = [DemoHelloPrx checkedCast: + [[[[communicator propertyToProxy:@"Hello.Proxy"] ice_twoway] ice_timeout:-1] ice_secure:NO]]; + if(!twoway) + { + fprintf(stderr, "%s: invalid proxy\n", argv[0]); + return EXIT_FAILURE; + } + id<DemoHelloPrx> oneway = [twoway ice_oneway]; + id<DemoHelloPrx> batchOneway = [twoway ice_batchOneway]; + id<DemoHelloPrx> datagram = [twoway ice_datagram]; + id<DemoHelloPrx> batchDatagram = [twoway ice_batchDatagram]; + + BOOL secure = NO; + int timeout = -1; + int delay = 0; + + menu(); + + char c = 0; + do + { + @try + { + printf("==> "); + fflush(stdout); + + do + { + c = getchar(); + } + while(c != EOF && c == '\n'); + if(c == 't') + { + [twoway sayHello:delay]; + } + else if(c == 'o') + { + [oneway sayHello:delay]; + } + else if(c == 'O') + { + [batchOneway sayHello:delay]; + } + else if(c == 'd') + { + if(secure) + { + printf("secure datagrams are not supported\n"); + fflush(stdout); + } + else + { + [datagram sayHello:delay]; + } + } + else if(c == 'D') + { + if(secure) + { + printf("secure datagrams are not supported\n"); + fflush(stdout); + } + else + { + [batchDatagram sayHello:delay]; + } + } + else if(c == 'f') + { + [communicator flushBatchRequests]; + } + else if(c == 'T') + { + if(timeout == -1) + { + timeout = 2000; + } + else + { + timeout = -1; + } + + twoway = [twoway ice_timeout:timeout]; + oneway = [oneway ice_timeout:timeout]; + batchOneway = [batchOneway ice_timeout:timeout]; + + if(timeout == -1) + { + printf("timeout is now switched off\n"); + fflush(stdout); + } + else + { + printf("timeout is now set to 2000ms\n"); + fflush(stdout); + } + } + else if(c == 'P') + { + if(delay == 0) + { + delay = 2500; + } + else + { + delay = 0; + } + + if(delay == 0) + { + printf("server delay is now deactivated\n"); + fflush(stdout); + } + else + { + printf("server delay is now set to 2500ms\n"); + fflush(stdout); + } + } + else if(c == 'S') + { + secure = !secure; + + twoway = [twoway ice_secure:secure]; + oneway = [oneway ice_secure:secure]; + batchOneway = [batchOneway ice_secure:secure]; + datagram = [datagram ice_secure:secure]; + batchDatagram = [batchDatagram ice_secure:secure]; + + if(secure) + { + printf("secure mode is now on\n"); + fflush(stdout); + } + else + { + printf("secure mode is now off\n"); + fflush(stdout); + } + } + else if(c == 's') + { + [twoway shutdown]; + } + else if(c == 'x') + { + // Nothing to do + } + else if(c == '?') + { + menu(); + } + else + { + printf("unknown command `%c'\n", c); + menu(); + } + } + @catch(ICEException* ex) + { + NSLog(@"%@", ex); + } + } + while(c != EOF && c != 'x'); + + return EXIT_SUCCESS; +} + +int +main(int argc, char* argv[]) +{ + int status = EXIT_SUCCESS; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = [ICEUtil createProperties]; + [initData.properties load:@"config.client"]; + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(argc, argv, communicator); + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + + if(communicator != nil) + { + @try + { + [communicator destroy]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + } + } + return status; +} diff --git a/objc/demo/Ice/hello/Hello.ice b/objc/demo/Ice/hello/Hello.ice new file mode 100644 index 00000000000..f75c9795b97 --- /dev/null +++ b/objc/demo/Ice/hello/Hello.ice @@ -0,0 +1,21 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Demo +{ + +interface Hello +{ + idempotent void sayHello(int delay); + void shutdown(); +}; + +}; diff --git a/objc/demo/Ice/hello/HelloI.h b/objc/demo/Ice/hello/HelloI.h new file mode 100644 index 00000000000..667f2cc2ca4 --- /dev/null +++ b/objc/demo/Ice/hello/HelloI.h @@ -0,0 +1,14 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <Hello.h> + +@interface HelloI : DemoHello<DemoHello> ++(id) helloI; +@end diff --git a/objc/demo/Ice/hello/HelloI.m b/objc/demo/Ice/hello/HelloI.m new file mode 100644 index 00000000000..b0d53885710 --- /dev/null +++ b/objc/demo/Ice/hello/HelloI.m @@ -0,0 +1,44 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <HelloI.h> + +#import <Foundation/NSThread.h> + +#import <stdio.h> + +@implementation HelloI ++(id) helloI +{ + id instance = [[HelloI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [instance autorelease]; +#endif + return instance; +} + +-(void) sayHello:(int)delay current:(ICECurrent*)c +{ + if(delay != 0) + { + [NSThread sleepForTimeInterval:delay / 1000.f]; + } + printf("Hello World!\n"); + fflush(stdout); +} + +-(void) shutdown:(ICECurrent*)c +{ + printf("Shutting down...\n"); + fflush(stdout); + [[c.adapter getCommunicator] shutdown]; +} + +@end diff --git a/objc/demo/Ice/hello/Makefile b/objc/demo/Ice/hello/Makefile new file mode 100644 index 00000000000..3678dc05eaf --- /dev/null +++ b/objc/demo/Ice/hello/Makefile @@ -0,0 +1,36 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = Hello.o + +COBJS = Client.o \ + +SOBJS = HelloI.o \ + Server.o + +OBJS = $(SLICE_OBJS) $(COBJS) $(SOBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. $(CPPFLAGS) + +$(CLIENT): $(SLICE_OBJS) $(COBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SLICE_OBJS) $(COBJS) $(LIBS) + +$(SERVER): $(SLICE_OBJS) $(SOBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SLICE_OBJS) $(SOBJS) $(LIBS) diff --git a/objc/demo/Ice/hello/README b/objc/demo/Ice/hello/README new file mode 100644 index 00000000000..2d4632f3228 --- /dev/null +++ b/objc/demo/Ice/hello/README @@ -0,0 +1,43 @@ +The demo shows how to make: + + - Twoway invocations. This is the default mode for any remote + invocation. A twoway invocation is not complete until a reply has + been received from the server. + + - Oneway invocations. A oneway invocation is complete as soon as the + client has successfully sent the invocation. Oneway invocations + may not return values or throw user exceptions. + + - Oneway batched invocations. See below for details on batching. + + - Datagram invocations. Datagram invocations use the udp transport, + and as such have very minimal quality of service guarantees. + Datagram invocations are always oneway. + + - Datagram batched invocations. See below for details on batching. + +Batching, which is only possible when using oneway or datagram +invocations, combines several Ice messages into a single physical +protocol message. Batching can result in higher throughput and smaller +physical messages due to less protocol overhead. Ice does not actually +send a batched message until it is flushed. + +If you enable secure invocations, oneway and twoway operations are +sent using the SSL transport. It is not possible to secure datagram +invocations. + +To run the demo, first start the server: + +$ server + +In a separate window, start the client: + +$ client + +To test timeouts you can use 'T' to set a timeout on the client proxy +and 'P' to set a delayed response in the server to cause a timeout. +You will notice that two "Hello World!" messages will be printed by +the server in this case. This happens because the Slice operation +sayHello is marked as idempotent, meaning that Ice does not need to +preserve the at-most-once retry semantics. See the manual for +more information about retry behavior. diff --git a/objc/demo/Ice/hello/Server.m b/objc/demo/Ice/hello/Server.m new file mode 100644 index 00000000000..50e3c4ab51b --- /dev/null +++ b/objc/demo/Ice/hello/Server.m @@ -0,0 +1,65 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <HelloI.h> + + +int +run(int argc, char* argv[], id<ICECommunicator> communicator) +{ + if(argc > 1) + { + NSLog(@"%s: too many arguments", argv[0]); + return EXIT_FAILURE; + } + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"Hello"]; + [adapter add:[HelloI helloI] identity:[communicator stringToIdentity:@"hello"]]; + [adapter activate]; + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +int +main(int argc, char* argv[]) +{ + int status = EXIT_SUCCESS; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = [ICEUtil createProperties]; + [initData.properties load:@"config.server"]; + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(argc, argv, communicator); + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + + if(communicator != nil) + { + @try + { + [communicator destroy]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + } + } + return status; +} diff --git a/objc/demo/Ice/hello/config.client b/objc/demo/Ice/hello/config.client new file mode 100644 index 00000000000..d43ea2b6723 --- /dev/null +++ b/objc/demo/Ice/hello/config.client @@ -0,0 +1,65 @@ +# +# The client reads this property to create the reference to the +# "hello" object in the server. +# +Hello.Proxy=hello:tcp -p 10000:udp -p 10000:ssl -p 10001 + +# +# Uncomment to use the WebSocket transports instead. +# +#Hello.Proxy=hello:ws -p 10002:udp -p 10000:wss -p 10003 + +# +# Only connect to the localhost interface by default. +# +Ice.Default.Host=localhost + +# +# Warn about connection exceptions +# +Ice.Warn.Connections=1 + +# +# Network Tracing +# +# 0 = no network tracing +# 1 = trace connection establishment and closure +# 2 = like 1, but more detailed +# 3 = like 2, but also trace data transfer +# +#Ice.Trace.Network=1 + +# +# Protocol Tracing +# +# 0 = no protocol tracing +# 1 = trace protocol messages +# +#Ice.Trace.Protocol=1 + +# +# Security Tracing +# +# 0 = no security tracing +# 1 = trace messages +# +#IceSSL.Trace.Security=1 + +# +# SSL Configuration +# +Ice.Plugin.IceSSL=IceSSL:createIceSSL +IceSSL.DefaultDir=../../../../certs +IceSSL.CertAuthFile=cacert.pem +IceSSL.CertFile=c_rsa1024.pfx +IceSSL.Password=password +IceSSL.Keychain=client.keychain +IceSSL.KeychainPassword=password + +# +# IceMX configuration. +# +#Ice.Admin.Endpoints=tcp -p 10004 +Ice.Admin.InstanceName=client +IceMX.Metrics.Debug.GroupBy=id +IceMX.Metrics.ByParent.GroupBy=parent diff --git a/objc/demo/Ice/hello/config.server b/objc/demo/Ice/hello/config.server new file mode 100644 index 00000000000..bb96a7a798b --- /dev/null +++ b/objc/demo/Ice/hello/config.server @@ -0,0 +1,74 @@ +# +# The server creates one single object adapter with the name +# "Hello". The following line sets the endpoints for this +# adapter. +# +# When no -h <host> option is specified in the endpoints, the default +# value from the Ice.Default.Host property is used. If this property +# isn't set, the endpoints will listen on all available network +# interfaces. +# +Hello.Endpoints=tcp -p 10000:udp -p 10000:ssl -p 10001:ws -p 10002:wss -p 10003 + +# +# Only listen on the localhost interface by default. You can comment +# out this property to allow listening on all available interfaces. +# +Ice.Default.Host=localhost + +# +# For secure WebSocket (WSS) clients and Windows Store App clients, +# you should disable this property. JavaScript browser clients and +# Windows Store App clients don't use client-side authentication. +# +#IceSSL.VerifyPeer=0 + +# +# Warn about connection exceptions +# +Ice.Warn.Connections=1 + +# +# Network Tracing +# +# 0 = no network tracing +# 1 = trace connection establishment and closure +# 2 = like 1, but more detailed +# 3 = like 2, but also trace data transfer +# +#Ice.Trace.Network=1 + +# +# Protocol Tracing +# +# 0 = no protocol tracing +# 1 = trace protocol messages +# +#Ice.Trace.Protocol=1 + +# +# Security Tracing +# +# 0 = no security tracing +# 1 = trace messages +# +#IceSSL.Trace.Security=1 + +# +# SSL Configuration +# +Ice.Plugin.IceSSL=IceSSL:createIceSSL +IceSSL.DefaultDir=../../../../certs +IceSSL.CertAuthFile=cacert.pem +IceSSL.CertFile=s_rsa1024.pfx +IceSSL.Password=password +IceSSL.Keychain=server.keychain +IceSSL.KeychainPassword=password + +# +# IceMX configuration +# +#Ice.Admin.Endpoints=tcp -p 10004 +Ice.Admin.InstanceName=server +IceMX.Metrics.Debug.GroupBy=id +IceMX.Metrics.ByParent.GroupBy=parent diff --git a/objc/demo/Ice/hello/expect.py b/objc/demo/Ice/hello/expect.py new file mode 100755 index 00000000000..1a4bbf96ccb --- /dev/null +++ b/objc/demo/Ice/hello/expect.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import sys, os + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(path[0]) + +from demoscript import Util +from demoscript.Ice import hello + +server = Util.spawn('./server --Ice.PrintAdapterReady --Ice.Warn.Connections=0') +server.expect('.* ready') +client = Util.spawn('./client --Ice.Warn.Connections=0') +client.expect('.*==>') + +hello.run(client, server) diff --git a/objc/demo/Ice/helloRouter/.gitignore b/objc/demo/Ice/helloRouter/.gitignore new file mode 100644 index 00000000000..8660bff4f6c --- /dev/null +++ b/objc/demo/Ice/helloRouter/.gitignore @@ -0,0 +1,9 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +.depend +Hello.m +Router.m +Hello.h +Router.h diff --git a/objc/demo/Ice/helloRouter/Client.m b/objc/demo/Ice/helloRouter/Client.m new file mode 100644 index 00000000000..a67b120f7c0 --- /dev/null +++ b/objc/demo/Ice/helloRouter/Client.m @@ -0,0 +1,133 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <Hello.h> +#import <Router.h> + +#import <stdio.h> + + +void +menu() +{ + printf("usage:\n" + "t: send greeting as twoway\n" + "o: send greeting as oneway\n" + "s: shutdown server\n" + "x: exit\n" + "?: help\n"); +} + +int +run(int argc, char* argv[], id<ICECommunicator> communicator) +{ + if(argc > 1) + { + fprintf(stderr, "%s: too many arguments\n", argv[0]); + return EXIT_FAILURE; + } + + id<DemoRouterPrx> router = [DemoRouterPrx checkedCast:[communicator getDefaultRouter]]; + [router createSession]; + + id<DemoHelloPrx> twoway = [DemoHelloPrx checkedCast:[communicator propertyToProxy:@"Hello.Proxy"]]; + if(!twoway) + { + fprintf(stderr, "%s: invalid proxy\n", argv[0]); + return EXIT_FAILURE; + } + id<DemoHelloPrx> oneway = [twoway ice_oneway]; + + menu(); + + char c = 0; + do + { + @try + { + printf("==> "); + do + { + c = getchar(); + } + while(c != EOF && c == '\n'); + if(c == 't') + { + [twoway sayHello:0]; + } + else if(c == 'o') + { + [oneway sayHello:0]; + } + else if(c == 's') + { + [twoway shutdown]; + } + else if(c == 'x') + { + // Nothing to do + } + else if(c == '?') + { + menu(); + } + else + { + printf("unknown command `%c'\n", c); + menu(); + } + } + @catch(ICEException* ex) + { + NSLog(@"%@", ex); + } + } + while(c != EOF && c != 'x'); + + return EXIT_SUCCESS; +} + +int +main(int argc, char* argv[]) +{ + int status = EXIT_SUCCESS; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = [ICEUtil createProperties]; + [initData.properties load:@"config.client"]; + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(argc, argv, communicator); + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + + if(communicator != nil) + { + @try + { + [communicator destroy]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + } + } + return status; +} diff --git a/objc/demo/Ice/helloRouter/Hello.ice b/objc/demo/Ice/helloRouter/Hello.ice new file mode 100644 index 00000000000..f75c9795b97 --- /dev/null +++ b/objc/demo/Ice/helloRouter/Hello.ice @@ -0,0 +1,21 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Demo +{ + +interface Hello +{ + idempotent void sayHello(int delay); + void shutdown(); +}; + +}; diff --git a/objc/demo/Ice/helloRouter/Makefile b/objc/demo/Ice/helloRouter/Makefile new file mode 100644 index 00000000000..fe4ef49348f --- /dev/null +++ b/objc/demo/Ice/helloRouter/Makefile @@ -0,0 +1,29 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client + +TARGETS = $(CLIENT) + +SLICE_OBJS = Hello.o \ + Router.o + +COBJS = Client.o + +OBJS = $(SLICE_OBJS) $(COBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. $(CPPFLAGS) + +$(CLIENT): $(SLICE_OBJS) $(COBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SLICE_OBJS) $(COBJS) -lGlacier2Objc $(LIBS) diff --git a/objc/demo/Ice/helloRouter/README b/objc/demo/Ice/helloRouter/README new file mode 100644 index 00000000000..f6a4f3a9560 --- /dev/null +++ b/objc/demo/Ice/helloRouter/README @@ -0,0 +1,12 @@ +This is a version of the hello demo for use with the iPhone router +demo in demo/iPhone/router. + +To run the demo, first start the hello server in demo/Ice/hello: + +$ server + +Next start the router demo in demo/iPhone/router on the iPhone. + +Finally, in a separate window, start the client: + +$ client diff --git a/objc/demo/Ice/helloRouter/Router.ice b/objc/demo/Ice/helloRouter/Router.ice new file mode 100644 index 00000000000..8161446f594 --- /dev/null +++ b/objc/demo/Ice/helloRouter/Router.ice @@ -0,0 +1,70 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Glacier2/Router.ice> + +module Demo +{ + +/** + * + * The Demo router interface. This router is used to route requests directly + * to an Ice server. + * + **/ +interface Router extends Ice::Router +{ + /** + * + * Create a new session. The returned category must be used in the + * identities of all of the client's callback objects. This is necessary + * in order for the router to forward callback requests to the intended + * client. + * + * @return A category. + * + */ + string createSession(); + + /** + * + * Create a new glacier2 session. + * + * @param router A proxy to the Glacier2 router. + * + * @param username The user id for which to check the password. + * + * @param password The password for the given user id. + * + * @param category The returned category that must be used in the + * identities of all of the client's callback objects. + * + * @param sessionTimeout The session timeout. + * + * @param sess The A proxy for the newly created session, or null + * if no [Glacier2::SessionManager] was defined. + * + * @throws Glacier2::PermissionDeniedException Raised if the password for + * the given user id is not correct, or if the user is not allowed + * access. + * + * @throws Glacier2::CannotCreateSessionException Raised if the session + * cannot be created. + * + */ + + void createGlacier2Session(Ice::Router* router, string userId, string password, + out string category, out int sessionTimeout, + out Glacier2::Session* sess) + throws Glacier2::PermissionDeniedException, Glacier2::CannotCreateSessionException; +}; + +}; diff --git a/objc/demo/Ice/helloRouter/config.client b/objc/demo/Ice/helloRouter/config.client new file mode 100644 index 00000000000..134bdea5ab1 --- /dev/null +++ b/objc/demo/Ice/helloRouter/config.client @@ -0,0 +1,57 @@ +# +# Proxy to the iPhone router. +# +Ice.Default.Router=iPhoneRouter/Router:tcp -h 169.254.37.90 -p 12000 + +# +# The client reads this property to create the reference to the +# "hello" object in the server. +# +Hello.Proxy=hello:tcp -p 10000 + +# +# Warn about connection exceptions +# +Ice.Warn.Connections=1 + +# +# Client-side ACM is enabled by default, with an interval of 60 +# seconds. For this demo, we want to use a short timeout of 10 +# seconds. By enabling network tracing below, you can see ACM +# automatically close idle connections. +# +Ice.ACM.Client=10 + +# +# Network Tracing +# +# 0 = no network tracing +# 1 = trace connection establishment and closure +# 2 = like 1, but more detailed +# 3 = like 2, but also trace data transfer +# +#Ice.Trace.Network=1 + +# +# Protocol Tracing +# +# 0 = no protocol tracing +# 1 = trace protocol messages +# +#Ice.Trace.Protocol=1 + +# +# Security Tracing +# +# 0 = no security tracing +# 1 = trace messages +# +#IceSSL.Trace.Security=1 + +# +# SSL Configuration +# +IceSSL.DefaultDir=../../../../certs +IceSSL.CertAuthFile=cacert.pem +IceSSL.CertFile=c_rsa1024_pub.pem +IceSSL.KeyFile=c_rsa1024_priv.pem diff --git a/objc/demo/Ice/minimal/.gitignore b/objc/demo/Ice/minimal/.gitignore new file mode 100644 index 00000000000..652acdba5de --- /dev/null +++ b/objc/demo/Ice/minimal/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +Hello.m +Hello.h diff --git a/objc/demo/Ice/minimal/Client.m b/objc/demo/Ice/minimal/Client.m new file mode 100644 index 00000000000..b467d83af7a --- /dev/null +++ b/objc/demo/Ice/minimal/Client.m @@ -0,0 +1,59 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <Hello.h> + +int +main(int argc, char* argv[]) +{ + int status = EXIT_SUCCESS; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + communicator = [ICEUtil createCommunicator:&argc argv:argv]; + if(argc > 1) + { + NSLog(@"%s: too many arguments", argv[0]); + return EXIT_FAILURE; + } + id<DemoHelloPrx> hello = [DemoHelloPrx checkedCast:[communicator stringToProxy:@"hello:default -p 10000"]]; + if(hello == nil) + { + NSLog(@"%s: invalid proxy", argv[0]); + status = EXIT_FAILURE; + } + else + { + [hello sayHello]; + } + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + + if(communicator != nil) + { + @try + { + [communicator destroy]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + } + } + return status; +} diff --git a/objc/demo/Ice/minimal/Hello.ice b/objc/demo/Ice/minimal/Hello.ice new file mode 100644 index 00000000000..33d311622fa --- /dev/null +++ b/objc/demo/Ice/minimal/Hello.ice @@ -0,0 +1,20 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Demo +{ + +interface Hello +{ + idempotent void sayHello(); +}; + +}; diff --git a/objc/demo/Ice/minimal/HelloI.h b/objc/demo/Ice/minimal/HelloI.h new file mode 100644 index 00000000000..667f2cc2ca4 --- /dev/null +++ b/objc/demo/Ice/minimal/HelloI.h @@ -0,0 +1,14 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <Hello.h> + +@interface HelloI : DemoHello<DemoHello> ++(id) helloI; +@end diff --git a/objc/demo/Ice/minimal/HelloI.m b/objc/demo/Ice/minimal/HelloI.m new file mode 100644 index 00000000000..e9e75b9a362 --- /dev/null +++ b/objc/demo/Ice/minimal/HelloI.m @@ -0,0 +1,29 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <HelloI.h> + +#include <stdio.h> + +@implementation HelloI ++(id) helloI +{ + id instance = [[HelloI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [instance autorelease]; +#endif + return instance; +} + +-(void) sayHello:(ICECurrent*)current +{ + printf("Hello World!\n"); + fflush(stdout); +} +@end diff --git a/objc/demo/Ice/minimal/Makefile b/objc/demo/Ice/minimal/Makefile new file mode 100644 index 00000000000..3678dc05eaf --- /dev/null +++ b/objc/demo/Ice/minimal/Makefile @@ -0,0 +1,36 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = Hello.o + +COBJS = Client.o \ + +SOBJS = HelloI.o \ + Server.o + +OBJS = $(SLICE_OBJS) $(COBJS) $(SOBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. $(CPPFLAGS) + +$(CLIENT): $(SLICE_OBJS) $(COBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SLICE_OBJS) $(COBJS) $(LIBS) + +$(SERVER): $(SLICE_OBJS) $(SOBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SLICE_OBJS) $(SOBJS) $(LIBS) diff --git a/objc/demo/Ice/minimal/README b/objc/demo/Ice/minimal/README new file mode 100644 index 00000000000..6052065fb3a --- /dev/null +++ b/objc/demo/Ice/minimal/README @@ -0,0 +1,14 @@ +This demo is a minimal Ice "hello world" application. Each time the +client is run, a "sayHello" invocation is sent to the server. + +To run the demo, first start the server: + +$ server + +In a separate window, start the client: + +$ client + +Note that this demo hardwires port 10000. If port 10000 is not +available on your machine, you need to edit both client and server +to use a free port. diff --git a/objc/demo/Ice/minimal/Server.m b/objc/demo/Ice/minimal/Server.m new file mode 100644 index 00000000000..b77cc035819 --- /dev/null +++ b/objc/demo/Ice/minimal/Server.m @@ -0,0 +1,55 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <HelloI.h> + +int +main(int argc, char* argv[]) +{ + int status = 0; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + communicator = [ICEUtil createCommunicator:&argc argv:argv]; + if(argc > 1) + { + NSLog(@"%s: too many arguments", argv[0]); + return 1; + } + + id<ICEObjectAdapter> adapter = [communicator createObjectAdapterWithEndpoints:@"Hello" + endpoints:@"default -p 10000"]; + [adapter add:[HelloI helloI] identity:[communicator stringToIdentity:@"hello"]]; + [adapter activate]; + [communicator waitForShutdown]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = 1; + } + + if(communicator != nil) + { + @try + { + [communicator destroy]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = 1; + } + } + } + return status; +} diff --git a/objc/demo/Ice/minimal/expect.py b/objc/demo/Ice/minimal/expect.py new file mode 100755 index 00000000000..64a271f1549 --- /dev/null +++ b/objc/demo/Ice/minimal/expect.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import sys, os, signal + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(path[0]) + +from demoscript import Util + +server = Util.spawn('./server --Ice.PrintAdapterReady') +server.expect('.* ready') + +sys.stdout.write("testing... ") +sys.stdout.flush() +client = Util.spawn('./client') +client.waitTestSuccess() +server.expect('Hello World!') +print("ok") + +server.kill(signal.SIGINT) +server.waitTestFail() diff --git a/objc/demo/Ice/optional/.gitignore b/objc/demo/Ice/optional/.gitignore new file mode 100644 index 00000000000..4d4a8840fe8 --- /dev/null +++ b/objc/demo/Ice/optional/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +Contact.m +Contact.h diff --git a/objc/demo/Ice/optional/Client.m b/objc/demo/Ice/optional/Client.m new file mode 100644 index 00000000000..7aeed28e5b8 --- /dev/null +++ b/objc/demo/Ice/optional/Client.m @@ -0,0 +1,246 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <Contact.h> + +#import <stdio.h> + +int +run(int argc, char* argv[], id<ICECommunicator> communicator) +{ + if(argc > 1) + { + fprintf(stderr, "%s: too many arguments\n", argv[0]); + return EXIT_FAILURE; + } + + id<DemoContactDBPrx> contactdb = [DemoContactDBPrx checkedCast:[communicator propertyToProxy:@"ContactDB.Proxy"]]; + if(contactdb == nil) + { + fprintf(stderr, "%s: invalid proxy\n", argv[0]); + return EXIT_FAILURE; + } + + // + // Add a contact for "john". All parameters are provided. + // + NSString* johnNumber = @"123-456-7890"; + [contactdb addContact:@"john" type:@(DemoHOME) number:johnNumber dialGroup:@0]; + + printf("Checking john... "); + + // + // Find the phone number for "john" + // + id number = [contactdb queryNumber:@"john"]; + + // + // Compare number to ICENone to check if the optional value is set. + // + if(number == ICENone) + { + printf("number is incorrect "); + } + + // + // If not ICENone, the optional is the number NSString. + // + if(![number isEqual:johnNumber]) + { + printf("number is incorrect "); + } + + // Optional can also be used in an out parameter. + id dialgroup; + [contactdb queryDialgroup:@"john" dialGroup:&dialgroup]; + if(dialgroup == ICENone || [dialgroup intValue] != 0) + { + printf("dialgroup is incorrect "); + } + + DemoContact* info = [contactdb query:@"john"]; + // + // All of the info parameters should be set. + // + if(![info hasType] || ![info hasNumber] || ![info hasDialGroup]) + { + printf("info is incorrect "); + } + else if(info.type != DemoHOME || ![info.number isEqual:johnNumber] || info.dialGroup != 0) + { + printf("info is incorrect "); + } + printf("ok\n"); + + // + // Add a contact for "steve". The behavior of the server is to + // default construct the Contact, and then assign all set parameters. + // Since the default value of NumberType in the slice definition + // is HOME and in this case the NumberType is unset it will take + // the default value. + // + NSString* steveNumber = @"234-567-8901"; + [contactdb addContact:@"steve" type:ICENone number:steveNumber dialGroup:@1]; + + printf("Checking steve... "); + number = [contactdb queryNumber:@"steve"]; + if(![number isEqual:steveNumber]) + { + printf("number is incorrect "); + } + + info = [contactdb query:@"steve"]; + // + // Check the value for the NumberType. + // + if(![info hasType] || info.type != DemoHOME) + { + printf("info is incorrect "); + } + + if(![info.number isEqual:steveNumber] || info.dialGroup != 1) + { + printf("info is incorrect "); + } + + [contactdb queryDialgroup:@"steve" dialGroup:&dialgroup]; + if(dialgroup == ICENone || [dialgroup intValue] != 1) + { + printf("dialgroup is incorrect "); + } + + printf("ok\n"); + + // + // Add a contact from "frank". Here the dialGroup field isn't set. + // + NSString* frankNumber = @"345-678-9012"; + [contactdb addContact:@"frank" type:@(DemoCELL) number:frankNumber dialGroup:ICENone]; + + printf("Checking frank... "); + + number = [contactdb queryNumber:@"frank"]; + if(![number isEqual:frankNumber]) + { + printf("number is incorrect "); + } + + info = [contactdb query:@"frank"]; + // + // The dial group field should be unset. + // + if([info hasDialGroup]) + { + printf("info is incorrect "); + } + if(info.type != DemoCELL || ![info.number isEqual:frankNumber]) + { + printf("info is incorrect "); + } + + [contactdb queryDialgroup:@"frank" dialGroup:&dialgroup]; + if(dialgroup != ICENone) + { + printf("dialgroup is incorrect "); + } + printf("ok\n"); + + // + // Add a contact from "anne". The number field isn't set. + // + [contactdb addContact:@"anne" type:@(DemoOFFICE) number:ICENone dialGroup:@2]; + + printf("Checking anne... "); + number = [contactdb queryNumber:@"anne"]; + if(number != ICENone) + { + printf("number is incorrect "); + } + + info = [contactdb query:@"anne"]; + // + // The number field should be unset. + // + if([info hasNumber]) + { + printf("info is incorrect "); + } + if(info.type != DemoOFFICE || info.dialGroup != 2) + { + printf("info is incorrect "); + } + + [contactdb queryDialgroup:@"anne" dialGroup:&dialgroup]; + if(dialgroup == ICENone || [dialgroup intValue] != 2) + { + printf("dialgroup is incorrect "); + } + + // + // The optional fields can be used to determine what fields to + // update on the contact. Here we update only the number for anne, + // the remainder of the fields are unchanged. + // + NSString* anneNumber = @"456-789-0123"; + [contactdb updateContact:@"anne" type:ICENone number:anneNumber dialGroup:ICENone]; + number = [contactdb queryNumber:@"anne"]; + if(![number isEqual:anneNumber]) + { + printf("number is incorrect "); + } + info = [contactdb query:@"anne"]; + if(![info.number isEqual:anneNumber] || info.type != DemoOFFICE || info.dialGroup != 2) + { + printf("info is incorrect "); + } + printf("ok\n"); + + [contactdb shutdown]; + + return EXIT_SUCCESS; +} + +int +main(int argc, char* argv[]) +{ + int status = EXIT_SUCCESS; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = [ICEUtil createProperties]; + [initData.properties load:@"config.client"]; + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(argc, argv, communicator); + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + + if(communicator != nil) + { + @try + { + [communicator destroy]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + } + } + return status; +} diff --git a/objc/demo/Ice/optional/Contact.ice b/objc/demo/Ice/optional/Contact.ice new file mode 100644 index 00000000000..241c8f867a1 --- /dev/null +++ b/objc/demo/Ice/optional/Contact.ice @@ -0,0 +1,43 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +module Demo +{ + +enum NumberType +{ + HOME, + OFFICE, + CELL +}; + +class Contact +{ + string name; + optional(1) NumberType type = HOME; + optional(2) string number; + optional(3) int dialGroup; +}; + +interface ContactDB +{ + void addContact(string name, optional(1) NumberType type, optional(2) string number, optional(3) int dialGroup); + void updateContact(string name, optional(1) NumberType type, optional(2) string number, optional(3) int dialGroup); + + Contact query(string name); + optional(1) string queryNumber(string name); + void queryDialgroup(string name, out optional(1) int dialGroup); + + void shutdown(); +}; + +}; + diff --git a/objc/demo/Ice/optional/ContactDBI.h b/objc/demo/Ice/optional/ContactDBI.h new file mode 100644 index 00000000000..ff11d32e5b0 --- /dev/null +++ b/objc/demo/Ice/optional/ContactDBI.h @@ -0,0 +1,20 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +#import <Contact.h> + +@interface ContactDBI : DemoContactDB<DemoContactDB> +{ +@private + NSMutableDictionary* contacts_; +} ++(id) contactDBI; +@end diff --git a/objc/demo/Ice/optional/ContactDBI.m b/objc/demo/Ice/optional/ContactDBI.m new file mode 100644 index 00000000000..65aa6daa771 --- /dev/null +++ b/objc/demo/Ice/optional/ContactDBI.m @@ -0,0 +1,114 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#import <objc/Ice.h> + +#import <ContactDBI.h> + +#include <stdio.h> + +@implementation ContactDBI +-(id) init +{ + self = [super init]; + if(self) + { + self->contacts_ = [[NSMutableDictionary alloc] init]; + } + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [self->contacts_ release]; + [super dealloc]; +} +#endif + ++(id) contactDBI +{ + id instance = [[ContactDBI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [instance autorelease]; +#endif + return instance; +} + +-(void) addContact:(NSMutableString*)name type:(id)type number:(id)number dialGroup:(id)dialGroup + current:(ICECurrent*)current +{ + DemoContact* contact = [DemoContact contact]; + contact.name = name; + if(type != ICENone) + { + contact.type = [type intValue]; + } + if(number != ICENone) + { + contact.number = number; + } + if(dialGroup != ICENone) + { + contact.dialGroup = [dialGroup intValue]; + } + [contacts_ setObject:contact forKey:name]; +} + +-(void) updateContact:(NSMutableString*)name type:(id)type number:(id)number dialGroup:(id)dialGroup + current:(ICECurrent *)current +{ + DemoContact* contact = [contacts_ objectForKey:name]; + if(contact != nil) + { + if(type != ICENone) + { + contact.type = [type intValue]; + } + if(number != ICENone) + { + contact.number = number; + } + if(dialGroup != ICENone) + { + contact.dialGroup = [dialGroup intValue]; + } + } +} + +-(DemoContact*) query:(NSMutableString*)name current:(ICECurrent *)current +{ + return [contacts_ objectForKey:name]; +} + +-(id) queryNumber:(NSMutableString*)name current:(ICECurrent *)current +{ + DemoContact* contact = [contacts_ objectForKey:name]; + if(contact != nil && [contact hasNumber]) + { + return contact.number; + } + return ICENone; +} + +-(void) queryDialgroup:(NSMutableString*)name dialGroup:(id*)dialGroup current:(ICECurrent *)current +{ + DemoContact* contact = [contacts_ objectForKey:name]; + if(contact != nil && [contact hasDialGroup]) + { + *dialGroup = @(contact.dialGroup); + } +} + +-(void) shutdown:(ICECurrent *)current +{ + printf("Shutting down...\n"); + [[current.adapter getCommunicator] shutdown]; +} +@end diff --git a/objc/demo/Ice/optional/Makefile b/objc/demo/Ice/optional/Makefile new file mode 100644 index 00000000000..bc70921eb5e --- /dev/null +++ b/objc/demo/Ice/optional/Makefile @@ -0,0 +1,36 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = Contact.o + +COBJS = Client.o \ + +SOBJS = ContactDBI.o \ + Server.o + +OBJS = $(SLICE_OBJS) $(COBJS) $(SOBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. $(CPPFLAGS) + +$(CLIENT): $(SLICE_OBJS) $(COBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SLICE_OBJS) $(COBJS) $(LIBS) + +$(SERVER): $(SLICE_OBJS) $(SOBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SLICE_OBJS) $(SOBJS) $(LIBS) diff --git a/objc/demo/Ice/optional/README b/objc/demo/Ice/optional/README new file mode 100644 index 00000000000..c8e2f5efa44 --- /dev/null +++ b/objc/demo/Ice/optional/README @@ -0,0 +1,10 @@ +This demo illustrates the use of optional class members and +parameters. + +To run the demo, first start the server: + +$ server + +In a separate window, start the client: + +$ client diff --git a/objc/demo/Ice/optional/Server.m b/objc/demo/Ice/optional/Server.m new file mode 100644 index 00000000000..91f278daac0 --- /dev/null +++ b/objc/demo/Ice/optional/Server.m @@ -0,0 +1,65 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <ContactDBI.h> + + +int +run(int argc, char* argv[], id<ICECommunicator> communicator) +{ + if(argc > 1) + { + NSLog(@"%s: too many arguments", argv[0]); + return EXIT_FAILURE; + } + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"ContactDB"]; + [adapter add:[ContactDBI contactDBI] identity:[communicator stringToIdentity:@"contactdb"]]; + [adapter activate]; + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +int +main(int argc, char* argv[]) +{ + int status = EXIT_SUCCESS; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = [ICEUtil createProperties]; + [initData.properties load:@"config.server"]; + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(argc, argv, communicator); + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + + if(communicator != nil) + { + @try + { + [communicator destroy]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + } + } + return status; +} diff --git a/objc/demo/Ice/optional/config.client b/objc/demo/Ice/optional/config.client new file mode 100644 index 00000000000..596855e5e00 --- /dev/null +++ b/objc/demo/Ice/optional/config.client @@ -0,0 +1,10 @@ +# +# The client reads this property to create the reference to the +# "ContactDB" object in the server. +# +ContactDB.Proxy=contactdb:default -p 10000 -h localhost + +# +# Warn about connection exceptions +# +Ice.Warn.Connections=1 diff --git a/objc/demo/Ice/optional/config.server b/objc/demo/Ice/optional/config.server new file mode 100644 index 00000000000..28294ccd18e --- /dev/null +++ b/objc/demo/Ice/optional/config.server @@ -0,0 +1,11 @@ +# +# The server creates one single object adapter with the name +# "ContactDB". The following line sets the endpoints for this +# adapter. +# +ContactDB.Endpoints=default -p 10000 -h localhost + +# +# Warn about connection exceptions +# +Ice.Warn.Connections=1 diff --git a/objc/demo/Ice/optional/expect.py b/objc/demo/Ice/optional/expect.py new file mode 100755 index 00000000000..ec5d2825528 --- /dev/null +++ b/objc/demo/Ice/optional/expect.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import sys, os + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(path[0]) + +from demoscript import Util +from demoscript.Ice import optional + +server = Util.spawn('./server --Ice.PrintAdapterReady --Ice.Warn.Connections=0') +server.expect('.* ready') +client = Util.spawn('./client --Ice.Warn.Connections=0') + +optional.run(client, server) diff --git a/objc/demo/Makefile b/objc/demo/Makefile new file mode 100644 index 00000000000..db858c45c7a --- /dev/null +++ b/objc/demo/Makefile @@ -0,0 +1,21 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = .. + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = Ice Database Manual + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done diff --git a/objc/demo/Manual/Makefile b/objc/demo/Manual/Makefile new file mode 100644 index 00000000000..4a954e0f0bf --- /dev/null +++ b/objc/demo/Manual/Makefile @@ -0,0 +1,21 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = printer simple_filesystem + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done diff --git a/objc/demo/Manual/README b/objc/demo/Manual/README new file mode 100644 index 00000000000..909403402a1 --- /dev/null +++ b/objc/demo/Manual/README @@ -0,0 +1,11 @@ +Demos in this directory: + +- printer + + An implementation of the simple printer example at the beginning of + the Ice manual. + +- simple_filesystem + + An implementation of the simple (non-persistent, non-life-cycle) + version of the file system example. diff --git a/objc/demo/Manual/printer/.gitignore b/objc/demo/Manual/printer/.gitignore new file mode 100644 index 00000000000..db9e318076b --- /dev/null +++ b/objc/demo/Manual/printer/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +Printer.m +Printer.h diff --git a/objc/demo/Manual/printer/Client.m b/objc/demo/Manual/printer/Client.m new file mode 100644 index 00000000000..11f8341e751 --- /dev/null +++ b/objc/demo/Manual/printer/Client.m @@ -0,0 +1,49 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <Printer.h> +#import <stdio.h> + + +int +main(int argc, char* argv[]) +{ + int status = EXIT_FAILURE; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + communicator = [ICEUtil createCommunicator:&argc argv:argv]; + id<ICEObjectPrx> base = [communicator stringToProxy:@"SimplePrinter:default -p 10000"]; + id<DemoPrinterPrx> printer = [DemoPrinterPrx checkedCast:base]; + if(!printer) + { + [NSException raise:@"Invalid proxy" format:@""]; + } + [printer printString:@"Hello World!"]; + status = EXIT_SUCCESS; + } + @catch(NSException* ex) + { + NSLog(@"%@", ex); + } + + @try + { + [communicator destroy]; + } + @catch (NSException* ex) + { + NSLog(@"%@", ex); + } + } + return status; +} diff --git a/objc/demo/Manual/printer/Makefile b/objc/demo/Manual/printer/Makefile new file mode 100644 index 00000000000..8229a1b58e2 --- /dev/null +++ b/objc/demo/Manual/printer/Makefile @@ -0,0 +1,35 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = Printer.o + +COBJS = Client.o + +SOBJS = Server.o + +OBJS = $(SLICE_OBJS) $(COBJS) $(SOBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. $(CPPFLAGS) + +$(CLIENT): $(SLICE_OBJS) $(COBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SLICE_OBJS) $(COBJS) $(LIBS) + +$(SERVER): $(SLICE_OBJS) $(SOBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SLICE_OBJS) $(SOBJS) $(LIBS) diff --git a/objc/demo/Manual/printer/Printer.ice b/objc/demo/Manual/printer/Printer.ice new file mode 100644 index 00000000000..673897fa777 --- /dev/null +++ b/objc/demo/Manual/printer/Printer.ice @@ -0,0 +1,20 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Demo +{ + + interface Printer + { + void printString(string s); + }; + +}; diff --git a/objc/demo/Manual/printer/README b/objc/demo/Manual/printer/README new file mode 100644 index 00000000000..a08f94f511a --- /dev/null +++ b/objc/demo/Manual/printer/README @@ -0,0 +1,8 @@ +This demo implements the printer example in the Ice manual. To run it, +start the server in a window: + +$ server + +In a separate window, run the client: + +$ client diff --git a/objc/demo/Manual/printer/Server.m b/objc/demo/Manual/printer/Server.m new file mode 100644 index 00000000000..d0359b07460 --- /dev/null +++ b/objc/demo/Manual/printer/Server.m @@ -0,0 +1,68 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <Printer.h> +#import <stdio.h> + +@interface PrinterI : DemoPrinter <DemoPrinter> +@end + +@implementation PrinterI ++(id) printerI +{ + id instance = [[PrinterI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [instance autorelease]; +#endif + return instance; +} +-(void) printString:(NSMutableString *)s current:(ICECurrent *)current +{ + printf("%s\n", [s UTF8String]); + fflush(stdout); +} +@end + +int +main(int argc, char* argv[]) +{ + int status = EXIT_FAILURE; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + communicator = [ICEUtil createCommunicator:&argc argv:argv]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapterWithEndpoints:@"SimplePrinterAdapter" + endpoints:@"default -p 10000"]; + [adapter add:[PrinterI printerI] identity:[communicator stringToIdentity:@"SimplePrinter"]]; + [adapter activate]; + + [communicator waitForShutdown]; + + status = EXIT_SUCCESS; + } + @catch (NSException* ex) + { + NSLog(@"%@", ex); + } + + @try + { + [communicator destroy]; + } + @catch (NSException* ex) + { + NSLog(@"%@", ex); + } + + } + return status; +} diff --git a/objc/demo/Manual/printer/expect.py b/objc/demo/Manual/printer/expect.py new file mode 100755 index 00000000000..a0237fca2e5 --- /dev/null +++ b/objc/demo/Manual/printer/expect.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ] +if len(path) == 0: + raise "can't find toplevel directory!" +sys.path.append(path[0]) + +from demoscript import * +import signal + +server = Util.spawn('./server --Ice.PrintAdapterReady') +server.expect('.* ready') + +print "testing...", +sys.stdout.flush() +client = Util.spawn('./client') +client.waitTestSuccess() +server.expect('Hello World!') +server.kill(signal.SIGTERM) +server.waitTestSuccess(-signal.SIGTERM) +print "ok" diff --git a/objc/demo/Manual/simple_filesystem/.gitignore b/objc/demo/Manual/simple_filesystem/.gitignore new file mode 100644 index 00000000000..091f857486f --- /dev/null +++ b/objc/demo/Manual/simple_filesystem/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +Filesystem.m +Filesystem.h diff --git a/objc/demo/Manual/simple_filesystem/Client.m b/objc/demo/Manual/simple_filesystem/Client.m new file mode 100644 index 00000000000..08119f30d68 --- /dev/null +++ b/objc/demo/Manual/simple_filesystem/Client.m @@ -0,0 +1,99 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <Filesystem.h> +#import <stdio.h> + + +static void +printIndent(int depth) +{ + while(depth-- > 0) + { + putchar('\t'); + } +} + +// Recursively print the contents of directory "dir" in tree fashion. +// For files, show the contents of each file. The "depth" +// parameter is the current nesting level (for indentation). + +static void +listRecursive(id<FSDirectoryPrx> dir, int depth) +{ + ++depth; + FSNodeSeq *contents = [dir list]; + + for(id<FSNodePrx> node in contents) + { + id<FSDirectoryPrx> dir = [FSDirectoryPrx checkedCast:node]; + id<FSFilePrx> file = [FSFilePrx uncheckedCast:node]; + printIndent(depth); + printf("%s%s\n", [[node name] UTF8String], (dir ? " (directory):" : " (file):")); + if(dir) + { + listRecursive(dir, depth); + } + else + { + FSLines *text = [file read]; + for(NSString *line in text) + { + printIndent(depth); + printf("\t%s\n", [line UTF8String]); + } + } + } +} + +int +main(int argc, char* argv[]) +{ + int status = EXIT_FAILURE; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + communicator = [ICEUtil createCommunicator:&argc argv:argv]; + // + // Create a proxy for the root directory + // + id<FSDirectoryPrx> rootDir = [FSDirectoryPrx checkedCast: + [communicator stringToProxy:@"RootDir:default -p 10000"]]; + if(!rootDir) + { + [NSException raise:@"invalid proxy" format:@"nil"]; + } + + // + // Recursively list the contents of the root directory + // + printf("Contents of root directory:\n"); + listRecursive(rootDir, 0); + + status = EXIT_SUCCESS; + } + @catch (NSException *ex) + { + NSLog(@"%@\n", ex); + } + + @try + { + [communicator destroy]; + } + @catch (NSException* ex) + { + NSLog(@"%@\n", ex); + } + } + return status; +} diff --git a/objc/demo/Manual/simple_filesystem/DirectoryI.h b/objc/demo/Manual/simple_filesystem/DirectoryI.h new file mode 100644 index 00000000000..a82e49beea6 --- /dev/null +++ b/objc/demo/Manual/simple_filesystem/DirectoryI.h @@ -0,0 +1,28 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <Filesystem.h> + +@interface DirectoryI : FSDirectory <FSDirectory> +{ + @private + NSString *myName; + DirectoryI *parent; + ICEIdentity *ident; + NSMutableArray *contents; +} +@property(nonatomic, retain) NSString *myName; +@property(nonatomic, retain) DirectoryI *parent; +@property(nonatomic, retain) ICEIdentity *ident; +@property(nonatomic, retain) NSMutableArray *contents; + ++(id) directoryi:(NSString *)name parent:(DirectoryI *)parent; +-(void) addChild:(id<FSNodePrx>)child; +-(void) activate:(id<ICEObjectAdapter>)a; +@end diff --git a/objc/demo/Manual/simple_filesystem/DirectoryI.m b/objc/demo/Manual/simple_filesystem/DirectoryI.m new file mode 100644 index 00000000000..bfd0bc7be6a --- /dev/null +++ b/objc/demo/Manual/simple_filesystem/DirectoryI.m @@ -0,0 +1,68 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <objc/Ice.h> +#include <DirectoryI.h> + +@implementation DirectoryI + +@synthesize myName; +@synthesize parent; +@synthesize ident; +@synthesize contents; + ++(id) directoryi:(NSString *)name parent:(DirectoryI *)parent +{ + DirectoryI *instance = [[DirectoryI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [instance autorelease]; +#endif + if(instance == nil) + { + return nil; + } + instance.myName = name; + instance.parent = parent; + instance.ident = [ICEIdentity identity:(parent ? [ICEUtil generateUUID] : @"RootDir") category:nil]; + instance.contents = [[NSMutableArray alloc] init]; + return instance; +} + +-(NSString *) name:(ICECurrent *)current +{ + return myName; +} + +-(NSArray *) list:(ICECurrent *)current +{ + return contents; +} + +-(void) addChild:(id<FSNodePrx>)child +{ + [contents addObject:child]; +} + +-(void) activate:(id<ICEObjectAdapter>)a +{ + id<FSNodePrx> thisNode = [FSNodePrx uncheckedCast:[a add:self identity:ident]]; + [parent addChild:thisNode]; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [myName release]; + [parent release]; + [ident release]; + [contents release]; + [super dealloc]; +} +#endif +@end diff --git a/objc/demo/Manual/simple_filesystem/FileI.h b/objc/demo/Manual/simple_filesystem/FileI.h new file mode 100644 index 00000000000..7179269e785 --- /dev/null +++ b/objc/demo/Manual/simple_filesystem/FileI.h @@ -0,0 +1,31 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <Filesystem.h> + +@class DirectoryI; + +@interface FileI : FSFile <FSFile> +{ + @private + NSString *myName; + DirectoryI *parent; + ICEIdentity *ident; + NSArray *lines; +} + +@property(nonatomic, retain) NSString *myName; +@property(nonatomic, retain) DirectoryI *parent; +@property(nonatomic, retain) ICEIdentity *ident; +@property(nonatomic, retain) NSArray *lines; + ++(id) filei:(NSString *)name parent:(DirectoryI *)parent; +-(void) write:(NSMutableArray *)text current:(ICECurrent *)current; +-(void) activate:(id<ICEObjectAdapter>)a; +@end diff --git a/objc/demo/Manual/simple_filesystem/FileI.m b/objc/demo/Manual/simple_filesystem/FileI.m new file mode 100644 index 00000000000..7f67a94b81a --- /dev/null +++ b/objc/demo/Manual/simple_filesystem/FileI.m @@ -0,0 +1,68 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <objc/Ice.h> +#include <FileI.h> +#include <DirectoryI.h> + +@implementation FileI + +@synthesize myName; +@synthesize parent; +@synthesize ident; +@synthesize lines; + ++(id) filei:(NSString *)name parent:(DirectoryI *)parent +{ + FileI *instance = [[FileI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [instance autorelease]; +#endif + if(instance == nil) + { + return nil; + } + instance.myName = name; + instance.parent = parent; + instance.ident = [ICEIdentity identity:[ICEUtil generateUUID] category:nil]; + return instance; +} + +-(NSString *) name:(ICECurrent *)current +{ + return myName; +} + +-(NSArray *) read:(ICECurrent *)current +{ + return lines; +} + +-(void) write:(NSMutableArray *)text current:(ICECurrent *)current +{ + self.lines = text; +} + +-(void) activate:(id<ICEObjectAdapter>)a +{ + id<FSNodePrx> thisNode = [FSNodePrx uncheckedCast:[a add:self identity:ident]]; + [parent addChild:thisNode]; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [myName release]; + [parent release]; + [ident release]; + [lines release]; + [super dealloc]; +} +#endif +@end diff --git a/objc/demo/Manual/simple_filesystem/Filesystem.ice b/objc/demo/Manual/simple_filesystem/Filesystem.ice new file mode 100644 index 00000000000..6bc1550deae --- /dev/null +++ b/objc/demo/Manual/simple_filesystem/Filesystem.ice @@ -0,0 +1,32 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +["objc:prefix:FS"] +module Filesystem { + exception GenericError { + string reason; + }; + + interface Node { + idempotent string name(); + }; + + sequence<string> Lines; + + interface File extends Node { + idempotent Lines read(); + idempotent void write(Lines text) throws GenericError; + }; + + sequence<Node*> NodeSeq; + + interface Directory extends Node { + idempotent NodeSeq list(); + }; +}; diff --git a/objc/demo/Manual/simple_filesystem/Makefile b/objc/demo/Manual/simple_filesystem/Makefile new file mode 100644 index 00000000000..13d2cab31a6 --- /dev/null +++ b/objc/demo/Manual/simple_filesystem/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = Filesystem.o + +COBJS = Client.o + +SOBJS = Server.o \ + DirectoryI.o \ + FileI.o + +OBJS = $(SLICE_OBJS) $(COBJS) $(SOBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. $(CPPFLAGS) + +$(CLIENT): $(SLICE_OBJS) $(COBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SLICE_OBJS) $(COBJS) $(LIBS) + +$(SERVER): $(SLICE_OBJS) $(SOBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SLICE_OBJS) $(SOBJS) $(LIBS) diff --git a/objc/demo/Manual/simple_filesystem/README b/objc/demo/Manual/simple_filesystem/README new file mode 100644 index 00000000000..3340e363bad --- /dev/null +++ b/objc/demo/Manual/simple_filesystem/README @@ -0,0 +1,10 @@ +This demo implements the simple filesystem application shown in the +Objective-C mapping documentation. + +To run it, start the server in a window: + +$ server + +Then run the client in a separate window: + +$ client diff --git a/objc/demo/Manual/simple_filesystem/Server.m b/objc/demo/Manual/simple_filesystem/Server.m new file mode 100644 index 00000000000..b8f5a6488cb --- /dev/null +++ b/objc/demo/Manual/simple_filesystem/Server.m @@ -0,0 +1,86 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <FileI.h> +#import <DirectoryI.h> + +int +main(int argc, char* argv[]) +{ + int status = EXIT_FAILURE; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + communicator = [ICEUtil createCommunicator:&argc argv:argv]; + + id<ICEObjectAdapter> adapter = [communicator createObjectAdapterWithEndpoints:@"SimpleFilesystem" + endpoints:@"default -p 10000"]; + + // + // Create the root directory (with name "/" and no parent) + // + DirectoryI *root = [DirectoryI directoryi:@"/" parent:nil]; + [root activate:adapter]; + + // + // Create a file called "README" in the root directory + // + FileI *file = [FileI filei:@"README" parent:root]; + NSMutableArray *text = [NSMutableArray arrayWithObject:@"This file system contains a collection of poetry."]; + [file write:text current:nil]; + [file activate:adapter]; + + // + // Create a directory called "Coleridge" in the root directory + // + DirectoryI *coleridge = [DirectoryI directoryi:@"Coleridge" parent:root]; + [coleridge activate:adapter]; + + // + // Create a file called "Kubla_Khan" in the Coleridge directory + // + file = [FileI filei:@"Kubla_Khan" parent:coleridge]; + text = [NSMutableArray arrayWithObjects:@"In Xanadu did Kubla Khan", + @"A stately pleasure-dome decree:", + @"Where Alph, the sacred river, ran", + @"Through caverns measureless to man", + @"Down to a sunless sea.", nil]; + [file write:text current:nil]; + [file activate:adapter]; + + // + // All objects are created, allow client requests now + // + [adapter activate]; + + // + // Wait until we are done + // + [communicator waitForShutdown]; + status = EXIT_SUCCESS; + } + @catch (NSException* ex) + { + NSLog(@"%@", ex); + } + + @try + { + [communicator destroy]; + } + @catch (NSException* ex) + { + NSLog(@"%@", ex); + } + } + return status; +} diff --git a/objc/demo/Manual/simple_filesystem/expect.py b/objc/demo/Manual/simple_filesystem/expect.py new file mode 100755 index 00000000000..f99aae6caca --- /dev/null +++ b/objc/demo/Manual/simple_filesystem/expect.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +import sys, os + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ] +if len(path) == 0: + raise "can't find toplevel directory!" +sys.path.append(path[0]) + +from demoscript import * + +import signal + +server = Util.spawn('./server --Ice.PrintAdapterReady') +server.expect('.* ready') + +print "testing...", +sys.stdout.flush() +client = Util.spawn('./client') +client.expect('Contents of root directory:\n.*Down to a sunless sea.') +client.waitTestSuccess() +server.kill(signal.SIGINT) +server.waitTestSuccess(-2) +print "ok" diff --git a/objc/demo/README b/objc/demo/README new file mode 100644 index 00000000000..fbb8e1fd642 --- /dev/null +++ b/objc/demo/README @@ -0,0 +1,10 @@ +This directory contains demos for various Ice components. The demos +are provided to get you started on how to use a particular feature or +coding technique. See the README file in each subdirectory for details +on the demos. + +The Manual directory contains demos for some of the code examples in the +Ice manual. + +For more examples of the features of the Ice services (Glacier2, +IceGrid, IceStorm) please see the demos in the Ice for C++ distibution. diff --git a/objc/include/Makefile b/objc/include/Makefile new file mode 100644 index 00000000000..2a18dba02a5 --- /dev/null +++ b/objc/include/Makefile @@ -0,0 +1,21 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = .. + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = objc + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done diff --git a/objc/include/objc/Glacier2.h b/objc/include/objc/Glacier2.h new file mode 100644 index 00000000000..7221a60b7a4 --- /dev/null +++ b/objc/include/objc/Glacier2.h @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Glacier2 Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import "Glacier2/Glacier2.h" diff --git a/objc/include/objc/Glacier2/.gitignore b/objc/include/objc/Glacier2/.gitignore new file mode 100644 index 00000000000..382c7a11d64 --- /dev/null +++ b/objc/include/objc/Glacier2/.gitignore @@ -0,0 +1,10 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +Metrics.h +PermissionsVerifierF.h +PermissionsVerifier.h +Router.h +RouterF.h +Session.h +SSLInfo.h diff --git a/objc/include/objc/Glacier2/Glacier2.h b/objc/include/objc/Glacier2/Glacier2.h new file mode 100644 index 00000000000..e4b1185f184 --- /dev/null +++ b/objc/include/objc/Glacier2/Glacier2.h @@ -0,0 +1,14 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Glacier2/Metrics.h> +#import <objc/Glacier2/PermissionsVerifier.h> +#import <objc/Glacier2/Router.h> +#import <objc/Glacier2/SSLInfo.h> +#import <objc/Glacier2/Session.h> diff --git a/objc/include/objc/Glacier2/Makefile b/objc/include/objc/Glacier2/Makefile new file mode 100644 index 00000000000..e5efc6949fc --- /dev/null +++ b/objc/include/objc/Glacier2/Makefile @@ -0,0 +1,26 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = ../../.. + +include $(top_srcdir)/config/Make.rules + +install:: + @if test ! -d $(DESTDIR)$(install_includedir)/Glacier2 ; \ + then \ + echo "Creating $(DESTDIR)$(install_includedir)/Glacier2..." ; \ + $(call mkdir,$(DESTDIR)$(install_includedir)/Glacier2) ; \ + fi + + @for i in *.h ; \ + do \ + echo "Installing $$i" ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(install_includedir)/Glacier2/$$i ; \ + chmod a+r $(DESTDIR)$(install_includedir)/Glacier2/$$i ; \ + done diff --git a/objc/include/objc/Ice.h b/objc/include/objc/Ice.h new file mode 100644 index 00000000000..e551f1a54d4 --- /dev/null +++ b/objc/include/objc/Ice.h @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import "Ice/Ice.h" diff --git a/objc/include/objc/Ice/.gitignore b/objc/include/objc/Ice/.gitignore new file mode 100644 index 00000000000..072c49f1ac4 --- /dev/null +++ b/objc/include/objc/Ice/.gitignore @@ -0,0 +1,17 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +BuiltinSequences.h +Identity.h +Locator.h +LocatorF.h +LocalException.h +Metrics.h +Process.h +ProcessF.h +PropertiesAdmin.h +RemoteLogger.h +Router.h +RouterF.h +SliceChecksumDict.h +Version.h diff --git a/objc/include/objc/Ice/Communicator.h b/objc/include/objc/Ice/Communicator.h new file mode 100644 index 00000000000..4c25016fa4f --- /dev/null +++ b/objc/include/objc/Ice/Communicator.h @@ -0,0 +1,63 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +// +// Forward declarations +// +@protocol ICEObjectPrx; +@protocol ICERouterPrx; +@protocol ICELocatorPrx; +@protocol ICELogger; +@protocol ICEProperties; +@protocol ICEObjectAdapter; +@protocol ICEObjectFactory; +@protocol ICEAsyncResult; +@protocol ICEImplicitContext; +@protocol ICEObject; +@class ICEIdentity; +@class ICEException; + +@protocol ICECommunicator <NSObject> +-(void) destroy; +-(void) shutdown; +-(void) waitForShutdown; +-(BOOL) isShutdown; +-(id<ICEObjectPrx>) stringToProxy:(NSString*)str; +-(NSString*)proxyToString:(id<ICEObjectPrx>)obj; +-(id<ICEObjectPrx>)propertyToProxy:(NSString*)property; +-(NSMutableDictionary*)proxyToProperty:(id<ICEObjectPrx>)prx property:(NSString*)property; +-(ICEIdentity*) stringToIdentity:(NSString*)str; +-(NSString*) identityToString:(ICEIdentity*)ident; +-(id<ICEObjectAdapter>) createObjectAdapter:(NSString*)name; +-(id<ICEObjectAdapter>) createObjectAdapterWithEndpoints:(NSString*)name endpoints:(NSString*)endpoints; +-(id<ICEObjectAdapter>) createObjectAdapterWithRouter:(NSString*)name router:(id<ICERouterPrx>)rtr; +-(void) addObjectFactory:(id<ICEObjectFactory>)factory sliceId:(NSString*)sliceId; +-(id<ICEObjectFactory>) findObjectFactory:(NSString*)sliceId; +-(id<ICEImplicitContext>) getImplicitContext; +-(id<ICEProperties>) getProperties; +-(id<ICELogger>) getLogger; +//-(ICEStats*) getStats; +-(id<ICERouterPrx>) getDefaultRouter; +-(void) setDefaultRouter:(id<ICERouterPrx>)rtr; +-(id<ICELocatorPrx>) getDefaultLocator; +-(void) setDefaultLocator:(id<ICELocatorPrx>)loc; +//-(PluginManager*) getPluginManager; +-(void) flushBatchRequests; +-(id<ICEAsyncResult>) begin_flushBatchRequests; +-(id<ICEAsyncResult>) begin_flushBatchRequests:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_flushBatchRequests:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(void) end_flushBatchRequests:(id<ICEAsyncResult>)result; +-(id<ICEObjectPrx>) getAdmin; +//void addAdminFacet(Object servant, NSString* facet); +//Object removeAdminFacet(NSString* facet); +-(id<ICEObject>) findAdminFacet:(NSString*)facet; + +@end diff --git a/objc/include/objc/Ice/Config.h b/objc/include/objc/Ice/Config.h new file mode 100644 index 00000000000..cef64455eb5 --- /dev/null +++ b/objc/include/objc/Ice/Config.h @@ -0,0 +1,41 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +// +// Some import files we need almost everywhere +// +#import <Foundation/NSObject.h> +#import <Foundation/NSString.h> +#import <Foundation/NSArray.h> +#import <Foundation/NSDictionary.h> +#import <Foundation/NSData.h> +#import <Foundation/NSNull.h> + +#import <stdlib.h> + +// +// Don't forget to update the conversion methods from Util.h if the types below +// are changed. +// +typedef unsigned char ICEByte; +typedef short ICEShort; +typedef int ICEInt; +typedef long long ICELong; +typedef float ICEFloat; +typedef double ICEDouble; + +#if defined(__clang__) && __has_feature(objc_arc) +# define ICE_STRONG_QUALIFIER __strong +# define ICE_AUTORELEASING_QUALIFIER __autoreleasing +# define ICE_STRONG_ATTR strong +#else +# define ICE_STRONG_QUALIFIER +# define ICE_AUTORELEASING_QUALIFIER +# define ICE_STRONG_ATTR retain +#endif diff --git a/objc/include/objc/Ice/Connection.h b/objc/include/objc/Ice/Connection.h new file mode 100644 index 00000000000..6ab911cca2b --- /dev/null +++ b/objc/include/objc/Ice/Connection.h @@ -0,0 +1,89 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +// +// Forward declarations +// +@class ICEIdentity; +@class ICEException; + +@protocol ICEObjectPrx; +@protocol ICEObjectAdapter; +@protocol ICEAsyncResult; +@protocol ICEEndpoint; + +@interface ICEConnectionInfo : NSObject +{ +@protected + BOOL incoming; + NSString* adapterName; + NSString* connectionId; +} + +@property(nonatomic) BOOL incoming; +@property(nonatomic, retain) NSString* adapterName; +@property(nonatomic, retain) NSString* connectionId; +@end + +@interface ICEIPConnectionInfo : ICEConnectionInfo +{ +@protected + NSString* localAddress; + ICEInt localPort; + NSString* remoteAddress; + ICEInt remotePort; +} + +@property(nonatomic, retain) NSString* localAddress; +@property(nonatomic) ICEInt localPort; +@property(nonatomic, retain) NSString* remoteAddress; +@property(nonatomic) ICEInt remotePort; +@end + +@interface ICETCPConnectionInfo : ICEIPConnectionInfo +@end + +@interface ICEUDPConnectionInfo : ICEIPConnectionInfo +{ +@private + NSString* mcastAddress; + ICEInt mcastPort; +} +@property(nonatomic, retain) NSString* mcastAddress; +@property(nonatomic) ICEInt mcastPort; +@end + +@interface ICESSLConnectionInfo : ICEIPConnectionInfo +{ +@private + NSString* cipher; + NSArray* certs; +} +@property(nonatomic, retain) NSString* cipher; +@property(nonatomic, retain) NSArray* certs; +@end + +@protocol ICEConnection <NSObject> +-(void) close:(BOOL)force; +-(id<ICEObjectPrx>) createProxy:(ICEIdentity*)identity; +-(void) setAdapter:(id<ICEObjectAdapter>)adapter; +-(id<ICEObjectAdapter>) getAdapter; +-(void) flushBatchRequests; +-(id<ICEAsyncResult>) begin_flushBatchRequests; +-(id<ICEAsyncResult>) begin_flushBatchRequests:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_flushBatchRequests:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(void) end_flushBatchRequests:(id<ICEAsyncResult>)result; +-(NSString*) type; +-(ICEInt) timeout; +-(NSString*) toString; +-(ICEConnectionInfo*) getInfo; +-(id<ICEEndpoint>) getEndpoint; +@end diff --git a/objc/include/objc/Ice/Current.h b/objc/include/objc/Ice/Current.h new file mode 100644 index 00000000000..6f4f0c793f5 --- /dev/null +++ b/objc/include/objc/Ice/Current.h @@ -0,0 +1,85 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> +#import <objc/Ice/Stream.h> + +// +// Forward declarations +// +@protocol ICEObjectAdapter; +@protocol ICEConnection; +@class ICEIdentity; +@class ICEEncodingVersion; + +typedef NSDictionary ICEContext; +typedef NSMutableDictionary ICEMutableContext; + +typedef enum +{ + ICENormal, + ICENonmutating, + ICEIdempotent +} ICEOperationMode; + +@interface ICECurrent : NSObject <NSCopying> +{ + @private + id<ICEObjectAdapter> adapter; + id<ICEConnection> con; + ICEIdentity *id_; + NSString *facet; + NSString *operation; + ICEOperationMode mode; + NSDictionary *ctx; + ICEInt requestId; + ICEEncodingVersion *encoding; +} + +@property(nonatomic, retain) id<ICEObjectAdapter> adapter; +@property(nonatomic, retain) id<ICEConnection> con; +@property(nonatomic, retain) ICEIdentity *id_; +@property(nonatomic, retain) NSString *facet; +@property(nonatomic, retain) NSString *operation; +@property(nonatomic, assign) ICEOperationMode mode; +@property(nonatomic, retain) NSDictionary *ctx; +@property(nonatomic, assign) ICEInt requestId; +@property(nonatomic, assign) ICEEncodingVersion *encoding; + +-(id) init:(id<ICEObjectAdapter>)adapter + con:(id<ICEConnection>)con_ + id_:(ICEIdentity *)id_ + facet:(NSString *)facet + operation:(NSString *)operation + mode:(ICEOperationMode)mode + ctx:(NSDictionary *)ctx + requestId:(ICEInt)requestId + encoding:(ICEEncodingVersion*)encoding; + ++(id) current:(id<ICEObjectAdapter>)adapter + con:(id<ICEConnection>)con_ + id_:(ICEIdentity *)id_ + facet:(NSString *)facet + operation:(NSString *)operation + mode:(ICEOperationMode)mode + ctx:(NSDictionary *)ctx + requestId:(ICEInt)requestId + encoding:(ICEEncodingVersion*)encoding; + ++(id) current; +// This class also overrides copyWithZone:, hash, isEqual:, and dealloc. +@end + +@interface ICEContextHelper : ICEDictionaryHelper +@end + +@interface ICEOperationModeHelper : ICEEnumHelper ++(ICEInt) getMinValue; ++(ICEInt) getMaxValue; +@end diff --git a/objc/include/objc/Ice/DispatchInterceptor.h b/objc/include/objc/Ice/DispatchInterceptor.h new file mode 100644 index 00000000000..2e6a773e6ed --- /dev/null +++ b/objc/include/objc/Ice/DispatchInterceptor.h @@ -0,0 +1,27 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Object.h> + +@protocol ICEDispatchInterceptor <ICEObject> +-(BOOL) dispatch:(id<ICERequest>)request; +@end + +@interface ICEDispatchInterceptor : ICEObject +@end + +@interface ICEMainThreadDispatch : ICEDispatchInterceptor<ICEDispatchInterceptor> +{ + ICEObject* servant; +} + +-(id)init:(ICEObject*)servant; ++(id)mainThreadDispatch:(ICEObject*)servant; +@end + diff --git a/objc/include/objc/Ice/Endpoint.h b/objc/include/objc/Ice/Endpoint.h new file mode 100644 index 00000000000..fb5fb7c2f8b --- /dev/null +++ b/objc/include/objc/Ice/Endpoint.h @@ -0,0 +1,90 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +typedef enum +{ + ICERandom, + ICEOrdered +} ICEEndpointSelectionType; + +extern const int ICETCPEndpointType; +extern const int ICESSLEndpointType; +extern const int ICEUDPEndpointType; + +@class ICEEncodingVersion; // Required by ICEOpaqueEndpointInfo + +@protocol ICEEndpointInfo<NSObject> +-(ICEShort) type; +-(BOOL) datagram; +-(BOOL) secure; +@end + +@interface ICEEndpointInfo : NSObject<ICEEndpointInfo> +{ +@protected + ICEInt timeout; + BOOL compress; + ICEShort type_; + BOOL datagram_; + BOOL secure_; +} + +@property(nonatomic) ICEInt timeout; +@property(nonatomic) BOOL compress; + +-(id) init; +@end + +@interface ICEIPEndpointInfo : ICEEndpointInfo +{ +@private + NSString* host; + ICEInt port; +} + +@property(nonatomic, retain) NSString* host; +@property(nonatomic) ICEInt port; +@end + + +@interface ICETCPEndpointInfo : ICEIPEndpointInfo +@end + +@interface ICEUDPEndpointInfo : ICEIPEndpointInfo +{ +@private + NSString* mcastInterface; + ICEInt mcastTtl; +} +@property(nonatomic, retain) NSString* mcastInterface; +@property(nonatomic) ICEInt mcastTtl; +@end + +@interface ICEOpaqueEndpointInfo : ICEEndpointInfo +{ +@private + ICEEncodingVersion* rawEncoding; + NSData* rawBytes; +} +@property(nonatomic, retain) ICEEncodingVersion* rawEncoding; +@property(nonatomic, retain) NSData* rawBytes; +@end + +@interface ICESSLEndpointInfo : ICEIPEndpointInfo +@end + +@protocol ICEEndpoint <NSObject> +-(ICEEndpointInfo*) getInfo; +-(NSString*) toString; +@end + +typedef NSArray ICEEndpointSeq; +typedef NSMutableArray ICEMutableEndpointSeq; diff --git a/objc/include/objc/Ice/Exception.h b/objc/include/objc/Ice/Exception.h new file mode 100644 index 00000000000..7d0754b533f --- /dev/null +++ b/objc/include/objc/Ice/Exception.h @@ -0,0 +1,46 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +#import <Foundation/NSException.h> + +// +// Forward declarations +// +@protocol ICEOutputStream; +@protocol ICEInputStream; + +@class NSCoder; + +@interface ICEException : NSException +-(NSString*)ice_name; +@end + +@interface ICELocalException : ICEException +{ +@protected + const char* file; + int line; +} + +@property(nonatomic, readonly) NSString* file; +@property(nonatomic, readonly) int line; + +-(id)init:(const char*)file line:(int)line; ++(id)localException:(const char*)file line:(int)line; +@end + +@interface ICEUserException : ICEException +-(BOOL)usesClasses__; +-(void)write__:(id<ICEOutputStream>)stream; +-(void) writeImpl__:(id<ICEOutputStream>)os; +-(void)read__:(id<ICEInputStream>)stream; +-(void) readImpl__:(id<ICEInputStream>)is; +@end diff --git a/objc/include/objc/Ice/Format.h b/objc/include/objc/Ice/Format.h new file mode 100644 index 00000000000..e6935d5c68e --- /dev/null +++ b/objc/include/objc/Ice/Format.h @@ -0,0 +1,15 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +typedef enum +{ + ICEDefaultFormat, + ICECompactFormat, + ICESlicedFormat +} ICEFormatType;
\ No newline at end of file diff --git a/objc/include/objc/Ice/Ice.h b/objc/include/objc/Ice/Ice.h new file mode 100644 index 00000000000..4cf5a9f8bd8 --- /dev/null +++ b/objc/include/objc/Ice/Ice.h @@ -0,0 +1,30 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Communicator.h> +#import <objc/Ice/Connection.h> +#import <objc/Ice/Current.h> +#import <objc/Ice/DispatchInterceptor.h> +#import <objc/Ice/Exception.h> +#import <objc/Ice/Identity.h> +#import <objc/Ice/Initialize.h> +#import <objc/Ice/LocalException.h> +#import <objc/Ice/Locator.h> +#import <objc/Ice/Logger.h> +#import <objc/Ice/Object.h> +#import <objc/Ice/ObjectAdapter.h> +#import <objc/Ice/Properties.h> +#import <objc/Ice/Proxy.h> +#import <objc/Ice/Router.h> +#import <objc/Ice/Stream.h> +#import <objc/Ice/ObjectFactory.h> +#import <objc/Ice/SlicedData.h> +#import <objc/Ice/Version.h> +#import <objc/Ice/ImplicitContext.h> +#import <objc/Ice/Metrics.h> diff --git a/objc/include/objc/Ice/ImplicitContext.h b/objc/include/objc/Ice/ImplicitContext.h new file mode 100644 index 00000000000..df32f3da99e --- /dev/null +++ b/objc/include/objc/Ice/ImplicitContext.h @@ -0,0 +1,20 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> +#import <objc/Ice/Current.h> + +@protocol ICEImplicitContext<NSObject> +-(ICEMutableContext*) getContext; +-(void) setContext:(ICEContext*)context; +-(BOOL) containsKey:(NSString*)key; +-(NSString*) get:(NSString*)key; +-(NSString*) put:(NSString*)key value:(NSString*)value; +-(NSString*) remove:(NSString*)key; +@end diff --git a/objc/include/objc/Ice/Initialize.h b/objc/include/objc/Ice/Initialize.h new file mode 100644 index 00000000000..845a8b1baad --- /dev/null +++ b/objc/include/objc/Ice/Initialize.h @@ -0,0 +1,80 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +#import <objc/Ice/Communicator.h> +#import <objc/Ice/Properties.h> +#import <objc/Ice/Stream.h> +#import <objc/Ice/Connection.h> +#import <objc/Ice/Version.h> + +// +// Forward declarations. +// +@protocol ICELogger; + +@protocol ICEDispatcherCall <NSObject> +-(void) run; +@end + +@interface ICEInitializationData : NSObject +{ +@private + id<ICEProperties> properties; + id<ICELogger> logger; + void(^dispatcher)(id<ICEDispatcherCall>, id<ICEConnection>); + NSDictionary* prefixTable__; +} +@property(retain, nonatomic) id<ICEProperties> properties; +@property(retain, nonatomic) id<ICELogger> logger; +@property(copy, nonatomic) void(^dispatcher)(id<ICEDispatcherCall>, id<ICEConnection>); +@property(retain, nonatomic) NSDictionary* prefixTable__; + +-(id) init:(id<ICEProperties>)properties logger:(id<ICELogger>)logger + dispatcher:(void(^)(id<ICEDispatcherCall>, id<ICEConnection>))d; ++(id) initializationData; ++(id) initializationData:(id<ICEProperties>)properties logger:(id<ICELogger>)logger + dispatcher:(void(^)(id<ICEDispatcherCall>, id<ICEConnection>))d; +// This class also overrides copyWithZone:, hash, isEqual:, and dealloc. +@end + +extern ICEEncodingVersion* ICEEncoding_1_0; +extern ICEEncodingVersion* ICEEncoding_1_1; +extern ICEEncodingVersion* ICECurrentEncoding; + +extern ICEProtocolVersion* ICEProtocol_1_0; +extern ICEProtocolVersion* ICECurrentProtocol; +extern ICEEncodingVersion* ICECurrentProtocolEncoding; + +@interface ICEUtil : NSObject ++(id<ICEProperties>) createProperties; ++(id<ICEProperties>) createProperties:(int*)argc argv:(char*[])argv; ++(id<ICECommunicator>) createCommunicator; ++(id<ICECommunicator>) createCommunicator:(ICEInitializationData *)initData; ++(id<ICECommunicator>) createCommunicator:(int*)argc argv:(char*[])argv; ++(id<ICECommunicator>) createCommunicator:(int*)argc argv:(char*[])argv initData:(ICEInitializationData *)initData; ++(id<ICEInputStream>) createInputStream:(id<ICECommunicator>)communicator data:(NSData*)data; ++(id<ICEInputStream>) createInputStream:(id<ICECommunicator>)c data:(NSData*)data encoding:(ICEEncodingVersion*)e; ++(id<ICEInputStream>) wrapInputStream:(id<ICECommunicator>)communicator data:(NSData*)data; ++(id<ICEInputStream>) wrapInputStream:(id<ICECommunicator>)c data:(NSData*)data encoding:(ICEEncodingVersion*)e; ++(id<ICEOutputStream>) createOutputStream:(id<ICECommunicator>)communicator; ++(id<ICEOutputStream>) createOutputStream:(id<ICECommunicator>)c encoding:(ICEEncodingVersion*)e; ++(NSString*) generateUUID; ++(NSArray*)argsToStringSeq:(int)argc argv:(char*[])argv; ++(void)stringSeqToArgs:(NSArray*)args argc:(int*)argc argv:(char*[])argv; +@end + +@interface ICEEncodingVersion(StringConv) ++(ICEEncodingVersion*) encodingVersionWithString:(NSString*)str; +@end + +@interface ICEProtocolVersion(StringConv) ++(ICEProtocolVersion*) protocolVersionWithString:(NSString*)str; +@end diff --git a/objc/include/objc/Ice/Logger.h b/objc/include/objc/Ice/Logger.h new file mode 100644 index 00000000000..1e9d7431c3f --- /dev/null +++ b/objc/include/objc/Ice/Logger.h @@ -0,0 +1,18 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +@protocol ICELogger <NSObject> +-(void) print:(NSString*)message; +-(void) trace:(NSString*)category message:(NSString*)message; +-(void) warning:(NSString*)message; +-(void) error:(NSString*)message; +-(NSString*) getPrefix; +@end diff --git a/objc/include/objc/Ice/Makefile b/objc/include/objc/Ice/Makefile new file mode 100644 index 00000000000..b1f775aef11 --- /dev/null +++ b/objc/include/objc/Ice/Makefile @@ -0,0 +1,26 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = ../../.. + +include $(top_srcdir)/config/Make.rules + +install:: + @if test ! -d $(DESTDIR)$(install_includedir)/Ice ; \ + then \ + echo "Creating $(DESTDIR)$(install_includedir)/Ice..." ; \ + $(call mkdir,$(DESTDIR)$(install_includedir)/Ice) ; \ + fi + + @for i in *.h ; \ + do \ + echo "Installing $$i" ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(install_includedir)/Ice/$$i ; \ + chmod a+r $(DESTDIR)$(install_includedir)/Ice/$$i ; \ + done diff --git a/objc/include/objc/Ice/Object.h b/objc/include/objc/Ice/Object.h new file mode 100644 index 00000000000..6d2ea5ff31e --- /dev/null +++ b/objc/include/objc/Ice/Object.h @@ -0,0 +1,78 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +#import <objc/Ice/Current.h> + +// +// Forward declarations. +// +@class ICEObject; +@protocol ICEInputStream; +@protocol ICEOutputStream; + +#if defined(__cplusplus) +extern "C" +#endif +int ICEInternalLookupString(NSString * const + arr[], size_t, NSString * __unsafe_unretained); +#if defined(__cplusplus) +extern "C" +#endif +void ICEInternalCheckModeAndSelector(id, ICEOperationMode, SEL, ICECurrent*); + +@interface ICEInternalPrefixTable : NSObject +@end + +@protocol ICERequest <NSObject> +-(ICECurrent*) getCurrent; +@end + +@protocol ICEObject <NSObject> +-(BOOL) ice_isA:(NSString*)typeId current:(ICECurrent*)current; +-(void) ice_ping:(ICECurrent*)current; +-(NSString*) ice_id:(ICECurrent*)current; +-(NSArray*) ice_ids:(ICECurrent*)current; +@end + +@interface ICEObject : NSObject<ICEObject, NSCopying> +{ + void* object__; + id delegate__; +} +-(id)initWithDelegate:(id)delegate; ++(id)objectWithDelegate:(id)delegate; +-(BOOL) ice_isA:(NSString*)typeId; +-(void) ice_ping; +-(NSString*) ice_id; +-(NSArray*) ice_ids; +-(void) ice_preMarshal; +-(void) ice_postUnmarshal; +-(BOOL) ice_dispatch:(id<ICERequest>)request; ++(NSString*) ice_staticId; ++(NSString*const*) staticIds__:(int*)count idIndex:(int*)idx; ++(BOOL) ice_isA___:(id)servant current:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os; ++(BOOL) ice_ping___:(id)servant current:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os; ++(BOOL) ice_id___:(id)servant current:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os; ++(BOOL) ice_ids___:(id)servant current:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os; +-(BOOL) dispatch__:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os; +-(void) write__:(id<ICEOutputStream>)os; +-(void) writeImpl__:(id<ICEOutputStream>)os; +-(void) read__:(id<ICEInputStream>)is; +-(void) readImpl__:(id<ICEInputStream>)is; +-(id)target__; +@end + +@protocol ICEBlobject<ICEObject> +-(BOOL) ice_invoke:(NSData*)inEncaps outEncaps:(NSMutableData**)outEncaps current:(ICECurrent*)current; +@end + +@interface ICEBlobject : ICEObject +@end diff --git a/objc/include/objc/Ice/ObjectAdapter.h b/objc/include/objc/Ice/ObjectAdapter.h new file mode 100644 index 00000000000..30e0735bc68 --- /dev/null +++ b/objc/include/objc/Ice/ObjectAdapter.h @@ -0,0 +1,53 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +#import <objc/Ice/Endpoint.h> + +// +// Forward declarations. +// +@protocol ICEObjectPrx; +@protocol ICELocatorPrx; +@protocol ICECommunicator; +@class ICEIdentity; +@class ICEObject; + +@protocol ICEObjectAdapter <NSObject> +-(NSString*) getName; +-(id<ICECommunicator>) getCommunicator; +-(void) activate; +-(void) hold; +-(void) waitForHold; +-(void) deactivate; +-(void) waitForDeactivate; +-(BOOL) isDeactivated; +-(void) destroy; +-(id<ICEObjectPrx>) add:(ICEObject*)servant identity:(ICEIdentity*)ident; +-(id<ICEObjectPrx>) addFacet:(ICEObject*)servant identity:(ICEIdentity*)ident facet:(NSString*)facet; +-(id<ICEObjectPrx>) addWithUUID:(ICEObject*)servant; +-(id<ICEObjectPrx>) addFacetWithUUID:(ICEObject*)servant facet:(NSString*)facet; +-(void) addDefaultServant:(ICEObject*)servant category:(NSString*)category; +-(ICEObject*) remove:(ICEIdentity*)ident; +-(ICEObject*) removeFacet:(ICEIdentity*)ident facet:(NSString*)facet; +-(NSDictionary*) removeAllFacets:(ICEIdentity*)ident; +-(ICEObject*) find:(ICEIdentity*)ident; +-(ICEObject*) findFacet:(ICEIdentity*)ident facet:(NSString*)facet; +-(NSDictionary*) findAllFacets:(ICEIdentity*)ident; +-(ICEObject*) findByProxy:(id<ICEObjectPrx>)proxy; +-(ICEObject*) findDefaultServant:(NSString*)category; +-(id<ICEObjectPrx>) createProxy:(ICEIdentity*)ident; +-(id<ICEObjectPrx>) createDirectProxy:(ICEIdentity*)ident; +-(id<ICEObjectPrx>) createIndirectProxy:(ICEIdentity*)ident; +-(void) setLocator:(id<ICELocatorPrx>)loc; +-(void) refreshPublishedEndpoints; +-(ICEEndpointSeq*) getEndpoints; +-(ICEEndpointSeq*) getPublishedEndpoints; +@end diff --git a/objc/include/objc/Ice/ObjectFactory.h b/objc/include/objc/Ice/ObjectFactory.h new file mode 100644 index 00000000000..c13b2e667df --- /dev/null +++ b/objc/include/objc/Ice/ObjectFactory.h @@ -0,0 +1,16 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +@protocol ICEObjectFactory <NSObject> +-(ICEObject*) create:(NSString*)sliceId NS_RETURNS_RETAINED; +-(void) destroy; +@end + diff --git a/objc/include/objc/Ice/Properties.h b/objc/include/objc/Ice/Properties.h new file mode 100644 index 00000000000..a8045ce4772 --- /dev/null +++ b/objc/include/objc/Ice/Properties.h @@ -0,0 +1,44 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> +#import <objc/Ice/PropertiesAdmin.h> + +@protocol ICEProperties <NSObject> + +-(NSString*) getProperty:(NSString*)key; +-(NSString*) getPropertyWithDefault:(NSString*)key value:(NSString*)value; +-(ICEInt) getPropertyAsInt:(NSString*)key; +-(ICEInt) getPropertyAsIntWithDefault:(NSString*)key value:(ICEInt)value; +-(NSArray*) getPropertyAsList:(NSString*)key; +-(NSArray*) getPropertyAsListWithDefault:(NSString*)key value:(NSArray*)value; +-(NSDictionary*) getPropertiesForPrefix:(NSString*)prefix; +-(void) setProperty:(NSString*)key value:(NSString*)value; +-(NSArray*) getCommandLineOptions; +-(NSArray*) parseCommandLineOptions:(NSString*)prefix options:(NSArray*)options; +-(NSArray*) parseIceCommandLineOptions:(NSArray*)options; +-(void) load:(NSString*)file; +-(id<ICEProperties>) clone; + +@end + +@protocol ICEPropertiesAdminUpdateCallback <NSObject> +-(void) updated:(ICEMutablePropertyDict*)properties; +@end + +@interface ICEPropertiesAdminUpdateCallback : NSObject +{ + void* cxxObject_; +} +@end + +@protocol ICENativePropertiesAdmin <NSObject> +-(void) addUpdateCallback:(id<ICEPropertiesAdminUpdateCallback>)callback; +-(void) removeUpdateCallback:(id<ICEPropertiesAdminUpdateCallback>)callback; +@end diff --git a/objc/include/objc/Ice/Proxy.h b/objc/include/objc/Ice/Proxy.h new file mode 100644 index 00000000000..58d46c24f1c --- /dev/null +++ b/objc/include/objc/Ice/Proxy.h @@ -0,0 +1,182 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +#import <objc/Ice/Format.h> // For ICEFormatType +#import <objc/Ice/Current.h> // For ICEOperationMode +#import <objc/Ice/Endpoint.h> // For ICEEndpointSelectionType + +#import <Foundation/NSProxy.h> + +// +// Forward declarations. +// +@class ICEObjectPrx; +@class ICEException; +@protocol ICECommunicator; +@protocol ICERouterPrx; +@protocol ICELocatorPrx; +@protocol ICEOutputStream; +@protocol ICEInputStream; + +// +// Marshal/Unmarshall callbacks +// +typedef void (^ICEMarshalCB)(id<ICEOutputStream>); +typedef void (^ICEUnmarshalCB)(id<ICEInputStream>, BOOL); + +@protocol ICEAsyncResult <NSObject> +-(id<ICECommunicator>) getCommunicator; +-(id<ICEConnection>) getConnection; +-(id<ICEObjectPrx>) getProxy; + +-(BOOL) isCompleted; +-(void) waitForCompleted; + +-(BOOL) isSent; +-(void) waitForSent; + +-(void) throwLocalException; + +-(BOOL) sentSynchronously; +-(NSString*) getOperation; +@end + +@protocol ICEObjectPrx <NSObject, NSCopying> + +-(NSComparisonResult) compareIdentity:(id<ICEObjectPrx>)aProxy; +-(NSComparisonResult) compareIdentityAndFacet:(id<ICEObjectPrx>)aProxy; + +-(id<ICECommunicator>) ice_getCommunicator; +-(NSString*) ice_toString; +-(BOOL) ice_isA:(NSString*)typeId; +-(BOOL) ice_isA:(NSString*)typeId context:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId; +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId context:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId response:(void(^)(BOOL))response exception:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId context:(ICEContext*)context response:(void(^)(BOOL))response exception:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId response:(void(^)(BOOL))response exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId context:(ICEContext*)context response:(void(^)(BOOL))response exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(BOOL) end_ice_isA:(id<ICEAsyncResult>)result; +-(void) ice_ping; +-(void) ice_ping:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_ice_ping; +-(id<ICEAsyncResult>) begin_ice_ping:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_ice_ping:(void(^)())response exception:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_ice_ping:(ICEContext*)context response:(void(^)())response exception:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_ice_ping:(void(^)())response exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(id<ICEAsyncResult>) begin_ice_ping:(ICEContext*)context response:(void(^)())response exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(void) end_ice_ping:(id<ICEAsyncResult>)result; +-(NSArray*) ice_ids; +-(NSArray*) ice_ids:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_ice_ids; +-(id<ICEAsyncResult>) begin_ice_ids:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_ice_ids:(void(^)(NSArray*))response exception:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_ice_ids:(ICEContext*)context response:(void(^)(NSArray*))response exception:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_ice_ids:(void(^)(NSArray*))response exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(id<ICEAsyncResult>) begin_ice_ids:(ICEContext*)context response:(void(^)(NSArray*))response exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(NSArray*) end_ice_ids:(id<ICEAsyncResult>)result; +-(NSString*) ice_id; +-(NSString*) ice_id:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_ice_id; +-(id<ICEAsyncResult>) begin_ice_id:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_ice_id:(void(^)(NSString*))response exception:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_ice_id:(ICEContext*)context response:(void(^)(NSString*))response exception:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_ice_id:(void(^)(NSString*))response exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(id<ICEAsyncResult>) begin_ice_id:(ICEContext*)context response:(void(^)(NSString*))response exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(NSString*) end_ice_id:(id<ICEAsyncResult>)result; +-(BOOL) ice_invoke:(NSString*)operation mode:(ICEOperationMode)mode inEncaps:(NSData*)inEncaps outEncaps:(NSMutableData**)outEncaps; +-(BOOL) ice_invoke:(NSString*)operation mode:(ICEOperationMode)mode inEncaps:(NSData*)inEncaps outEncaps:(NSMutableData**)outEncaps context:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation mode:(ICEOperationMode)mode inEncaps:(NSData*)inEncaps; +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation mode:(ICEOperationMode)mode inEncaps:(NSData*)inEncaps context :(ICEContext*)context; +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation mode:(ICEOperationMode)mode inEncaps:(NSData*)inEncaps response:(void(^)(BOOL, NSMutableData*))response exception:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation mode:(ICEOperationMode)mode inEncaps:(NSData*)inEncaps context:(ICEContext*)context response:(void(^)(BOOL, NSMutableData*))response exception:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation mode:(ICEOperationMode)mode inEncaps:(NSData*)inEncaps response:(void(^)(BOOL, NSMutableData*))response exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation mode:(ICEOperationMode)mode inEncaps:(NSData*)inEncaps context:(ICEContext*)context response:(void(^)(BOOL, NSMutableData*))response exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(BOOL) end_ice_invoke:(NSMutableData**)outEncaps result:(id<ICEAsyncResult>)result; +-(ICEIdentity*) ice_getIdentity; +-(id) ice_identity:(ICEIdentity*)identity; +-(ICEMutableContext*) ice_getContext; +-(id) ice_context:(ICEContext*)context; +-(NSString*) ice_getFacet; +-(id) ice_facet:(NSString*)facet; +-(NSString*) ice_getAdapterId; +-(id) ice_adapterId:(NSString*)adapterId; +-(ICEEndpointSeq*) ice_getEndpoints; +-(id) ice_endpoints:(ICEEndpointSeq*)endpoints; +-(ICEInt) ice_getLocatorCacheTimeout; +-(id) ice_locatorCacheTimeout:(ICEInt)timeout; +-(BOOL) ice_isConnectionCached; +-(id) ice_connectionCached:(BOOL)cached; +-(ICEEndpointSelectionType) ice_getEndpointSelection; +-(id) ice_endpointSelection:(ICEEndpointSelectionType)type; +-(BOOL) ice_isSecure; +-(id) ice_secure:(BOOL)secure; +-(ICEEncodingVersion*) ice_getEncodingVersion; +-(id) ice_encodingVersion:(ICEEncodingVersion*)encoding; +-(BOOL) ice_isPreferSecure; +-(id) ice_preferSecure:(BOOL)preferSecure; +-(id<ICERouterPrx>) ice_getRouter; +-(id) ice_router:(id<ICERouterPrx>)router; +-(id<ICELocatorPrx>) ice_getLocator; +-(id) ice_locator:(id<ICELocatorPrx>)locator; +//-(BOOL) ice_isCollocationOptimized; +//-(id) ice_collocationOptimized:(BOOL)collocOptimized; +-(id) ice_twoway; +-(BOOL) ice_isTwoway; +-(id) ice_oneway; +-(BOOL) ice_isOneway; +-(id) ice_batchOneway; +-(BOOL) ice_isBatchOneway; +-(id) ice_datagram; +-(BOOL) ice_isDatagram; +-(id) ice_batchDatagram; +-(BOOL) ice_isBatchDatagram; +-(id) ice_compress:(BOOL)compress; +-(id) ice_timeout:(int)timeout; +-(id) ice_connectionId:(NSString*)connectionId; +-(id<ICEConnection>) ice_getConnection; +-(id<ICEConnection>) ice_getCachedConnection; +-(void) ice_flushBatchRequests; +-(id<ICEAsyncResult>) begin_ice_flushBatchRequests; +-(id<ICEAsyncResult>) begin_ice_flushBatchRequests:(void(^)(ICEException*))exception; +-(id<ICEAsyncResult>) begin_ice_flushBatchRequests:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent; +-(void) end_ice_flushBatchRequests:(id<ICEAsyncResult>)result; +@end + +@interface ICEObjectPrx : NSObject<ICEObjectPrx> +{ + void* objectPrx__; + id<ICECommunicator> communicator__; +} ++(id) uncheckedCast:(id<ICEObjectPrx>)proxy; ++(id) uncheckedCast:(id<ICEObjectPrx>)proxy facet:(NSString*)facet; ++(id) checkedCast:(id<ICEObjectPrx>)proxy; ++(id) checkedCast:(id<ICEObjectPrx>)proxy facet:(NSString*)facet; ++(id) checkedCast:(id<ICEObjectPrx>)proxy context:(ICEContext*)context; ++(id) checkedCast:(id<ICEObjectPrx>)proxy facet:(NSString*)facet context:(ICEContext*)context; ++(NSString*) ice_staticId; + ++(Protocol*) protocol__; +-(id<ICEOutputStream>) createOutputStream__; +-(void) invoke__:(NSString*)operation mode:(ICEOperationMode)mode format:(ICEFormatType)format marshal:(ICEMarshalCB)marshal + unmarshal:(ICEUnmarshalCB)unmarshal context:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_invoke__:(NSString*)operation mode:(ICEOperationMode)mode format:(ICEFormatType)format marshal:(ICEMarshalCB)marshal + returnsData:(BOOL)returnsData context:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_invoke__:(NSString*)operation mode:(ICEOperationMode)mode format:(ICEFormatType)format marshal:(ICEMarshalCB)marshal + response:(void(^)())response + exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent + context:(ICEContext*)context; +-(id<ICEAsyncResult>) begin_invoke__:(NSString*)operation mode:(ICEOperationMode)mode format:(ICEFormatType)format marshal:(ICEMarshalCB)marshal + completed:(void(^)(id<ICEInputStream>, BOOL))completed + response:(BOOL)response exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent + context:(ICEContext*)context; +-(void)end_invoke__:(NSString*)operation unmarshal:(ICEUnmarshalCB)unmarshal result:(id<ICEAsyncResult>)result; +@end diff --git a/objc/include/objc/Ice/SlicedData.h b/objc/include/objc/Ice/SlicedData.h new file mode 100644 index 00000000000..1c4c1df1a42 --- /dev/null +++ b/objc/include/objc/Ice/SlicedData.h @@ -0,0 +1,25 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in +// the ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +#import <objc/Ice/Object.h> + +@protocol ICESlicedData<NSObject> +@end + +@interface ICEUnknownSlicedObject : ICEObject +{ +@private + NSString* unknownTypeId_; + id<ICESlicedData> slicedData_; +} +-(NSString*) getUnknownTypeId; +-(id<ICESlicedData>) getSlicedData; +@end diff --git a/objc/include/objc/Ice/Stream.h b/objc/include/objc/Ice/Stream.h new file mode 100644 index 00000000000..74b0a0b57c5 --- /dev/null +++ b/objc/include/objc/Ice/Stream.h @@ -0,0 +1,369 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> +#import <objc/Ice/Format.h> // for ICEFormatType + +#import <Foundation/NSData.h> + +// +// Forward declarations +// +@class ICEObject; +@protocol ICEObjectPrx; +@protocol ICECommunicator; +@protocol ICESlicedData; +@class ICEUserException; +@class ICEEncodingVersion; + +typedef enum +{ + ICEOptionalFormatF1 = 0, + ICEOptionalFormatF2 = 1, + ICEOptionalFormatF4 = 2, + ICEOptionalFormatF8 = 3, + ICEOptionalFormatSize = 4, + ICEOptionalFormatVSize = 5, + ICEOptionalFormatFSize = 6, + ICEOptionalFormatClass = 7 +} ICEOptionalFormat; + +@protocol ICEReadObjectCallback <NSObject> +-(void)invoke:(ICEObject*)obj; +@end + +// +// ICENone singleton to specify not set optionals. +// +extern id ICENone; + +typedef struct +{ + Class key; + Class value; +} ICEKeyValueTypeHelper; + +@protocol ICEInputStream <NSObject> + +-(id<ICECommunicator>) communicator; + +-(void) sliceObjects:(BOOL)b; + +-(BOOL) readBool; +-(NSMutableData*) newBoolSeq; +-(NSMutableData*) readBoolSeq; + +-(ICEByte) readByte; +-(NSMutableData*) newByteSeq; +-(NSMutableData*) readByteSeq; +-(NSData*) readByteSeqNoCopy; + +-(ICEShort) readShort; +-(NSMutableData*) newShortSeq; +-(NSMutableData*) readShortSeq; + +-(ICEInt) readInt; +-(NSMutableData*) newIntSeq; +-(NSMutableData*) readIntSeq; + +-(ICELong) readLong; +-(NSMutableData*) newLongSeq; +-(NSMutableData*) readLongSeq; + +-(ICEFloat) readFloat; +-(NSMutableData*) newFloatSeq; +-(NSMutableData*) readFloatSeq; + +-(ICEDouble) readDouble; +-(NSMutableData*) newDoubleSeq; +-(NSMutableData*) readDoubleSeq; + +-(NSMutableString*) newString; +-(NSMutableString*) readString; +-(NSMutableArray*) newStringSeq; +-(NSMutableArray*) readStringSeq; + +-(ICEInt) readEnumerator:(ICEInt)min max:(ICEInt)max; +-(NSMutableData*) newEnumSeq:(ICEInt)min max:(ICEInt)max; +-(NSMutableData*) readEnumSeq:(ICEInt)min max:(ICEInt)max; + +-(id<ICEObjectPrx>) newProxy:(Class)c; +-(id<ICEObjectPrx>) readProxy:(Class)c; + +-(void) newObject:(ICEObject*ICE_STRONG_QUALIFIER*)object; +-(void) newObject:(ICEObject*ICE_STRONG_QUALIFIER*)object expectedType:(Class)type; +-(void) readObject:(ICEObject**)object; +-(void) readObject:(ICEObject**)object expectedType:(Class)type; +-(NSMutableArray*) newObjectSeq:(Class)expectedType; +-(NSMutableArray*) readObjectSeq:(Class)expectedType; +-(NSMutableDictionary*) newObjectDict:(Class)keyType expectedType:(Class)type; +-(NSMutableDictionary*) readObjectDict:(Class)keyType expectedType:(Class)type; + +-(NSMutableArray*) newSequence:(Class)type; +-(NSMutableArray*) readSequence:(Class)type; +-(NSMutableDictionary*) newDictionary:(ICEKeyValueTypeHelper)type; +-(NSMutableDictionary*) readDictionary:(ICEKeyValueTypeHelper)type; + +-(BOOL) readOptional:(ICEInt)tag format:(ICEOptionalFormat)format; + +-(ICEInt) readSize; +-(ICEInt) readAndCheckSeqSize:(ICEInt)minSize; + +-(void) throwException; + +-(void) startObject; +-(id<ICESlicedData>) endObject:(BOOL)preserve NS_RETURNS_RETAINED; + +-(void) startException; +-(id<ICESlicedData>) endException:(BOOL)preserve NS_RETURNS_RETAINED; + +-(void) startSlice; +-(void) endSlice; +-(void) skipSlice; + +-(ICEEncodingVersion*) startEncapsulation; +-(void) endEncapsulation; +-(ICEEncodingVersion*) skipEncapsulation; + +-(ICEEncodingVersion*) getEncoding; + +-(void) readPendingObjects; + +-(void) rewind; + +-(void) skip:(ICEInt)sz; +-(void) skipSize; +@end + +@protocol ICEOutputStream <NSObject> + +-(id<ICECommunicator>) communicator; + +-(void) writeBool:(BOOL)v; +-(void) writeBoolSeq:(NSData*)v; + +-(void) writeByte:(ICEByte)v; +-(void) writeByteSeq:(NSData*)v; + +-(void) writeShort:(ICEShort)v; +-(void) writeShortSeq:(NSData*)v; + +-(void) writeInt:(ICEInt)v; +-(void) writeIntSeq:(NSData*)v; + +-(void) writeLong:(ICELong)v; +-(void) writeLongSeq:(NSData*)v; + +-(void) writeFloat:(ICEFloat)v; +-(void) writeFloatSeq:(NSData*)v; + +-(void) writeDouble:(ICEDouble)v; +-(void) writeDoubleSeq:(NSData*)v; + +-(void) writeString:(NSString*)v; +-(void) writeStringSeq:(NSArray*)v; + +-(void) writeEnumerator:(ICEInt)v min:(ICEInt)min max:(ICEInt)max; +-(void) writeEnumSeq:(NSData*)v min:(ICEInt)min max:(ICEInt)max; + +-(void) writeProxy:(id<ICEObjectPrx>)v; + +-(void) writeObject:(ICEObject*)v; +-(void) writeObjectSeq:(NSArray*)v; +-(void) writeObjectDict:(NSDictionary*)v helper:(Class)helper; + +-(void) writeSequence:(NSArray*)arr helper:(Class)helper; +-(void) writeDictionary:(NSDictionary*)dictionary helper:(ICEKeyValueTypeHelper)helper; + +-(BOOL) writeOptional:(ICEInt)tag format:(ICEOptionalFormat)format; + +-(void) writeSize:(ICEInt)v; + +-(void) writeException:(ICEUserException*)v; + +-(void) startObject:(id<ICESlicedData>)slicedData; +-(void) endObject; + +-(void) startException:(id<ICESlicedData>)slicedData; +-(void) endException; + +-(void) startSlice:(NSString*)typeId compactId:(ICEInt)compactId lastSlice:(BOOL)lastSlice; +-(void) endSlice; + +-(void) startEncapsulation; +-(void) startEncapsulation:(ICEEncodingVersion*)encoding format:(ICEFormatType)format; +-(void) endEncapsulation; + +-(ICEEncodingVersion*) getEncoding; + +-(void) writePendingObjects; + +-(NSMutableData*) finished; +-(NSData*) finishedNoCopy; + +-(void) reset:(BOOL)clearBuffer; +@end + +// +// Helper protocol implemented by helpers for marshaling/un-marshaling +// Slice types. +// +@protocol ICEStreamHelper ++(id) readRetained:(id<ICEInputStream>)stream NS_RETURNS_RETAINED; ++(id) read:(id<ICEInputStream>)stream; ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream; ++(id) readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag; ++(id) readOpt:(id<ICEInputStream>)stream tag:(ICEInt)tag; ++(void) writeOpt:(id)obj stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag; ++(ICEInt) minWireSize; +@end + +@interface ICEStreamHelper : NSObject<ICEStreamHelper> +@end + +// +// Helper classes for streaming Slice types +// +@interface ICEBoolHelper : ICEStreamHelper +@end + +@interface ICEByteHelper : ICEStreamHelper +@end + +@interface ICEShortHelper : ICEStreamHelper +@end + +@interface ICEIntHelper : ICEStreamHelper +@end + +@interface ICELongHelper : ICEStreamHelper +@end + +@interface ICEFloatHelper : ICEStreamHelper +@end + +@interface ICEDoubleHelper : ICEStreamHelper +@end + +@interface ICEStringHelper : ICEStreamHelper +@end + +@interface ICEObjectHelper : ICEStreamHelper ++(void)read:(ICEObject**)v stream:(id<ICEInputStream>)stream; ++(void)readOpt:(id*)v stream:(id<ICEInputStream>)stream tag:(ICEInt)tag; +@end + +@interface ICEProxyHelper : ICEStreamHelper +@end + +@interface ICEEnumHelper : ICEStreamHelper ++(ICEInt) getMinValue; ++(ICEInt) getMaxValue; +@end + +@interface ICEStructHelper : ICEStreamHelper ++(Class) getOptionalHelper; +@end + +@protocol ICESequenceStreamHelper<ICEStreamHelper> ++(Class) getElementHelper; ++(ICEInt) count:(id)obj; +@end + +@interface ICEArraySequenceHelper : ICEStreamHelper<ICESequenceStreamHelper> ++(Class) getOptionalHelper; +@end + +@interface ICEDataSequenceHelper : ICEStreamHelper<ICESequenceStreamHelper> +@end + +@interface ICEBoolSequenceHelper : ICEDataSequenceHelper +@end + +@interface ICEByteSequenceHelper : ICEDataSequenceHelper +@end + +@interface ICEShortSequenceHelper : ICEDataSequenceHelper +@end + +@interface ICEIntSequenceHelper : ICEDataSequenceHelper +@end + +@interface ICELongSequenceHelper : ICEDataSequenceHelper +@end + +@interface ICEFloatSequenceHelper : ICEDataSequenceHelper +@end + +@interface ICEDoubleSequenceHelper : ICEDataSequenceHelper +@end + +@interface ICEEnumSequenceHelper : ICEDataSequenceHelper +@end + +@interface ICEStringSequenceHelper : ICEArraySequenceHelper +@end + +@interface ICEObjectSequenceHelper : ICEArraySequenceHelper +@end + +@interface ICEProxySequenceHelper : ICEArraySequenceHelper +@end + +@protocol ICEDictionaryStreamHelper<ICEStreamHelper> ++(ICEInt) count:(id)obj; +@end + +@interface ICEDictionaryHelper : ICEStreamHelper<ICEDictionaryStreamHelper> ++(Class) getOptionalHelper; +@end + +@interface ICEObjectDictionaryHelper : ICEDictionaryHelper +@end + +// +// Helper for optionals +// +@protocol ICEOptionalStreamHelper ++(id) readRetained:(id<ICEInputStream>)stream helper:(Class)helper NS_RETURNS_RETAINED; ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream helper:(Class)helper; ++(ICEOptionalFormat) optionalFormat; +@end + +@interface ICEFixedLengthOptionalHelper : NSObject<ICEOptionalStreamHelper> +@end + +@interface ICEVarLengthOptionalHelper : NSObject<ICEOptionalStreamHelper> +@end + +@interface ICEFixedSequenceOptionalHelper : NSObject<ICEOptionalStreamHelper> +@end + +@interface ICEFixedSize1SequenceOptionalHelper : NSObject<ICEOptionalStreamHelper> +@end + +@interface ICEFixedDictionaryOptionalHelper : NSObject<ICEOptionalStreamHelper> +@end + +@interface CompactIdMapHelper : NSObject ++(void) initialize; ++(void) registerClass:(NSString*)type value:(ICEInt)value; +@end + +@interface ICEOptionalGetter : NSObject ++(BOOL) get:(id)value value:(id ICE_STRONG_QUALIFIER*)v type:(Class)cl; ++(BOOL) getRetained:(id)value value:(id ICE_STRONG_QUALIFIER*)v type:(Class)cl; ++(BOOL) getByte:(id)value value:(ICEByte*)v; ++(BOOL) getBool:(id)value value:(BOOL*)v; ++(BOOL) getShort:(id)value value:(ICEShort*)v; ++(BOOL) getInt:(id)value value:(ICEInt*)v; ++(BOOL) getLong:(id)value value:(ICELong*)v; ++(BOOL) getFloat:(id)value value:(ICEFloat*)v; ++(BOOL) getDouble:(id)value value:(ICEDouble*)v; +@end diff --git a/objc/include/objc/IceGrid.h b/objc/include/objc/IceGrid.h new file mode 100644 index 00000000000..d81e101dd03 --- /dev/null +++ b/objc/include/objc/IceGrid.h @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import "IceGrid/IceGrid.h" diff --git a/objc/include/objc/IceGrid/.gitignore b/objc/include/objc/IceGrid/.gitignore new file mode 100644 index 00000000000..41f5d685b02 --- /dev/null +++ b/objc/include/objc/IceGrid/.gitignore @@ -0,0 +1,15 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +Admin.h +Descriptor.h +Discovery.h +Exception.h +FileParser.h +Locator.h +Observer.h +PluginFacade.h +Query.h +Registry.h +Session.h +UserAccountMapper.h diff --git a/objc/include/objc/IceGrid/IceGrid.h b/objc/include/objc/IceGrid/IceGrid.h new file mode 100644 index 00000000000..32c734a5d44 --- /dev/null +++ b/objc/include/objc/IceGrid/IceGrid.h @@ -0,0 +1,19 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/IceGrid/Admin.h> +#import <objc/IceGrid/Exception.h> +#import <objc/IceGrid/Observer.h> +#import <objc/IceGrid/Registry.h> +#import <objc/IceGrid/UserAccountMapper.h> +#import <objc/IceGrid/Descriptor.h> +#import <objc/IceGrid/FileParser.h> +#import <objc/IceGrid/Locator.h> +#import <objc/IceGrid/Query.h> +#import <objc/IceGrid/Session.h> diff --git a/objc/include/objc/IceGrid/Makefile b/objc/include/objc/IceGrid/Makefile new file mode 100644 index 00000000000..d0305fd73ae --- /dev/null +++ b/objc/include/objc/IceGrid/Makefile @@ -0,0 +1,26 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = ../../.. + +include $(top_srcdir)/config/Make.rules + +install:: + @if test ! -d $(DESTDIR)$(install_includedir)/IceGrid ; \ + then \ + echo "Creating $(DESTDIR)$(install_includedir)/IceGrid..." ; \ + $(call mkdir,$(DESTDIR)$(install_includedir)/IceGrid) ; \ + fi + + @for i in *.h ; \ + do \ + echo "Installing $$i" ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(install_includedir)/IceGrid/$$i ; \ + chmod a+r $(DESTDIR)$(install_includedir)/IceGrid/$$i ; \ + done diff --git a/objc/include/objc/IceStorm.h b/objc/include/objc/IceStorm.h new file mode 100644 index 00000000000..7089fb8c50b --- /dev/null +++ b/objc/include/objc/IceStorm.h @@ -0,0 +1,10 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import "IceStorm/IceStorm.h" diff --git a/objc/include/objc/IceStorm/.gitignore b/objc/include/objc/IceStorm/.gitignore new file mode 100644 index 00000000000..bb5bf8a8dc7 --- /dev/null +++ b/objc/include/objc/IceStorm/.gitignore @@ -0,0 +1,5 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +Metrics.h +IceStorm.h diff --git a/objc/include/objc/IceStorm/Makefile b/objc/include/objc/IceStorm/Makefile new file mode 100644 index 00000000000..97b7e1bdd1d --- /dev/null +++ b/objc/include/objc/IceStorm/Makefile @@ -0,0 +1,26 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = ../../.. + +include $(top_srcdir)/config/Make.rules + +install:: + @if test ! -d $(DESTDIR)$(install_includedir)/IceStorm ; \ + then \ + echo "Creating $(DESTDIR)$(install_includedir)/IceStorm..." ; \ + $(call mkdir,$(DESTDIR)$(install_includedir)/IceStorm) ; \ + fi + + @for i in *.h ; \ + do \ + echo "Installing $$i" ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(install_includedir)/IceStorm/$$i ; \ + chmod a+r $(DESTDIR)$(install_includedir)/IceStorm/$$i ; \ + done diff --git a/objc/include/objc/Makefile b/objc/include/objc/Makefile new file mode 100644 index 00000000000..1776a2985eb --- /dev/null +++ b/objc/include/objc/Makefile @@ -0,0 +1,21 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = ../.. + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = Ice Glacier2 IceStorm IceGrid + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done diff --git a/objc/lib/.gitignore b/objc/lib/.gitignore new file mode 100644 index 00000000000..39af5887579 --- /dev/null +++ b/objc/lib/.gitignore @@ -0,0 +1 @@ +# Dummy file, so that git retains this otherwise empty directory. diff --git a/objc/src/Glacier2/.gitignore b/objc/src/Glacier2/.gitignore new file mode 100644 index 00000000000..ece727d3b20 --- /dev/null +++ b/objc/src/Glacier2/.gitignore @@ -0,0 +1,18 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +.depend +Metrics.m +PermissionsVerifierF.m +PermissionsVerifier.m +Router.m +RouterF.m +Session.m +SSLInfo.m +Metrics.h +PermissionsVerifierF.h +PermissionsVerifier.h +Router.h +RouterF.h +Session.h +SSLInfo.h diff --git a/objc/src/Glacier2/Makefile b/objc/src/Glacier2/Makefile new file mode 100644 index 00000000000..50f5d7cf7c0 --- /dev/null +++ b/objc/src/Glacier2/Makefile @@ -0,0 +1,50 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = ../.. + +LIBFILENAME = $(call mklibfilename,Glacier2ObjC,$(VERSION)) +SONAME = $(call mksoname,Glacier2ObjC,$(SOVERSION)) +LIBNAME = $(call mklibname,Glacier2ObjC) + +TARGETS = $(call mklibtargets,$(libdir)/$(LIBFILENAME),$(libdir)/$(SONAME),$(libdir)/$(LIBNAME)) + +SLICE_OBJS = Metrics.o \ + PermissionsVerifierF.o \ + PermissionsVerifier.o \ + Router.o \ + RouterF.o \ + Session.o \ + SSLInfo.o + +OBJS = $(SLICE_OBJS) + +HDIR = $(headerdir)/objc/Glacier2 +SDIR = $(slicedir)/Glacier2 + +include $(top_srcdir)/config/Make.rules + +SLICE2OBJCFLAGS := --ice --include-dir objc/Glacier2 $(SLICE2OBJCFLAGS) + +$(libdir)/$(LIBFILENAME): $(OBJS) $(HDIR)/PermissionsVerifierF.h $(HDIR)/RouterF.h + @mkdir -p $(dir $@) + rm -f $@ + $(call mkshlib,$@,$(SONAME),$(OBJS),$(LIBS)) + +$(libdir)/$(SONAME): $(libdir)/$(LIBFILENAME) + rm -f $@ + ln -s $(LIBFILENAME) $@ + +$(libdir)/$(LIBNAME): $(libdir)/$(SONAME) + @mkdir -p $(libdir) + rm -f $@ + ln -s $(SONAME) $@ + +install:: all + $(call installlib,$(DESTDIR)$(install_libdir),$(libdir),$(LIBFILENAME),$(SONAME),$(LIBNAME)) diff --git a/objc/src/Ice/.gitignore b/objc/src/Ice/.gitignore new file mode 100644 index 00000000000..704e8c6c2b0 --- /dev/null +++ b/objc/src/Ice/.gitignore @@ -0,0 +1,33 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +.depend +BuiltinSequences.m +Identity.m +Locator.m +LocatorF.m +LocalException.m +Metrics.m +Process.m +ProcessF.m +PropertiesAdmin.m +RemoteLogger.m +Router.m +RouterF.m +SliceChecksumDict.m +Version.m +BuiltinSequences.h +Identity.h +Locator.h +LocatorF.h +LocalException.h +Metrics.h +Process.h +ProcessF.h +PropertiesAdmin.h +RemoteLogger.h +Router.h +RouterF.h +SliceChecksumDict.h +Version.h +include/** diff --git a/objc/src/Ice/Communicator.mm b/objc/src/Ice/Communicator.mm new file mode 100644 index 00000000000..7557af3ba27 --- /dev/null +++ b/objc/src/Ice/Communicator.mm @@ -0,0 +1,608 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <CommunicatorI.h> +#import <PropertiesI.h> +#import <ProxyI.h> +#import <IdentityI.h> +#import <LoggerI.h> +#import <ObjectAdapterI.h> +#import <Util.h> +#import <StreamI.h> +#import <SlicedDataI.h> +#import <ImplicitContextI.h> +#import <ProxyI.h> + +#include <IceCpp/Router.h> +#include <IceCpp/Locator.h> +#include <IceCpp/ObjectFactory.h> + +#import <objc/Ice/Router.h> +#import <objc/Ice/Locator.h> +#import <objc/Ice/ObjectFactory.h> + +#import <objc/runtime.h> + +#define COMMUNICATOR dynamic_cast<Ice::Communicator*>(static_cast<IceUtil::Shared*>(cxxObject_)) + +namespace IceObjC +{ + +class UnknownSlicedObjectFactoryI : public Ice::ObjectFactory +{ +public: + + virtual Ice::ObjectPtr + create(const std::string&) + { + ICEUnknownSlicedObject* obj = [[ICEUnknownSlicedObject alloc] init]; + Ice::ObjectPtr o = [ICEInputStream createObjectReader:obj]; + [obj release]; + return o; + } + + virtual void + destroy() + { + } +}; + +class ObjectFactoryI : public Ice::ObjectFactory +{ +public: + + // We must explicitely CFRetain/CFRelease so that the garbage + // collector does not trash the dictionaries. + ObjectFactoryI(NSDictionary* factories, NSDictionary* prefixTable) : + _factories(factories), _prefixTable(prefixTable) + { + CFRetain(_factories); + CFRetain(_prefixTable); + } + + ~ObjectFactoryI() + { + CFRelease(_factories); + CFRelease(_prefixTable); + } + + virtual Ice::ObjectPtr + create(const std::string& type) + { + NSString* sliceId = [[NSString alloc] initWithUTF8String:type.c_str()]; + @try + { + id<ICEObjectFactory> factory = nil; + @synchronized(_factories) + { + factory = [_factories objectForKey:sliceId]; + if(factory == nil) + { + factory = [_factories objectForKey:@""]; + } + } + + ICEObject* obj = nil; + if(factory != nil) + { + obj = [factory create:sliceId]; + } + + if(obj == nil) + { + std::string tId = toObjCSliceId(type, _prefixTable); + Class c = objc_lookUpClass(tId.c_str()); + if(c == nil) + { + return 0; // No object factory. + } + if([c isSubclassOfClass:[ICEObject class]]) + { + obj = (ICEObject*)[[c alloc] init]; + } + } + + Ice::ObjectPtr o; + if(obj != nil) + { + o = [ICEInputStream createObjectReader:obj]; + [obj release]; + } + return o; + } + @catch(id ex) + { + rethrowCxxException(ex); + } + @finally + { + [sliceId release]; + } + return nil; // Keep the compiler happy. + } + + virtual void + destroy() + { + for(NSString* k in _factories) + { + [[_factories objectForKey:k] destroy]; + } + } + +private: + + NSDictionary* _factories; + NSDictionary* _prefixTable; +}; + +} + +@interface ICEInternalPrefixTable(ICEInternal) ++(NSDictionary*) newPrefixTable; +@end + +@implementation ICEInternalPrefixTable(ICEInternal) ++(NSDictionary*) newPrefixTable +{ + NSMutableDictionary* prefixTable = [[NSMutableDictionary alloc] init]; + ICEInternalPrefixTable* table = [[ICEInternalPrefixTable alloc] init]; + unsigned int count; + Method* methods = class_copyMethodList([ICEInternalPrefixTable class], &count); + for(unsigned int i = 0; i < count; ++i) + { + SEL selector = method_getName(methods[i]); + const char* methodName = sel_getName(selector); + if(strncmp(methodName, "addPrefixes_C", 13) == 0) + { + [table performSelector:selector withObject:prefixTable]; + } + } + free(methods); + [table release]; + return prefixTable; +} +@end + +@implementation ICECommunicator +-(void)setup:(NSDictionary*)prefixTable +{ + objectFactories_ = [[NSMutableDictionary alloc] init]; + if(prefixTable) + { + prefixTable_ = [prefixTable retain]; + } + else + { + prefixTable_ = [ICEInternalPrefixTable newPrefixTable]; + } + COMMUNICATOR->addObjectFactory(new IceObjC::UnknownSlicedObjectFactoryI, "::Ice::Object"); + COMMUNICATOR->addObjectFactory(new IceObjC::ObjectFactoryI(objectFactories_, prefixTable_), ""); +} +-(void) dealloc +{ + [prefixTable_ release]; + [objectFactories_ release]; + [super dealloc]; +} +-(Ice::Communicator*) communicator +{ + return COMMUNICATOR; +} +-(NSDictionary*) getPrefixTable +{ + return prefixTable_; +} + +// +// Methods from @protocol ICECommunicator +// + +-(void) destroy +{ + NSException* nsex = nil; + try + { + COMMUNICATOR->destroy(); + return; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) shutdown +{ + NSException* nsex = nil; + try + { + COMMUNICATOR->shutdown(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) waitForShutdown +{ + NSException* nsex = nil; + try + { + COMMUNICATOR->waitForShutdown(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(BOOL) isShutdown +{ + NSException* nsex = nil; + try + { + return COMMUNICATOR->isShutdown(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return NO; // Keep the compiler happy. +} + +-(id<ICEObjectPrx>) stringToProxy:(NSString*)str +{ + NSException* nsex = nil; + try + { + return [ICEObjectPrx objectPrxWithObjectPrx__:COMMUNICATOR->stringToProxy(fromNSString(str))]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(NSString*)proxyToString:(id<ICEObjectPrx>)obj +{ + NSException* nsex = nil; + try + { + return [toNSString(COMMUNICATOR->proxyToString([(ICEObjectPrx*)obj objectPrx__])) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICEObjectPrx>)propertyToProxy:(NSString*)property +{ + NSException* nsex = nil; + try + { + return [ICEObjectPrx objectPrxWithObjectPrx__:COMMUNICATOR->propertyToProxy(fromNSString(property))]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(NSMutableDictionary*)proxyToProperty:(id<ICEObjectPrx>)prx property:(NSString*)property +{ + NSException* nsex = nil; + try + { + return [toNSDictionary(COMMUNICATOR->proxyToProperty([(ICEObjectPrx*)prx objectPrx__], + fromNSString(property))) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICEIdentity*) stringToIdentity:(NSString*)str +{ + NSException* nsex = nil; + try + { + return [ICEIdentity identityWithIdentity:COMMUNICATOR->stringToIdentity(fromNSString(str))]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(NSString*) identityToString:(ICEIdentity*)ident +{ + NSException* nsex = nil; + try + { + return [toNSString(COMMUNICATOR->identityToString([ident identity])) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICEObjectAdapter>) createObjectAdapter:(NSString*)name; +{ + NSException* nsex = nil; + try + { + ICEObjectAdapter* adapter = [ICEObjectAdapter wrapperWithCxxObject: + COMMUNICATOR->createObjectAdapter( + fromNSString(name)).get()]; + return adapter; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICEObjectAdapter>) createObjectAdapterWithEndpoints:(NSString*)name endpoints:(NSString*)endpoints; +{ + NSException* nsex = nil; + try + { + ICEObjectAdapter* adapter = [ICEObjectAdapter wrapperWithCxxObject: + COMMUNICATOR->createObjectAdapterWithEndpoints( + fromNSString(name), fromNSString(endpoints)).get()]; + return adapter; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICEObjectAdapter>) createObjectAdapterWithRouter:(NSString*)name router:(id<ICERouterPrx>)rtr +{ + NSException* nsex = nil; + try + { + Ice::RouterPrx router = Ice::RouterPrx::uncheckedCast(Ice::ObjectPrx([(ICEObjectPrx*)rtr objectPrx__])); + ICEObjectAdapter* adapter = [ICEObjectAdapter wrapperWithCxxObject: + COMMUNICATOR->createObjectAdapterWithRouter( + fromNSString(name), router).get()]; + return adapter; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(void) addObjectFactory:(id<ICEObjectFactory>)factory sliceId:(NSString*)sliceId +{ + @synchronized(objectFactories_) + { + [objectFactories_ setObject:factory forKey:sliceId]; + } +} +-(id<ICEObjectFactory>) findObjectFactory:(NSString*)sliceId +{ + @synchronized(objectFactories_) + { + return [objectFactories_ objectForKey:sliceId]; + } + return nil; // Keep the compiler happy. +} + +-(id<ICEImplicitContext>) getImplicitContext +{ + return [ICEImplicitContext implicitContextWithImplicitContext:COMMUNICATOR->getImplicitContext().get()]; +} + +-(id<ICEProperties>) getProperties +{ + NSException* nsex = nil; + try + { + return [ICEProperties wrapperWithCxxObject:COMMUNICATOR->getProperties().get()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICELogger>) getLogger +{ + NSException* nsex = nil; + try + { + return [ICELogger wrapperWithCxxObject:COMMUNICATOR->getLogger().get()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICERouterPrx>) getDefaultRouter +{ + NSException* nsex = nil; + try + { + return (id<ICERouterPrx>)[ICERouterPrx objectPrxWithObjectPrx__:COMMUNICATOR->getDefaultRouter()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(void) setDefaultRouter:(id<ICERouterPrx>)rtr +{ + NSException* nsex = nil; + try + { + COMMUNICATOR->setDefaultRouter(Ice::RouterPrx::uncheckedCast(Ice::ObjectPrx([(ICEObjectPrx*)rtr objectPrx__]))); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(id<ICELocatorPrx>) getDefaultLocator +{ + NSException* nsex = nil; + try + { + return (id<ICELocatorPrx>)[ICELocatorPrx objectPrxWithObjectPrx__:COMMUNICATOR->getDefaultLocator()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(void) setDefaultLocator:(id<ICELocatorPrx>)loc +{ + NSException* nsex = nil; + try + { + COMMUNICATOR->setDefaultLocator(Ice::LocatorPrx::uncheckedCast( + Ice::ObjectPrx([(ICEObjectPrx*)loc objectPrx__]))); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) flushBatchRequests +{ + NSException* nsex = nil; + try + { + COMMUNICATOR->flushBatchRequests(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} +-(id<ICEAsyncResult>) begin_flushBatchRequests +{ + return beginCppCall(^(Ice::AsyncResultPtr& result) + { + result = COMMUNICATOR->begin_flushBatchRequests(); + }); +} +-(id<ICEAsyncResult>) begin_flushBatchRequests:(void(^)(ICEException*))exception +{ + return [self begin_flushBatchRequests:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_flushBatchRequests:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) + { + result = COMMUNICATOR->begin_flushBatchRequests(cb); + }, + ^(const Ice::AsyncResultPtr& result) { + COMMUNICATOR->end_flushBatchRequests(result); + }, + exception, sent); +} +-(void) end_flushBatchRequests:(id<ICEAsyncResult>)result +{ + endCppCall(^(const Ice::AsyncResultPtr& r) + { + COMMUNICATOR->end_flushBatchRequests(r); + }, result); +} + +-(id<ICEObjectPrx>) getAdmin +{ + NSException* nsex = nil; + try + { + return [ICEObjectPrx objectPrxWithObjectPrx__:COMMUNICATOR->getAdmin()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id) findAdminFacet:(NSString*)facet +{ + if([facet isEqualToString:@"Properties"]) + { + Ice::ObjectPtr obj = COMMUNICATOR->findAdminFacet(fromNSString(facet)); + return [ICENativePropertiesAdmin wrapperWithCxxObject:Ice::NativePropertiesAdminPtr::dynamicCast(obj).get()]; + } + else + { + return nil; + } +} +@end diff --git a/objc/src/Ice/CommunicatorI.h b/objc/src/Ice/CommunicatorI.h new file mode 100644 index 00000000000..4b30e3fe9d3 --- /dev/null +++ b/objc/src/Ice/CommunicatorI.h @@ -0,0 +1,28 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Communicator.h> + +#import <Wrapper.h> + +#import <Foundation/NSSet.h> + +#include <IceCpp/Communicator.h> + +@class ICEObjectAdapter; + +@interface ICECommunicator : ICEInternalWrapper<ICECommunicator> +{ + NSMutableDictionary* objectFactories_; + NSDictionary* prefixTable_; +} +-(void)setup:(NSDictionary*)prefixTable; +-(Ice::Communicator*)communicator; +-(NSDictionary*)getPrefixTable; +@end diff --git a/objc/src/Ice/Connection.mm b/objc/src/Ice/Connection.mm new file mode 100644 index 00000000000..703d611f575 --- /dev/null +++ b/objc/src/Ice/Connection.mm @@ -0,0 +1,424 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <ConnectionI.h> +#import <EndpointI.h> +#import <IdentityI.h> +#import <ObjectAdapterI.h> +#import <ProxyI.h> +#import <Util.h> + +@implementation ICEConnectionInfo + +@synthesize incoming; +@synthesize adapterName; +@synthesize connectionId; + +-(id) initWithConnectionInfo:(Ice::ConnectionInfo*)connectionInfo; +{ + self = [super init]; + if(self != nil) + { + self->incoming = connectionInfo->incoming; + self->adapterName = [[NSString alloc] initWithUTF8String:connectionInfo->adapterName.c_str()]; + self->connectionId = [[NSString alloc] initWithUTF8String:connectionInfo->connectionId.c_str()]; + } + return self; +} + +-(void) dealloc +{ + [self->adapterName release]; + [self->connectionId release]; + [super dealloc]; +} + +-(BOOL) isEqual:(id)o_ +{ + if(self == o_) + { + return YES; + } + if(!o_ || ![o_ isKindOfClass:[self class]]) + { + return NO; + } + ICEConnectionInfo *obj_ = (ICEConnectionInfo *)o_; + if(self->incoming != obj_->incoming) + { + return NO; + } + if(![self->adapterName isEqualToString:obj_->adapterName]) + { + return NO; + } + if(![self->connectionId isEqualToString:obj_->connectionId]) + { + return NO; + } + return YES; +} + ++(id) connectionInfoWithConnectionInfo:(Ice::ConnectionInfo*)connectionInfo +{ + if(!connectionInfo) + { + return nil; + } + else if(dynamic_cast<Ice::UDPConnectionInfo*>(connectionInfo)) + { + return [[[ICEUDPConnectionInfo alloc] + initWithUDPConnectionInfo:dynamic_cast<Ice::UDPConnectionInfo*>(connectionInfo)] autorelease]; + } + else if(dynamic_cast<Ice::TCPConnectionInfo*>(connectionInfo)) + { + return [[[ICETCPConnectionInfo alloc] + initWithTCPConnectionInfo:dynamic_cast<Ice::TCPConnectionInfo*>(connectionInfo)] autorelease]; + } + else if(dynamic_cast<IceSSL::ConnectionInfo*>(connectionInfo)) + { + return [[[ICESSLConnectionInfo alloc] + initWithSSLConnectionInfo:dynamic_cast<IceSSL::ConnectionInfo*>(connectionInfo)] autorelease]; + } + return nil; +} +@end + +@implementation ICEIPConnectionInfo + +@synthesize localAddress; +@synthesize localPort; +@synthesize remoteAddress; +@synthesize remotePort; + +-(id) initWithIPConnectionInfo:(Ice::IPConnectionInfo*)ipConnectionInfo +{ + self = [super initWithConnectionInfo:ipConnectionInfo]; + if(self) + { + self->localAddress = [[NSString alloc] initWithUTF8String:ipConnectionInfo->localAddress.c_str()]; + self->localPort = ipConnectionInfo->localPort; + self->remoteAddress = [[NSString alloc] initWithUTF8String:ipConnectionInfo->remoteAddress.c_str()]; + self->remotePort = ipConnectionInfo->remotePort; + } + return self; +} + +-(void) dealloc +{ + [self->localAddress release]; + [self->remoteAddress release]; + [super dealloc]; +} + +-(BOOL) isEqual:(id)o_ +{ + if(self == o_) + { + return YES; + } + if(!o_ || ![o_ isKindOfClass:[self class]]) + { + return NO; + } + if(![super isEqual:o_]) + { + return NO; + } + ICEIPConnectionInfo *obj_ = (ICEIPConnectionInfo *)o_; + if(![self->localAddress isEqualToString:obj_->localAddress]) + { + return NO; + } + if(self->localPort != obj_->localPort) + { + return NO; + } + if(![self->remoteAddress isEqualToString:obj_->remoteAddress]) + { + return NO; + } + if(self->remotePort != obj_->remotePort) + { + return NO; + } + return YES; +} +@end + +@implementation ICETCPConnectionInfo + +-(id) initWithTCPConnectionInfo:(Ice::TCPConnectionInfo*)tcpConnectionInfo +{ + self = [super initWithIPConnectionInfo:tcpConnectionInfo]; + return self; +} +@end + +@implementation ICEUDPConnectionInfo + +@synthesize mcastAddress; +@synthesize mcastPort; + +-(id) initWithUDPConnectionInfo:(Ice::UDPConnectionInfo*)udpConnectionInfo +{ + self = [super initWithIPConnectionInfo:udpConnectionInfo]; + if(self) + { + self->mcastAddress = [[NSString alloc] initWithUTF8String:udpConnectionInfo->mcastAddress.c_str()]; + self->mcastPort = udpConnectionInfo->mcastPort; + } + return self; +} + +-(void) dealloc +{ + [self->mcastAddress release]; + [super dealloc]; +} + +-(BOOL) isEqual:(id)o_ +{ + if(self == o_) + { + return YES; + } + if(!o_ || ![o_ isKindOfClass:[self class]]) + { + return NO; + } + if(![super isEqual:o_]) + { + return NO; + } + ICEUDPConnectionInfo *obj_ = (ICEUDPConnectionInfo *)o_; + if(![self->mcastAddress isEqualToString:obj_->mcastAddress]) + { + return NO; + } + if(self->mcastPort != obj_->mcastPort) + { + return NO; + } + return YES; +} +@end + +@implementation ICESSLConnectionInfo + +@synthesize cipher; +@synthesize certs; + +-(id) initWithSSLConnectionInfo:(IceSSL::ConnectionInfo*)sslConnectionInfo +{ + self = [super initWithIPConnectionInfo:sslConnectionInfo]; + if(self) + { + self->cipher = [[NSString alloc] initWithUTF8String:sslConnectionInfo->cipher.c_str()]; + self->certs = toNSArray(sslConnectionInfo->certs); + } + return self; +} + +-(void) dealloc +{ + [self->cipher release]; + [self->certs release]; + [super dealloc]; +} + +-(BOOL) isEqual:(id)o_ +{ + if(self == o_) + { + return YES; + } + if(!o_ || ![o_ isKindOfClass:[self class]]) + { + return NO; + } + if(![super isEqual:o_]) + { + return NO; + } + ICESSLConnectionInfo* obj_ = (ICESSLConnectionInfo*)o_; + if(![self->cipher isEqualToString:obj_->cipher]) + { + return NO; + } + if(![self->certs isEqual:obj_->certs]) + { + return NO; + } + return YES; +} +@end + +#define CONNECTION dynamic_cast<Ice::Connection*>(static_cast<IceUtil::Shared*>(cxxObject_)) + +@implementation ICEConnection +-(void) close:(BOOL)force +{ + NSException* nsex = nil; + try + { + CONNECTION->close(force); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} +-(id<ICEObjectPrx>) createProxy:(ICEIdentity*)identity +{ + NSException* nsex = nil; + try + { + return [ICEObjectPrx objectPrxWithObjectPrx__:CONNECTION->createProxy([identity identity])]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(void) setAdapter:(id<ICEObjectAdapter>)adapter +{ + NSException* nsex = nil; + try + { + CONNECTION->setAdapter([(ICEObjectAdapter*)adapter adapter]); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} +-(id<ICEObjectAdapter>) getAdapter +{ + NSException* nsex = nil; + try + { + return [ICEObjectAdapter wrapperWithCxxObject:CONNECTION->getAdapter().get()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(void) flushBatchRequests +{ + NSException* nsex = nil; + try + { + CONNECTION->flushBatchRequests(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} +-(id<ICEAsyncResult>) begin_flushBatchRequests +{ + return beginCppCall(^(Ice::AsyncResultPtr& result) + { + result = CONNECTION->begin_flushBatchRequests(); + }); +} +-(id<ICEAsyncResult>) begin_flushBatchRequests:(void(^)(ICEException*))exception +{ + return [self begin_flushBatchRequests:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_flushBatchRequests:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) + { + result = CONNECTION->begin_flushBatchRequests(cb); + }, + ^(const Ice::AsyncResultPtr& result) { + CONNECTION->end_flushBatchRequests(result); + }, + exception, sent); +} +-(void) end_flushBatchRequests:(id<ICEAsyncResult>)result +{ + endCppCall(^(const Ice::AsyncResultPtr& r) + { + CONNECTION->end_flushBatchRequests(r); + }, result); +} +-(NSString*) type +{ + return [toNSString(CONNECTION->type()) autorelease]; +} +-(ICEInt) timeout +{ + return CONNECTION->timeout(); +} +-(NSString*) toString +{ + return [toNSString(CONNECTION->toString()) autorelease]; +} +-(NSString*) description +{ + return [toNSString(CONNECTION->toString()) autorelease]; +} + +-(ICEConnectionInfo*) getInfo +{ + NSException* nsex = nil; + try + { + Ice::ConnectionInfoPtr info = CONNECTION->getInfo(); + return [ICEConnectionInfo connectionInfoWithConnectionInfo:info.get()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return nil; +} + +-(ICEEndpoint*) getEndpoint +{ + NSException* nsex = nil; + try + { + return [ICEEndpoint wrapperWithCxxObject:CONNECTION->getEndpoint().get()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return nil; +} +@end diff --git a/objc/src/Ice/ConnectionI.h b/objc/src/Ice/ConnectionI.h new file mode 100644 index 00000000000..86c6df4e001 --- /dev/null +++ b/objc/src/Ice/ConnectionI.h @@ -0,0 +1,39 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Connection.h> + +#import <Wrapper.h> + +#include <IceCpp/Connection.h> +#include <IceSSLCpp/ConnectionInfo.h> + +@interface ICEConnectionInfo () +-(id) initWithConnectionInfo:(Ice::ConnectionInfo*)connectionInfo; ++(id) connectionInfoWithConnectionInfo:(Ice::ConnectionInfo*)connectionInfo; +@end + +@interface ICEIPConnectionInfo () +-(id) initWithIPConnectionInfo:(Ice::IPConnectionInfo*)ipConnectionInfo; +@end + +@interface ICETCPConnectionInfo () +-(id) initWithTCPConnectionInfo:(Ice::TCPConnectionInfo*)tcpConnectionInfo; +@end + +@interface ICEUDPConnectionInfo () +-(id) initWithUDPConnectionInfo:(Ice::UDPConnectionInfo*)udpConnectionInfo; +@end + +@interface ICESSLConnectionInfo () +-(id) initWithSSLConnectionInfo:(IceSSL::ConnectionInfo*)sslConnectionInfo; +@end + +@interface ICEConnection : ICEInternalWrapper<ICEConnection> +@end diff --git a/objc/src/Ice/Current.mm b/objc/src/Ice/Current.mm new file mode 100644 index 00000000000..2490a142f53 --- /dev/null +++ b/objc/src/Ice/Current.mm @@ -0,0 +1,287 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <CurrentI.h> +#import <VersionI.h> +#import <ObjectAdapterI.h> +#import <ConnectionI.h> +#import <IdentityI.h> +#import <Util.h> + +// +// NOTE: Current.h/Current.m are not generated from the Slice +// Current.ice file for few reasons: +// +// - Current.ice includes a number of other Slice files that we don't need to generate. +// - the Current structure is local and slice2objc doesn't support local structures. +// + +@implementation ICECurrent + +@synthesize adapter; +@synthesize con; +@synthesize id_; +@synthesize facet; +@synthesize operation; +@synthesize mode; +@synthesize ctx; +@synthesize requestId; +@synthesize encoding; + +-(id) init:(id<ICEObjectAdapter>)adapter_ + con:(id<ICEConnection>)con_ + id_:(ICEIdentity *)id__ + facet:(NSString *)facet_ + operation:(NSString *)operation_ + mode:(ICEOperationMode)mode_ + ctx:(NSDictionary *)ctx_ + requestId:(ICEInt)requestId_ + encoding:(ICEEncodingVersion*)encoding_ +{ + self = [super init]; + if(!self) + { + return nil; + } + adapter = [adapter_ retain]; + con = [con_ retain]; + id_ = [id__ retain]; + facet = [facet_ retain]; + operation = [operation_ retain]; + mode = mode_; + ctx = [ctx_ retain]; + requestId = requestId_; + encoding = [encoding_ retain]; + return self; +} + ++(id) current:(id<ICEObjectAdapter>)adapter_ + con:(id<ICEConnection>)con_ + id_:(ICEIdentity *)id__ + facet:(NSString *)facet_ + operation:(NSString *)operation_ + mode:(ICEOperationMode)mode_ + ctx:(NSDictionary *)ctx_ + requestId:(ICEInt)requestId_ + encoding:(ICEEncodingVersion*)encoding_ +{ + ICECurrent *s__ = [((ICECurrent *)[ICECurrent alloc]) init:adapter_ + con:con_ + id_:id__ + facet:facet_ + operation:operation_ + mode:mode_ + ctx:ctx_ + requestId:requestId_ + encoding:encoding_]; + [s__ autorelease]; + return s__; +} + ++(id) current +{ + ICECurrent *s__ = [[ICECurrent alloc] init]; + [s__ autorelease]; + return s__; +} + +-(id) copyWithZone:(NSZone *)zone +{ + ICECurrent *copy_ = [ICECurrent allocWithZone:zone]; + copy_->adapter = [adapter retain]; + copy_->con = [con retain]; + copy_->id_ = [id_ retain]; + copy_->facet = [facet retain]; + copy_->operation = [operation retain]; + copy_->mode = mode; + copy_->ctx = [ctx retain]; + copy_->requestId = requestId; + copy_->encoding = [encoding retain]; + return copy_; +} + +-(NSUInteger) hash +{ + NSUInteger h_ = 0; + h_ = (h_ << 1) ^ (!adapter ? 0 : [adapter hash]); + h_ = (h_ << 1) ^ (!con ? 0 : [con hash]); + h_ = (h_ << 1) ^ (!id_ ? 0 : [id_ hash]); + h_ = (h_ << 1) ^ (!facet ? 0 : [facet hash]); + h_ = (h_ << 1) ^ (!operation ? 0 : [operation hash]); + h_ = (h_ << 1) ^ mode; + h_ = (h_ << 1) ^ (!ctx ? 0 : [ctx hash]); + h_ = (h_ << 1) ^ requestId; + h_ = (h_ << 1) ^ (!encoding ? 0 : [encoding hash]); + return h_; +} + +-(BOOL) isEqual:(id)o_ +{ + if(self == o_) + { + return YES; + } + if(!o_ || ![o_ isKindOfClass:[self class]]) + { + return NO; + } + ICECurrent *obj_ = (ICECurrent *)o_; + if(!adapter) + { + if(obj_->adapter) + { + return NO; + } + } + else + { + if(![adapter isEqual:obj_->adapter]) + { + return NO; + } + } + if(!con) + { + if(obj_->con) + { + return NO; + } + } + else + { + if(![con isEqual:obj_->con]) + { + return NO; + } + } + if(!id_) + { + if(obj_->id_) + { + return NO; + } + } + else + { + if(![id_ isEqual:obj_->id_]) + { + return NO; + } + } + if(!facet) + { + if(obj_->facet) + { + return NO; + } + } + else + { + if(![facet isEqualToString:obj_->facet]) + { + return NO; + } + } + if(!operation) + { + if(obj_->operation) + { + return NO; + } + } + else + { + if(![operation isEqualToString:obj_->operation]) + { + return NO; + } + } + if(mode != obj_->mode) + { + return NO; + } + if(!ctx) + { + if(obj_->ctx) + { + return NO; + } + } + else + { + if(![ctx isEqual:obj_->ctx]) + { + return NO; + } + } + if(requestId != obj_->requestId) + { + return NO; + } + return YES; +} + +-(void) dealloc +{ + [adapter release]; + [con release]; + [id_ release]; + [facet release]; + [operation release]; + [ctx release]; + [encoding release]; + [super dealloc]; +} + +-(ICECurrent*) initWithCurrent:(const Ice::Current&)current +{ + self = [super init]; + if(!self) + { + return nil; + } + + // + // TODO: Optimize: the servant blobject should cache an ICECurrent object to + // avoid re-creating the wrappers for each dispatched invocation. + // + adapter = [ICEObjectAdapter wrapperWithCxxObjectNoAutoRelease:current.adapter.get()]; + con = [ICEConnection wrapperWithCxxObjectNoAutoRelease:current.con.get()]; + id_ = [[ICEIdentity alloc] initWithIdentity:current.id]; + facet = [[NSString alloc] initWithUTF8String:current.facet.c_str()]; + operation = [[NSString alloc] initWithUTF8String:current.operation.c_str()]; + mode = (ICEOperationMode)current.mode; + ctx = toNSDictionary(current.ctx); + requestId = current.requestId; + encoding = [[ICEEncodingVersion encodingVersionWithEncodingVersion:current.encoding] retain]; + return self; +} +@end + +@implementation ICEContextHelper ++(ICEKeyValueTypeHelper) getKeyValueHelper +{ + ICEKeyValueTypeHelper c; + c.key = [ICEStringHelper class]; + c.value = [ICEStringHelper class]; + return c; +} +@end + +@implementation ICEOperationModeHelper ++(ICEInt) getMinValue +{ + return 0; +} + ++(ICEInt) getMaxValue +{ + return 3; +} +@end diff --git a/objc/src/Ice/CurrentI.h b/objc/src/Ice/CurrentI.h new file mode 100644 index 00000000000..5c8910fdaac --- /dev/null +++ b/objc/src/Ice/CurrentI.h @@ -0,0 +1,16 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Current.h> + +#include <IceCpp/Current.h> + +@interface ICECurrent () +-(ICECurrent*) initWithCurrent:(const Ice::Current&)arg; +@end diff --git a/objc/src/Ice/DispatchInterceptor.m b/objc/src/Ice/DispatchInterceptor.m new file mode 100644 index 00000000000..3acb01db3f9 --- /dev/null +++ b/objc/src/Ice/DispatchInterceptor.m @@ -0,0 +1,60 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/DispatchInterceptor.h> + +#import <Request.h> + +#import <Foundation/NSThread.h> +#import <Foundation/NSInvocation.h> + +@implementation ICEDispatchInterceptor +-(BOOL) dispatch__:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os +{ + ICERequest* request = [ICERequest request:current is:is os:os]; + id<ICEDispatchInterceptor> dispatchInterceptor = (id<ICEDispatchInterceptor>)self; + return [dispatchInterceptor dispatch:request]; +} +@end + +@implementation ICEMainThreadDispatch + +-(id)init:(ICEObject*)s +{ + servant = [s retain]; + return self; +} + ++(id)mainThreadDispatch:(ICEObject*)s +{ + return [[[self alloc] init:s] autorelease]; +} + +-(BOOL) dispatch:(id<ICERequest>)request +{ + SEL selector = @selector(ice_dispatch:); + NSMethodSignature* sig = [[servant class] instanceMethodSignatureForSelector:selector]; + NSInvocation* inv = [NSInvocation invocationWithMethodSignature:sig]; + [inv setTarget:servant]; + [inv setSelector:selector]; + [inv setArgument:&request atIndex:2]; + + [inv performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:servant waitUntilDone:YES]; + + BOOL status; + [inv getReturnValue:&status]; + return status; +} + +-(void)dealloc +{ + [servant release]; + [super dealloc]; +} +@end diff --git a/objc/src/Ice/Dispatcher.mm b/objc/src/Ice/Dispatcher.mm new file mode 100644 index 00000000000..6e055bd0476 --- /dev/null +++ b/objc/src/Ice/Dispatcher.mm @@ -0,0 +1,96 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <DispatcherI.h> +#import <Util.h> +#import <ConnectionI.h> + +#include <Block.h> + +namespace +{ + +class DispatcherI : public Ice::Dispatcher +{ +public: + +// We must explicitely retain/release so that the garbage +// collector does not trash the dispatcher. +DispatcherI(void(^dispatcher)(id<ICEDispatcherCall>, id<ICEConnection>)) : _dispatcher(Block_copy(dispatcher)) +{ +} + +virtual ~DispatcherI() +{ + Block_release(_dispatcher); +} + +virtual void +dispatch(const Ice::DispatcherCallPtr& call, const Ice::ConnectionPtr& connection) +{ + id<ICEConnection> con = [ICEConnection wrapperWithCxxObjectNoAutoRelease:connection.get()]; + id<ICEDispatcherCall> c = [[ICEDispatcherCall alloc] initWithCall:call.get()]; + @try + { + _dispatcher(c, con); + } + @finally + { + [con release]; + [c release]; + } +} + +private: + +void(^_dispatcher)(id<ICEDispatcherCall>, id<ICEConnection>); + +}; +typedef IceUtil::Handle<DispatcherI> DispatcherIPtr; + +} + +@implementation ICEDispatcher ++(Ice::Dispatcher*) dispatcherWithDispatcher:(void(^)(id<ICEDispatcherCall>, id<ICEConnection>))dispatcher +{ + return new DispatcherI(dispatcher); +} +@end + +@implementation ICEDispatcherCall +-(id) initWithCall:(Ice::DispatcherCall*)call +{ + self = [super init]; + if(!self) + { + return nil; + } + + cxxCall_ = call; + cxxCall_->__incRef(); + return self; +} +-(void) dealloc +{ + cxxCall_->__decRef(); + cxxCall_ = 0; + [super dealloc]; +} +-(void) finalize +{ + cxxCall_->__decRef(); + cxxCall_ = 0; + [super finalize]; +} + +-(void) run +{ + cppCall(^ { cxxCall_->run(); }); +} +@end diff --git a/objc/src/Ice/DispatcherI.h b/objc/src/Ice/DispatcherI.h new file mode 100644 index 00000000000..8b09e28bde9 --- /dev/null +++ b/objc/src/Ice/DispatcherI.h @@ -0,0 +1,27 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Initialize.h> +#import <objc/Ice/Connection.h> + +#import <Wrapper.h> + +#include <IceCpp/Dispatcher.h> + +@interface ICEDispatcher : NSObject ++(Ice::Dispatcher*)dispatcherWithDispatcher:(void(^)(id<ICEDispatcherCall>, id<ICEConnection>))arg; +@end + +@interface ICEDispatcherCall : NSObject<ICEDispatcherCall> +{ + Ice::DispatcherCall* cxxCall_; +} +-(id) initWithCall:(Ice::DispatcherCall*)call; +@end + diff --git a/objc/src/Ice/Endpoint.mm b/objc/src/Ice/Endpoint.mm new file mode 100644 index 00000000000..9fc13d39721 --- /dev/null +++ b/objc/src/Ice/Endpoint.mm @@ -0,0 +1,321 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in +// the ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <EndpointI.h> +#import <Util.h> +#import <VersionI.h> + +#import <objc/Ice/BuiltinSequences.h> + +#import <IceCpp/Endpoint.h> + + +const int ICETCPEndpointType = 1; +const int ICESSLEndpointType = 2; +const int ICEUDPEndpointType = 3; + +#define ENDPOINT dynamic_cast<Ice::Endpoint*>(static_cast<IceUtil::Shared*>(cxxObject_)) + +@implementation ICEEndpoint + +-(Ice::Endpoint*) endpoint +{ + return ENDPOINT; +} + +-(ICEEndpointInfo*) getInfo +{ + Ice::EndpointInfoPtr info = ENDPOINT->getInfo(); + return [ICEEndpointInfo enpointInfoWithEndpointInfo:info.get()]; +} + +-(NSString*) toString +{ + return [toNSString(ENDPOINT->toString()) autorelease]; +} + +-(BOOL) isEqual:(id)o_ +{ + if(self == o_) + { + return YES; + } + if(!o_ || ![o_ isKindOfClass:[self class]]) + { + return NO; + } + ICEEndpoint* obj_ = (ICEEndpoint*)o_; + return *ENDPOINT == *(dynamic_cast<Ice::Endpoint*>(static_cast<IceUtil::Shared*>(obj_->cxxObject_))); +} +@end + +@implementation ICEEndpointInfo + +@synthesize timeout; +@synthesize compress; + +-(id) init +{ + self = [super init]; + return self; +} + +-(id) initWithEndpointInfo:(Ice::EndpointInfo*)endpointInfo; +{ + self = [super init]; + if(self) + { + self->timeout = endpointInfo->timeout; + self->compress = endpointInfo->compress; + self->type_ = endpointInfo->type(); + self->datagram_ = endpointInfo->datagram(); + self->secure_ = endpointInfo->secure(); + } + return self; +} + ++(id) enpointInfoWithEndpointInfo:(Ice::EndpointInfo*)endpointInfo +{ + if(!endpointInfo) + { + return nil; + } + else if(dynamic_cast<Ice::TCPEndpointInfo*>(endpointInfo)) + { + return [[[ICETCPEndpointInfo alloc] + initWithTCPEndpointInfo:dynamic_cast<Ice::TCPEndpointInfo*>(endpointInfo)] autorelease]; + } + else if(dynamic_cast<Ice::UDPEndpointInfo*>(endpointInfo)) + { + return [[[ICEUDPEndpointInfo alloc] + initWithUDPEndpointInfo:dynamic_cast<Ice::UDPEndpointInfo*>(endpointInfo)] autorelease]; +} + else if(dynamic_cast<Ice::OpaqueEndpointInfo*>(endpointInfo)) + { + return [[[ICEOpaqueEndpointInfo alloc] + initWithOpaqueEndpointInfo:dynamic_cast<Ice::OpaqueEndpointInfo*>(endpointInfo)] autorelease]; + } + else if(dynamic_cast<IceSSL::EndpointInfo*>(endpointInfo)) + { + return [[[ICESSLEndpointInfo alloc] + initWithSSLEndpointInfo:dynamic_cast<IceSSL::EndpointInfo*>(endpointInfo)] autorelease]; + } + return nil; +} + +-(BOOL) isEqual:(id)o_ +{ + if(self == o_) + { + return YES; + } + if(!o_ || ![o_ isKindOfClass:[self class]]) + { + return NO; + } + ICEEndpointInfo* obj_ = (ICEEndpointInfo*)o_; + if(self->timeout != obj_->timeout) + { + return NO; + } + if(self->compress != obj_->compress) + { + return NO; + } + if(self->type_ != obj_->type_) + { + return NO; + } + if(self->datagram_ != obj_->datagram_) + { + return NO; + } + if(self->secure_ != obj_->secure_) + { + return NO; + } + return YES; +} + +-(ICEShort) type +{ + return type_; +} + +-(BOOL) datagram; +{ + return datagram_; +} + +-(BOOL) secure; +{ + return secure_; +} +@end + +@implementation ICEIPEndpointInfo + +@synthesize host; +@synthesize port; + +-(id) initWithIPEndpointInfo:(Ice::IPEndpointInfo*)ipEndpointInfo; +{ + self = [super initWithEndpointInfo:ipEndpointInfo]; + if(self) + { + self->host = [[NSString alloc] initWithUTF8String:ipEndpointInfo->host.c_str()]; + self->port = ipEndpointInfo->port; + } + return self; +} + +-(void) dealloc +{ + [self->host release]; + [super dealloc]; +} + +-(BOOL) isEqual:(id)o_ +{ + if(self == o_) + { + return YES; + } + if(!o_ || ![o_ isKindOfClass:[self class]]) + { + return NO; + } + if(![super isEqual:o_]) + { + return NO; + } + ICEIPEndpointInfo* obj_ = (ICEIPEndpointInfo*)o_; + if(![self->host isEqualToString:obj_->host]) + { + return NO; + } + if(self->port != obj_->port) + { + return NO; + } + return YES; +} +@end + +@implementation ICETCPEndpointInfo +-(id) initWithTCPEndpointInfo:(Ice::TCPEndpointInfo*)tcpEndpointInfo +{ + self = [super initWithIPEndpointInfo:tcpEndpointInfo]; + return self; +} +@end + +@implementation ICEUDPEndpointInfo + +@synthesize mcastInterface; +@synthesize mcastTtl; + +-(id) initWithUDPEndpointInfo:(Ice::UDPEndpointInfo*)udpEndpointInfo +{ + self = [super initWithIPEndpointInfo:udpEndpointInfo]; + if(self) + { + self->mcastInterface = [[NSString alloc] initWithUTF8String:udpEndpointInfo->mcastInterface.c_str()]; + self->mcastTtl = udpEndpointInfo->mcastTtl; + } + return self; +} + +-(void) dealloc +{ + [self->mcastInterface release]; + [super dealloc]; + +} + +-(BOOL) isEqual:(id)o_ +{ + if(self == o_) + { + return YES; + } + if(!o_ || ![o_ isKindOfClass:[self class]]) + { + return NO; + } + if(![super isEqual:o_]) + { + return NO; + } + ICEUDPEndpointInfo* obj_ = (ICEUDPEndpointInfo*)o_; + if(![self->mcastInterface isEqualToString:obj_->mcastInterface]) + { + return NO; + } + if(self->mcastTtl != obj_->mcastTtl) + { + return NO; + } + return YES; +} +@end + +@implementation ICEOpaqueEndpointInfo + +@synthesize rawEncoding; +@synthesize rawBytes; + +-(id) initWithOpaqueEndpointInfo:(Ice::OpaqueEndpointInfo*)opaqueEndpointInfo +{ + self = [super init]; + if(self) + { + self->rawEncoding = [[ICEEncodingVersion alloc] initWithEncodingVersion:opaqueEndpointInfo->rawEncoding]; + self->rawBytes = toNSData(opaqueEndpointInfo->rawBytes); + } + return self; +} + +-(void) dealloc +{ + [self->rawEncoding release]; + [self->rawBytes release]; + [super dealloc]; +} + +-(BOOL) isEqual:(id)o_ +{ + if(self == o_) + { + return YES; + } + if(!o_ || ![o_ isKindOfClass:[self class]]) + { + return NO; + } + ICEOpaqueEndpointInfo* obj_ = (ICEOpaqueEndpointInfo*)o_; + if(![self->rawEncoding isEqual:obj_->rawEncoding]) + { + return NO; + } + if(![self->rawBytes isEqual:obj_->rawBytes]) + { + return NO; + } + return YES; +} +@end + +@implementation ICESSLEndpointInfo +-(id) initWithSSLEndpointInfo:(IceSSL::EndpointInfo*)sslEndpointInfo +{ + self = [super initWithIPEndpointInfo:sslEndpointInfo]; + return self; +} +@end diff --git a/objc/src/Ice/EndpointI.h b/objc/src/Ice/EndpointI.h new file mode 100644 index 00000000000..a0b02bafa64 --- /dev/null +++ b/objc/src/Ice/EndpointI.h @@ -0,0 +1,45 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in +// the ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Endpoint.h> + +#import <Wrapper.h> + +#include <IceCpp/Endpoint.h> +#include <IceSSLCpp/EndpointInfo.h> + +@interface ICEEndpoint : ICEInternalWrapper<ICEEndpoint> +-(Ice::Endpoint*) endpoint; +@end + + +@interface ICEEndpointInfo () +-(id) initWithEndpointInfo:(Ice::EndpointInfo*)endpointInfo; ++(id) enpointInfoWithEndpointInfo:(Ice::EndpointInfo*)endpointInfo; +@end + +@interface ICEIPEndpointInfo () +-(id) initWithIPEndpointInfo:(Ice::IPEndpointInfo*)ipEndpointInfo; +@end + +@interface ICETCPEndpointInfo () +-(id) initWithTCPEndpointInfo:(Ice::TCPEndpointInfo*)tcpEndpointInfo; +@end + +@interface ICEUDPEndpointInfo () +-(id) initWithUDPEndpointInfo:(Ice::UDPEndpointInfo*)udpEndpointInfo; +@end + +@interface ICEOpaqueEndpointInfo () +-(id) initWithOpaqueEndpointInfo:(Ice::OpaqueEndpointInfo*)opaqueEndpointInfo; +@end + +@interface ICESSLEndpointInfo () +-(id) initWithSSLEndpointInfo:(IceSSL::EndpointInfo*)sslEndpointInfo; +@end diff --git a/objc/src/Ice/Exception.mm b/objc/src/Ice/Exception.mm new file mode 100644 index 00000000000..908ad553630 --- /dev/null +++ b/objc/src/Ice/Exception.mm @@ -0,0 +1,919 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <ExceptionI.h> +#import <IdentityI.h> +#import <Util.h> +#import <VersionI.h> + +#import <objc/Ice/LocalException.h> + +#include <IceCpp/LocalException.h> + +#import <Foundation/NSKeyedArchiver.h> + +@implementation ICEException +-(id)init +{ + return [super initWithName:[self ice_name] reason:nil userInfo:nil]; +} + +-(id)initWithReason:(NSString*)reason +{ + return [super initWithName:[self ice_name] reason:reason userInfo:nil]; +} +-(NSString*)ice_name +{ + NSAssert(false, @"ice_name not overriden"); + return nil; +} + +-(id) initWithCoder:(NSCoder*)decoder +{ + [NSException raise:NSInvalidArchiveOperationException format:@"ICEExceptions do not support NSCoding"]; + return nil; +} + +-(void) encodeWithCoder:(NSCoder*)coder +{ + [NSException raise:NSInvalidArchiveOperationException format:@"ICEExceptions do not support NSCoding"]; +} + +-(id) copyWithZone:(NSZone *)zone +{ + NSAssert(false, @"copyWithZone: must be overriden"); + return nil; +} + +-(void) dealloc +{ + [super dealloc]; +} +@end + +static NSString* +localExceptionToString(const Ice::LocalException& ex) +{ + std::ostringstream os; + os << ex; + std::string str = os.str(); + const std::string prefix = "../../../cpp/src/"; + if(str.find(prefix) == 0) + { + str = str.substr(prefix.size()); + } + return [NSString stringWithUTF8String:str.c_str()]; +} + +@implementation ICELocalException +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithReason:localExceptionToString(ex)]; + if(!self) + { + return nil; + } + file = ex.ice_file(); + line = ex.ice_line(); + return self; +} + +-(void)rethrowCxx +{ + NSAssert(false, @"rethrowCxx must be overriden"); +} + ++(id)localExceptionWithLocalException:(const Ice::LocalException&)ex +{ + return [[[self alloc] initWithLocalException:ex] autorelease]; +} + +-(NSString*) file +{ + return [toNSString(file) autorelease]; +} + +@synthesize line; + +-(id)init:(const char*)f line:(int)l +{ + self = [super init]; + if(!self) + { + return nil; + } + file = f; + line = l; + return self; +} + ++(id)localException:(const char*)file line:(int)line +{ + return [[[self alloc] init:file line:line] autorelease]; +} + +-(NSString*)description +{ + try + { + [self rethrowCxx]; + return @""; // Keep the compiler happy. + } + catch(const Ice::LocalException& ex) + { + return localExceptionToString(ex); + } +} + +-(id) copyWithZone:(NSZone *)zone +{ + return [[[self class] allocWithZone:zone] init:file line:line]; +} + +-(void) dealloc +{ + [super dealloc]; +} +@end + +@implementation ICEUserException +-(BOOL)usesClasses__ +{ + return NO; +} + +-(void)write__:(id<ICEOutputStream>)os +{ + [os startException:nil]; + [self writeImpl__:os]; + [os endException]; +} + +-(void) writeImpl__:(id<ICEOutputStream>)os +{ + NSAssert(NO, @"writeImpl__ requires override"); +} + +-(void)read__:(id<ICEInputStream>)is +{ + [is startException]; + [self readImpl__:is]; + [is endException:NO]; +} + +-(void) readImpl__:(id<ICEInputStream>)is +{ + NSAssert(NO, @"readImpl__ requires override"); +} + +-(id) copyWithZone:(NSZone *)zone +{ + return [[[self class] allocWithZone:zone] init]; +} + +-(void) dealloc +{ + [super dealloc]; +} +@end + +@implementation ICEInitializationException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::InitializationException*>(&ex), @"invalid local exception type"); + const Ice::InitializationException& localEx = dynamic_cast<const Ice::InitializationException&>(ex); + reason_ = toNSString(localEx.reason); + return self; +} +-(void) rethrowCxx +{ + throw Ice::InitializationException(file, line, fromNSString(reason_)); +} +@end + +@implementation ICEPluginInitializationException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::PluginInitializationException*>(&ex), @"invalid local exception type"); + const Ice::PluginInitializationException& localEx = dynamic_cast<const Ice::PluginInitializationException&>(ex); + reason_ = toNSString(localEx.reason); + return self; +} +-(void) rethrowCxx +{ + throw Ice::PluginInitializationException(file, line, fromNSString(reason_)); +} +@end + +@implementation ICECollocationOptimizationException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::CollocationOptimizationException(file, line); +} +@end + +@implementation ICEAlreadyRegisteredException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::AlreadyRegisteredException*>(&ex), @"invalid local exception type"); + const Ice::AlreadyRegisteredException& localEx = dynamic_cast<const Ice::AlreadyRegisteredException&>(ex); + kindOfObject = toNSString(localEx.kindOfObject); + id_ = toNSString(localEx.id); + return self; +} +-(void) rethrowCxx +{ + throw Ice::AlreadyRegisteredException(file, line, fromNSString(kindOfObject), fromNSString(id_)); +} +@end + +@implementation ICENotRegisteredException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::NotRegisteredException*>(&ex), @"invalid local exception type"); + const Ice::NotRegisteredException& localEx = dynamic_cast<const Ice::NotRegisteredException&>(ex); + kindOfObject = toNSString(localEx.kindOfObject); + id_ = toNSString(localEx.id); + return self; +} +-(void) rethrowCxx +{ + throw Ice::NotRegisteredException(file, line, fromNSString(kindOfObject), fromNSString(id_)); +} +@end + +@implementation ICETwowayOnlyException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::TwowayOnlyException*>(&ex), @"invalid local exception type"); + const Ice::TwowayOnlyException& localEx = dynamic_cast<const Ice::TwowayOnlyException&>(ex); + operation = toNSString(localEx.operation); + return self; +} +-(void) rethrowCxx +{ + throw Ice::TwowayOnlyException(file, line, fromNSString(operation)); +} +@end + +@implementation ICEUnknownException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::UnknownException*>(&ex), @"invalid local exception type"); + const Ice::UnknownException& localEx = dynamic_cast<const Ice::UnknownException&>(ex); + unknown = toNSString(localEx.unknown); + return self; +} +-(void) rethrowCxx +{ + throw Ice::UnknownException(file, line, fromNSString(unknown)); +} +@end + +@implementation ICEUnknownLocalException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::UnknownLocalException(file, line, fromNSString([self unknown])); +} +@end + +@implementation ICEUnknownUserException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::UnknownUserException(file, line, fromNSString([self unknown])); +} +@end + +@implementation ICEVersionMismatchException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::VersionMismatchException(file, line); +} +@end + +@implementation ICECommunicatorDestroyedException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::CommunicatorDestroyedException(file, line); +} +@end + +@implementation ICEObjectAdapterDeactivatedException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::ObjectAdapterDeactivatedException*>(&ex), @"invalid local exception type"); + const Ice::ObjectAdapterDeactivatedException& localEx = dynamic_cast<const Ice::ObjectAdapterDeactivatedException&>(ex); + name_ = toNSString(localEx.name); + return self; +} +-(void) rethrowCxx +{ + throw Ice::ObjectAdapterDeactivatedException(file, line, fromNSString(name_)); +} +@end + +@implementation ICEObjectAdapterIdInUseException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::ObjectAdapterIdInUseException*>(&ex), @"invalid local exception type"); + const Ice::ObjectAdapterIdInUseException& localEx = dynamic_cast<const Ice::ObjectAdapterIdInUseException&>(ex); + id_ = toNSString(localEx.id); + return self; +} +@end + +@implementation ICENoEndpointException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::NoEndpointException*>(&ex), @"invalid local exception type"); + const Ice::NoEndpointException& localEx = dynamic_cast<const Ice::NoEndpointException&>(ex); + proxy = toNSString(localEx.proxy); + return self; +} +-(void) rethrowCxx +{ + throw Ice::NoEndpointException(file, line, fromNSString(proxy)); +} +@end + +@implementation ICEEndpointParseException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::EndpointParseException*>(&ex), @"invalid local exception type"); + const Ice::EndpointParseException& localEx = dynamic_cast<const Ice::EndpointParseException&>(ex); + str = toNSString(localEx.str); + return self; +} +-(void) rethrowCxx +{ + throw Ice::EndpointParseException(file, line, fromNSString(str)); +} +@end + +@implementation ICEEndpointSelectionTypeParseException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::EndpointSelectionTypeParseException*>(&ex), @"invalid local exception type"); + const Ice::EndpointSelectionTypeParseException& localEx = dynamic_cast<const Ice::EndpointSelectionTypeParseException&>(ex); + str = toNSString(localEx.str); + return self; +} +-(void) rethrowCxx +{ + throw Ice::EndpointSelectionTypeParseException(file, line, fromNSString(str)); +} +@end + +@implementation ICEIdentityParseException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::IdentityParseException*>(&ex), @"invalid local exception type"); + const Ice::IdentityParseException& localEx = dynamic_cast<const Ice::IdentityParseException&>(ex); + str = toNSString(localEx.str); + return self; +} +@end + +@implementation ICEProxyParseException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::ProxyParseException*>(&ex), @"invalid local exception type"); + const Ice::ProxyParseException& localEx = dynamic_cast<const Ice::ProxyParseException&>(ex); + str = toNSString(localEx.str); + return self; +} +-(void) rethrowCxx +{ + throw Ice::ProxyParseException(file, line, fromNSString(str)); +} +@end + +@implementation ICEIllegalIdentityException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::IllegalIdentityException*>(&ex), @"invalid local exception type"); + const Ice::IllegalIdentityException& localEx = dynamic_cast<const Ice::IllegalIdentityException&>(ex); + id_ = [[ICEIdentity alloc] initWithIdentity:localEx.id]; + return self; +} +-(void) rethrowCxx +{ + Ice::Identity ident = { fromNSString(id_.name), fromNSString(id_.category) }; + throw Ice::IllegalIdentityException(file, line, ident); +} +@end + +@implementation ICERequestFailedException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::RequestFailedException*>(&ex), @"invalid local exception type"); + const Ice::RequestFailedException& localEx = dynamic_cast<const Ice::RequestFailedException&>(ex); + id_ = [[ICEIdentity alloc] initWithIdentity:localEx.id]; + facet = toNSString(localEx.facet); + operation = toNSString(localEx.operation); + return self; +} +-(void) rethrowCxx +{ + Ice::Identity ident = { fromNSString(id_.name), fromNSString(id_.category) }; + throw Ice::RequestFailedException(file, line, ident, fromNSString(facet), fromNSString(operation)); +} +@end + +@implementation ICEObjectNotExistException (ICEInternal) +-(void) rethrowCxx +{ + Ice::Identity ident = { fromNSString([self id_].name), fromNSString([self id_].category) }; + throw Ice::ObjectNotExistException(file, line, ident, fromNSString([self facet]), fromNSString([self operation])); +} +@end + +@implementation ICEFacetNotExistException (ICEInternal) +-(void) rethrowCxx +{ + Ice::Identity ident = { fromNSString([self id_].name), fromNSString([self id_].category) }; + throw Ice::FacetNotExistException(file, line, ident, fromNSString([self facet]), fromNSString([self operation])); +} +@end + +@implementation ICEOperationNotExistException (ICEInternal) +-(void) rethrowCxx +{ + Ice::Identity ident = { fromNSString([self id_].name), fromNSString([self id_].category) }; + throw Ice::OperationNotExistException(file, line, ident, fromNSString([self facet]), fromNSString([self operation])); +} +@end + +@implementation ICESyscallException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::SyscallException*>(&ex), @"invalid local exception type"); + const Ice::SyscallException& localEx = dynamic_cast<const Ice::SyscallException&>(ex); + error = localEx.error; + return self; +} +-(void) rethrowCxx +{ + throw Ice::SyscallException(file, line, error); +} +@end + +@implementation ICESocketException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::SocketException(file, line, [self error]); +} +@end + +@implementation ICEConnectFailedException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::ConnectFailedException(file, line, [self error]); +} +@end + +@implementation ICEConnectionRefusedException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::ConnectionRefusedException(file, line, [self error]); +} +@end + +@implementation ICEConnectionLostException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::ConnectionLostException(file, line, [self error]); +} +@end + +@implementation ICEFileException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::FileException*>(&ex), @"invalid local exception type"); + const Ice::FileException& localEx = dynamic_cast<const Ice::FileException&>(ex); + path = toNSString(localEx.path); + return self; +} +-(void) rethrowCxx +{ + throw Ice::FileException(file, line, [self error], fromNSString(path)); +} +@end + +@implementation ICEDNSException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::DNSException*>(&ex), @"invalid local exception type"); + const Ice::DNSException& localEx = dynamic_cast<const Ice::DNSException&>(ex); + error = localEx.error; + host = toNSString(localEx.host); + return self; +} +-(void) rethrowCxx +{ + throw Ice::DNSException(file, line, [self error], fromNSString(host)); +} +@end + +@implementation ICETimeoutException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::TimeoutException(file, line); +} +@end + +@implementation ICEConnectTimeoutException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::ConnectTimeoutException(file, line); +} +@end + +@implementation ICECloseTimeoutException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::CloseTimeoutException(file, line); +} +@end + +@implementation ICEConnectionTimeoutException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::ConnectionTimeoutException(file, line); +} +@end + +@implementation ICEProtocolException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::ProtocolException*>(&ex), @"invalid local exception type"); + const Ice::ProtocolException& localEx = dynamic_cast<const Ice::ProtocolException&>(ex); + reason_ = toNSString(localEx.reason); + return self; +} +-(void) rethrowCxx +{ + throw Ice::ProtocolException(file, line, fromNSString(reason_)); +} +@end + +@implementation ICEUnknownMessageException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::UnknownMessageException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEConnectionNotValidatedException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::ConnectionNotValidatedException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEUnknownRequestIdException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::UnknownRequestIdException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEUnknownReplyStatusException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::UnknownReplyStatusException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICECloseConnectionException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::CloseConnectionException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEForcedCloseConnectionException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::ForcedCloseConnectionException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEIllegalMessageSizeException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::IllegalMessageSizeException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICECompressionException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::CompressionException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEDatagramLimitException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::DatagramLimitException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEMarshalException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::MarshalException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEProxyUnmarshalException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::ProxyUnmarshalException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEUnmarshalOutOfBoundsException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::UnmarshalOutOfBoundsException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEMemoryLimitException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::MemoryLimitException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEStringConversionException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::StringConversionException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEEncapsulationException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::EncapsulationException(file, line, fromNSString([self reason_])); +} +@end + +@implementation ICEBadMagicException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::BadMagicException*>(&ex), @"invalid local exception type"); + const Ice::BadMagicException& localEx = dynamic_cast<const Ice::BadMagicException&>(ex); + badMagic = toNSData(localEx.badMagic); + return self; +} +-(void) rethrowCxx +{ + Ice::ByteSeq s; + throw Ice::BadMagicException(file, line, fromNSString([self reason_]), fromNSData(badMagic, s)); +} +@end + +@implementation ICEUnsupportedProtocolException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::UnsupportedProtocolException*>(&ex), @"invalid local exception type"); + const Ice::UnsupportedProtocolException& localEx = dynamic_cast<const Ice::UnsupportedProtocolException&>(ex); + bad = [[ICEProtocolVersion protocolVersionWithProtocolVersion:localEx.bad] retain]; + supported = [[ICEProtocolVersion protocolVersionWithProtocolVersion:localEx.supported] retain]; + return self; +} +-(void) rethrowCxx +{ + Ice::ProtocolVersion badVersion = [bad protocolVersion]; + Ice::ProtocolVersion supportedVersion = [supported protocolVersion]; + throw Ice::UnsupportedProtocolException(file, line, fromNSString([self reason_]), badVersion, supportedVersion); +} +@end + +@implementation ICEUnsupportedEncodingException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::UnsupportedEncodingException*>(&ex), @"invalid local exception type"); + const Ice::UnsupportedEncodingException& localEx = dynamic_cast<const Ice::UnsupportedEncodingException&>(ex); + bad = [[ICEEncodingVersion encodingVersionWithEncodingVersion:localEx.bad] retain]; + supported = [[ICEEncodingVersion encodingVersionWithEncodingVersion:localEx.supported] retain]; + return self; +} +-(void) rethrowCxx +{ + Ice::EncodingVersion badVersion = [bad encodingVersion]; + Ice::EncodingVersion supportedVersion = [supported encodingVersion]; + throw Ice::UnsupportedEncodingException(file, line, fromNSString([self reason_]), badVersion, supportedVersion); +} +@end + +@implementation ICENoObjectFactoryException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::NoObjectFactoryException*>(&ex), @"invalid local exception type"); + const Ice::NoObjectFactoryException& localEx = dynamic_cast<const Ice::NoObjectFactoryException&>(ex); + type = toNSString(localEx.type); + return self; +} +-(void) rethrowCxx +{ + throw Ice::NoObjectFactoryException(file, line, fromNSString([self reason_]), fromNSString(type)); +} +@end + +@implementation ICEUnexpectedObjectException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::UnexpectedObjectException*>(&ex), @"invalid local exception type"); + const Ice::UnexpectedObjectException& localEx = dynamic_cast<const Ice::UnexpectedObjectException&>(ex); + type = toNSString(localEx.type); + expectedType = toNSString(localEx.expectedType); + return self; +} +-(void) rethrowCxx +{ + throw Ice::UnexpectedObjectException(file, line, fromNSString([self reason_]), fromNSString(type), fromNSString(expectedType)); +} +@end + +@implementation ICEFeatureNotSupportedException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::FeatureNotSupportedException*>(&ex), @"invalid local exception type"); + const Ice::FeatureNotSupportedException& localEx = dynamic_cast<const Ice::FeatureNotSupportedException&>(ex); + unsupportedFeature = toNSString(localEx.unsupportedFeature); + return self; +} +-(void) rethrowCxx +{ + throw Ice::FeatureNotSupportedException(file, line, fromNSString(unsupportedFeature)); +} +@end + +@implementation ICESecurityException (ICEInternal) +-(id)initWithLocalException:(const Ice::LocalException&)ex +{ + self = [super initWithLocalException:ex]; + if(!self) + { + return nil; + } + NSAssert(dynamic_cast<const Ice::SecurityException*>(&ex), @"invalid local exception type"); + const Ice::SecurityException& localEx = dynamic_cast<const Ice::SecurityException&>(ex); + reason_ = toNSString(localEx.reason); + return self; +} +-(void) rethrowCxx +{ + throw Ice::SecurityException(file, line, fromNSString(reason_)); +} +@end + +@implementation ICEFixedProxyException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::FixedProxyException(file, line); +} +@end + +@implementation ICEResponseSentException (ICEInternal) +-(void) rethrowCxx +{ + throw Ice::ResponseSentException(file, line); +} +@end diff --git a/objc/src/Ice/ExceptionI.h b/objc/src/Ice/ExceptionI.h new file mode 100644 index 00000000000..b65ca66cabf --- /dev/null +++ b/objc/src/Ice/ExceptionI.h @@ -0,0 +1,18 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Exception.h> + +#include <IceCpp/Exception.h> + +@interface ICELocalException () +-(id) initWithLocalException:(const Ice::LocalException&)ex; +-(void) rethrowCxx; ++(id) localExceptionWithLocalException:(const Ice::LocalException&)ex; +@end diff --git a/objc/src/Ice/IdentityI.h b/objc/src/Ice/IdentityI.h new file mode 100644 index 00000000000..2236c51d8b5 --- /dev/null +++ b/objc/src/Ice/IdentityI.h @@ -0,0 +1,18 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Identity.h> + +#include <IceCpp/Identity.h> + +@interface ICEIdentity (ICEInternal) +-(ICEIdentity*)initWithIdentity:(const Ice::Identity&)arg; +-(Ice::Identity)identity; ++(ICEIdentity*)identityWithIdentity:(const Ice::Identity&)arg; +@end diff --git a/objc/src/Ice/IdentityI.mm b/objc/src/Ice/IdentityI.mm new file mode 100644 index 00000000000..d8200de49a2 --- /dev/null +++ b/objc/src/Ice/IdentityI.mm @@ -0,0 +1,40 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <IdentityI.h> +#import <Util.h> + +@implementation ICEIdentity (ICEInternal) + +-(ICEIdentity*) initWithIdentity:(const Ice::Identity&)arg +{ + self = [super init]; + if(!self) + { + return nil; + } + category = [[NSString alloc] initWithUTF8String:arg.category.c_str()]; + name = [[NSString alloc] initWithUTF8String:arg.name.c_str()]; + return self; +} + +-(Ice::Identity) identity +{ + Ice::Identity ident; + ident.category = fromNSString(category); + ident.name = fromNSString(name); + return ident; +} + ++(ICEIdentity*) identityWithIdentity:(const Ice::Identity&)arg +{ + return [[[ICEIdentity alloc] initWithIdentity:arg] autorelease]; +} + +@end diff --git a/objc/src/Ice/ImplicitContext.mm b/objc/src/Ice/ImplicitContext.mm new file mode 100644 index 00000000000..689a081e981 --- /dev/null +++ b/objc/src/Ice/ImplicitContext.mm @@ -0,0 +1,83 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <ImplicitContextI.h> +#import <Util.h> + +@implementation ICEImplicitContext + +-(id) init:(Ice::ImplicitContext*)implicitContext +{ + self = [super init]; + if(self) + { + self->implicitContext__ = implicitContext; + self->implicitContext__->__incRef(); + } + return self; +} + ++(id) implicitContextWithImplicitContext:(Ice::ImplicitContext*)implicitContext +{ + if(!implicitContext) + { + return nil; + } + else + { + return [[[ICEImplicitContext alloc] init:implicitContext] autorelease]; + } +} + +-(void) dealloc +{ + self->implicitContext__->__decRef(); + [super dealloc]; +} + +-(ICEContext*) getContext +{ + return [toNSDictionary(implicitContext__->getContext()) autorelease]; +} + +-(void) setContext:(ICEContext*)context +{ + Ice::Context ctx; + fromNSDictionary(context, ctx); + implicitContext__->setContext(ctx); +} + +-(BOOL) containsKey:(NSString*)key +{ + return implicitContext__->containsKey(fromNSString(key)); +} + +-(NSString*) get:(NSString*)key +{ + if(implicitContext__->containsKey(fromNSString(key))) + { + return [toNSString(implicitContext__->get(fromNSString(key))) autorelease]; + } + else + { + return nil; + } +} + +-(NSString*) put:(NSString*)key value:(NSString*)value +{ + return [toNSString(implicitContext__->put(fromNSString(key), fromNSString(value))) autorelease]; +} + +-(NSString*) remove:(NSString*)key +{ + return [toNSString(implicitContext__->remove(fromNSString(key))) autorelease]; +} + +@end diff --git a/objc/src/Ice/ImplicitContextI.h b/objc/src/Ice/ImplicitContextI.h new file mode 100644 index 00000000000..a7566e1b9cd --- /dev/null +++ b/objc/src/Ice/ImplicitContextI.h @@ -0,0 +1,22 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/ImplicitContext.h> + +#include <IceCpp/ImplicitContext.h> + +@interface ICEImplicitContext : NSObject<ICEImplicitContext> +{ +@private + + Ice::ImplicitContext* implicitContext__; +} +-(id) init:(Ice::ImplicitContext*)implicitContext; ++(id) implicitContextWithImplicitContext:(Ice::ImplicitContext*)implicitContext; +@end diff --git a/objc/src/Ice/Initialize.mm b/objc/src/Ice/Initialize.mm new file mode 100644 index 00000000000..81956a161a2 --- /dev/null +++ b/objc/src/Ice/Initialize.mm @@ -0,0 +1,623 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <InitializeI.h> +#import <PropertiesI.h> +#import <CommunicatorI.h> +#import <StreamI.h> +#import <LoggerI.h> +#import <DispatcherI.h> +#import <Util.h> +#import <VersionI.h> + +#import <objc/Ice/LocalException.h> + +#include <IceCpp/Initialize.h> +#include <IceUtilCpp/UUID.h> +#include <IceUtilCpp/MutexPtrLock.h> + +#include <Availability.h> + +#import <Foundation/NSAutoreleasePool.h> +#import <Foundation/NSThread.h> + +#ifdef ICE_NO_KQUEUE +# define ICE_USE_CFSTREAM 1 +#endif + +namespace +{ +typedef std::map<int, std::string> CompactIdMap; + +IceUtil::Mutex* _compactIdMapMutex = 0; +CompactIdMap* _compactIdMap = 0; + +class CompactIdResolverI : public Ice::CompactIdResolver +{ +public: + + virtual ::std::string + resolve(::Ice::Int value) const + { + assert(_compactIdMapMutex); + assert(_compactIdMap); + + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_compactIdMapMutex); + CompactIdMap::iterator p = _compactIdMap->find(value); + if(p != _compactIdMap->end()) + { + return p->second; + } + return ::std::string(); + } +}; + +// +// We don't use the constructor to initialize the compactIdMap as +// static initializtion takes place after +load is called. +// +class Init +{ +public: + + ~Init() + { + if(_compactIdMap) + { + delete _compactIdMap; + _compactIdMap = 0; + } + + if(_compactIdMapMutex) + { + delete _compactIdMapMutex; + _compactIdMapMutex = 0; + } + } +}; +Init init; + +} + +@implementation CompactIdMapHelper ++(void) initialize +{ + assert(!_compactIdMapMutex); + assert(!_compactIdMap); + _compactIdMapMutex = new ::IceUtil::Mutex; + _compactIdMap = new CompactIdMap; +} + ++(void) registerClass:(NSString*)type value:(ICEInt)value +{ + assert(_compactIdMapMutex); + assert(_compactIdMap); + + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(_compactIdMapMutex); + CompactIdMap::iterator p = _compactIdMap->find(value); + if(p != _compactIdMap->end()) + { + _compactIdMap->erase(p); + } + _compactIdMap->insert(CompactIdMap::value_type(value, fromNSString(type))); +} +@end + +namespace IceObjC +{ + +class ThreadNotification : public Ice::ThreadNotification, public IceUtil::Mutex +{ +public: + + ThreadNotification() + { + } + + virtual void start() + { + Lock sync(*this); + _pools.insert(std::make_pair(IceUtil::ThreadControl().id(), [[NSAutoreleasePool alloc] init])); + } + + virtual void stop() + { + Lock sync(*this); + std::map<IceUtil::ThreadControl::ID, NSAutoreleasePool*>::iterator p = + _pools.find(IceUtil::ThreadControl().id()); + [p->second drain]; + _pools.erase(p); + } + +private: + + std::map<IceUtil::ThreadControl::ID, NSAutoreleasePool*> _pools; +}; + +}; + +@implementation ICEInitializationData (ICEInternal) +-(Ice::InitializationData)initializationData +{ + Ice::InitializationData data; + data.properties = [(ICEProperties*)properties properties]; + data.logger = [ICELogger loggerWithLogger:logger]; + if(dispatcher) + { + data.dispatcher = [ICEDispatcher dispatcherWithDispatcher:dispatcher]; + } + data.compactIdResolver = new CompactIdResolverI; + return data; +} +@end + +@implementation ICEInitializationData + +@synthesize properties; +@synthesize logger; +@synthesize dispatcher; +@synthesize prefixTable__; + +-(id) init:(id<ICEProperties>)props logger:(id<ICELogger>)log +dispatcher:(void(^)(id<ICEDispatcherCall>, id<ICEConnection>))d; +{ + self = [super init]; + if(!self) + { + return nil; + } + properties = [props retain]; + logger = [log retain]; + dispatcher = [d copy]; + return self; +} + ++(id) initializationData; +{ + ICEInitializationData *s = [[ICEInitializationData alloc] init]; + [s autorelease]; + return s; +} + ++(id) initializationData:(id<ICEProperties>)p logger:(id<ICELogger>)l + dispatcher:(void(^)(id<ICEDispatcherCall>, id<ICEConnection>))d; +{ + return [[((ICEInitializationData *)[ICEInitializationData alloc]) init:p logger:l dispatcher:d] autorelease]; +} + +-(id) copyWithZone:(NSZone *)zone +{ + ICEInitializationData *copy = [ICEInitializationData allocWithZone:zone]; + copy->properties = [properties retain]; + copy->logger = [logger retain]; + copy->dispatcher = [dispatcher copy]; + copy->prefixTable__ = [prefixTable__ retain]; + return copy; +} + +-(NSUInteger) hash; +{ + NSUInteger h = 0; + h = (h << 1 ^ [properties hash]); + h = (h << 1 ^ [logger hash]); + h = (h << 1 ^ [prefixTable__ hash]); + return h; +} + +-(BOOL) isEqual:(id)anObject; +{ + if(self == anObject) + { + return YES; + } + if(!anObject || ![anObject isKindOfClass:[self class]]) + { + return NO; + } + ICEInitializationData * obj =(ICEInitializationData *)anObject; + if(!properties) + { + if(obj->properties) + { + return NO; + } + } + else + { + if(![properties isEqual:obj->properties]) + { + return NO; + } + } + if(!logger) + { + if(obj->logger) + { + return NO; + } + } + else + { + if(![logger isEqual:obj->logger]) + { + return NO; + } + } + if(!dispatcher) + { + if(obj->dispatcher) + { + return NO; + } + } + else + { + if(dispatcher == obj->dispatcher) + { + return NO; + } + } + if(!prefixTable__) + { + if(obj->prefixTable__) + { + return NO; + } + } + else + { + if(![prefixTable__ isEqual:obj->prefixTable__]) + { + return NO; + } + } + return YES; +} + +-(void) dealloc; +{ + [properties release]; + [logger release]; + [dispatcher release]; + [prefixTable__ release]; + [super dealloc]; +} +@end + +@implementation ICEUtil ++(id<ICEProperties>) createProperties +{ + return [self createProperties:nil argv:nil]; +} + ++(id<ICEProperties>) createProperties:(int*)argc argv:(char*[])argv +{ + NSException* nsex = nil; + try + { + Ice::PropertiesPtr properties; + if(argc != nil && argv != nil) + { + properties = Ice::createProperties(*argc, argv); + } + else + { + properties = Ice::createProperties(); + } + return [ICEProperties wrapperWithCxxObject:properties.get()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + ++(id<ICECommunicator>) createCommunicator +{ + return [self createCommunicator:nil argv:nil initData:nil]; +} + ++(id<ICECommunicator>) createCommunicator:(ICEInitializationData*)initData +{ + return [self createCommunicator:nil argv:nil initData:initData]; +} + ++(id<ICECommunicator>) createCommunicator:(int*)argc argv:(char*[])argv +{ + return [self createCommunicator:argc argv:argv initData:nil]; +} + ++(id<ICECommunicator>) createCommunicator:(int*)argc argv:(char*[])argv initData:(ICEInitializationData*)initData +{ + if(![NSThread isMultiThreaded]) // Ensure sure Cocoa is multithreaded. + { + NSThread* thread = [[NSThread alloc] init]; + [thread start]; + [thread release]; + } + + id<ICEProperties> properties = [initData properties]; + if(properties != nil && ![properties isKindOfClass:[ICEProperties class]]) + { + @throw [ICEInitializationException initializationException:__FILE__ line:__LINE__ + reason_:@"properties were not created with createProperties"]; + } + + NSException* nsex = nil; + try + { + Ice::InitializationData data; + if(initData != nil) + { + data = [initData initializationData]; + } + data.threadHook = new IceObjC::ThreadNotification(); + if(!data.properties) + { + data.properties = Ice::createProperties(); + } + data.properties->setProperty("Ice.Default.CollocationOptimized", "0"); + + if(argc != nil && argv != nil) + { + data.properties = createProperties(*argc, argv, data.properties); + } + + Ice::CommunicatorPtr communicator; + if(argc != nil && argv != nil) + { + communicator = Ice::initialize(*argc, argv, data); + } + else + { + communicator = Ice::initialize(data); + } + + ICECommunicator* c = [ICECommunicator wrapperWithCxxObject:communicator.get()]; + [c setup:initData.prefixTable__]; + return c; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + ++(id<ICEInputStream>) createInputStream:(id<ICECommunicator>)communicator data:(NSData*)data +{ + NSException* nsex = nil; + try + { + Ice::CommunicatorPtr com = [(ICECommunicator*)communicator communicator]; + Ice::Byte* start = (Ice::Byte*)[data bytes]; + Ice::Byte* end = (Ice::Byte*)[data bytes] + [data length]; + Ice::InputStreamPtr is = Ice::createInputStream(com, std::make_pair(start, end)); + if(is) + { + return [ICEInputStream wrapperWithCxxObject:is.get()]; + } + else + { + return nil; + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + ++(id<ICEInputStream>) createInputStream:(id<ICECommunicator>)c data:(NSData*)data encoding:(ICEEncodingVersion*)e +{ + NSException* nsex = nil; + try + { + Ice::CommunicatorPtr com = [(ICECommunicator*)c communicator]; + Ice::Byte* start = (Ice::Byte*)[data bytes]; + Ice::Byte* end = (Ice::Byte*)[data bytes] + [data length]; + Ice::InputStreamPtr is = Ice::createInputStream(com, std::make_pair(start, end), [e encodingVersion]); + if(is) + { + return [ICEInputStream wrapperWithCxxObject:is.get()]; + } + else + { + return nil; + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + ++(id<ICEInputStream>) wrapInputStream:(id<ICECommunicator>)communicator data:(NSData*)data +{ + NSException* nsex = nil; + try + { + Ice::CommunicatorPtr com = [(ICECommunicator*)communicator communicator]; + Ice::Byte* start = (Ice::Byte*)[data bytes]; + Ice::Byte* end = (Ice::Byte*)[data bytes] + [data length]; + Ice::InputStreamPtr is = Ice::wrapInputStream(com, std::make_pair(start, end)); + if(is) + { + return [ICEInputStream wrapperWithCxxObject:is.get()]; + } + else + { + return nil; + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + ++(id<ICEInputStream>) wrapInputStream:(id<ICECommunicator>)c data:(NSData*)data encoding:(ICEEncodingVersion*)e +{ + NSException* nsex = nil; + try + { + Ice::CommunicatorPtr com = [(ICECommunicator*)c communicator]; + Ice::Byte* start = (Ice::Byte*)[data bytes]; + Ice::Byte* end = (Ice::Byte*)[data bytes] + [data length]; + Ice::InputStreamPtr is = Ice::wrapInputStream(com, std::make_pair(start, end), [e encodingVersion]); + if(is) + { + return [ICEInputStream wrapperWithCxxObject:is.get()]; + } + else + { + return nil; + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + ++(id<ICEOutputStream>) createOutputStream:(id<ICECommunicator>)communicator +{ + NSException* nsex = nil; + try + { + Ice::CommunicatorPtr com = [(ICECommunicator*)communicator communicator]; + Ice::OutputStreamPtr os = Ice::createOutputStream(com); + if(os) + { + return [ICEOutputStream wrapperWithCxxObject:os.get()]; + } + else + { + return nil; + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + ++(id<ICEOutputStream>) createOutputStream:(id<ICECommunicator>)communicator encoding:(ICEEncodingVersion*)encoding +{ + NSException* nsex = nil; + try + { + Ice::CommunicatorPtr com = [(ICECommunicator*)communicator communicator]; + Ice::OutputStreamPtr os = Ice::createOutputStream(com, [encoding encodingVersion]); + if(os) + { + return [ICEOutputStream wrapperWithCxxObject:os.get()]; + } + else + { + return nil; + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + ++(NSString*) generateUUID +{ + return [NSString stringWithUTF8String:IceUtil::generateUUID().c_str()]; +} + ++(NSArray*)argsToStringSeq:(int)argc argv:(char*[])argv +{ + NSMutableArray* ns = [NSMutableArray array]; + int i; + for(i = 0; i < argc; ++i) + { + [ns addObject:[NSString stringWithCString:argv[i] encoding:NSUTF8StringEncoding]]; + } + return [[ns copy] autorelease]; +} + ++(void)stringSeqToArgs:(NSArray*)args argc:(int*)argc argv:(char*[])argv; +{ + // + // Shift all elements in argv which are present in args to the + // beginning of argv. We record the original value of argc so + // that we can know later if we've shifted the array. + // + const int argcOrig = *argc; + int i = 0; + while(i < *argc) + { + BOOL found = NO; + for(NSString* s in args) + { + if([s compare:[NSString stringWithCString:argv[i] encoding:NSUTF8StringEncoding]] == 0) + { + found = YES; + break; + } + } + if(!found) + { + int j; + for(j = i; j < *argc - 1; j++) + { + argv[j] = argv[j + 1]; + } + --(*argc); + } + else + { + ++i; + } + } + + // + // Make sure that argv[*argc] == 0, the ISO C++ standard requires this. + // We can only do this if we've shifted the array, otherwise argv[*argc] + // may point to an invalid address. + // + if(argv && argcOrig != *argc) + { + argv[*argc] = 0; + } +} +@end + +@implementation ICEEncodingVersion(StringConv) ++(ICEEncodingVersion*) encodingVersionWithString:(NSString*)str +{ + return [ICEEncodingVersion encodingVersionWithEncodingVersion:Ice::stringToEncodingVersion(fromNSString(str))]; +} +@end + +@implementation ICEProtocolVersion(StringConv) ++(ICEProtocolVersion*) protocolVersionWithString:(NSString*)str +{ + return [ICEProtocolVersion protocolVersionWithProtocolVersion:Ice::stringToProtocolVersion(fromNSString(str))]; +} +@end diff --git a/objc/src/Ice/InitializeI.h b/objc/src/Ice/InitializeI.h new file mode 100644 index 00000000000..22fed8e692a --- /dev/null +++ b/objc/src/Ice/InitializeI.h @@ -0,0 +1,16 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Initialize.h> + +#include <IceCpp/Initialize.h> + +@interface ICEInitializationData (ICEInternal) +-(Ice::InitializationData)initializationData; +@end diff --git a/objc/src/Ice/Logger.mm b/objc/src/Ice/Logger.mm new file mode 100644 index 00000000000..804ea99edca --- /dev/null +++ b/objc/src/Ice/Logger.mm @@ -0,0 +1,194 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <LoggerI.h> +#import <Util.h> + +#import <Foundation/NSDate.h> + +namespace +{ + +class LoggerI : public Ice::Logger +{ +public: + +// We must explicitely CFRetain/CFRelease so that the garbage +// collector does not trash the logger. +LoggerI(id<ICELogger> logger) : _logger(logger) +{ + CFRetain(_logger); +} + +virtual ~LoggerI() +{ + CFRelease(_logger); +} + +virtual void +print(const std::string& msg) +{ + NSString* s = toNSString(msg); + @try + { + [_logger print:s]; + } + @catch(id ex) + { + rethrowCxxException(ex); + } + @finally + { + [s release]; + } +} + +virtual void +trace(const std::string& category, const std::string& msg) +{ + NSString* s1 = toNSString(category); + NSString* s2 = toNSString(msg); + @try + { + [_logger trace:s1 message:s2]; + } + @catch(id ex) + { + rethrowCxxException(ex); + } + @finally + { + [s1 release]; + [s2 release]; + } +} + +virtual void +warning(const std::string& msg) +{ + NSString* s = toNSString(msg); + @try + { + [_logger warning:s]; + } + @catch(id ex) + { + rethrowCxxException(ex); + } + @finally + { + [s release]; + } +} + +virtual void +error(const std::string& msg) +{ + NSString* s = toNSString(msg); + @try + { + [_logger error:s]; + } + @catch(id ex) + { + rethrowCxxException(ex); + } + @finally + { + [s release]; + } +} + +virtual Ice::LoggerPtr +cloneWithPrefix(const std::string& prefix) +{ + return this; +} + +virtual std::string +getPrefix() +{ + return fromNSString([_logger getPrefix]); +} + +id<ICELogger> +getLogger() +{ + return _logger; +} + +private: + +id<ICELogger> _logger; + +}; +typedef IceUtil::Handle<LoggerI> LoggerIPtr; + +} + +@implementation ICELogger ++(Ice::Logger*) loggerWithLogger:(id<ICELogger>)logger +{ + if(logger == 0) + { + id<ICELogger> l = [[self alloc] init]; + Ice::Logger* impl = new LoggerI(l); + [l release]; + return impl; + } + else + { + return new LoggerI(logger); + } +} ++(id) wrapperWithCxxObject:(IceUtil::Shared*)cxxObject +{ + LoggerI* impl = dynamic_cast<LoggerI*>(cxxObject); + assert(impl); + return [[impl->getLogger() retain] autorelease]; +} + +// +// @protocol Logger methods. +// + +-(void) print:(NSString*)message +{ + NSLog(@"%@", message); +} + +-(void) trace:(NSString*)category message:(NSString*)message +{ + NSMutableString* s = [[NSMutableString alloc] initWithFormat:@"[%@: %@]", category, message]; +#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR + [s replaceOccurrencesOfString:@"\n" withString:@" " options:0 range:NSMakeRange(0, s.length)]; +#endif + [self print:s]; + [s release]; +} + +-(void) warning:(NSString*)message +{ + NSString* s = [[NSString alloc] initWithFormat:@"warning: %@", message]; + [self print:s]; + [s release]; +} + +-(void) error:(NSString*)message +{ + NSString* s = [[NSString alloc] initWithFormat:@"error: %@", message]; + [self print:s]; + [s release]; +} + +-(NSString*) getPrefix +{ + return @""; +} +@end diff --git a/objc/src/Ice/LoggerI.h b/objc/src/Ice/LoggerI.h new file mode 100644 index 00000000000..d01e3490c42 --- /dev/null +++ b/objc/src/Ice/LoggerI.h @@ -0,0 +1,21 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Logger.h> + +#import <Wrapper.h> + +#include <IceCpp/Logger.h> + +@interface ICELogger : NSObject<ICELogger> +{ +} ++(Ice::Logger*)loggerWithLogger:(id<ICELogger>)arg; ++(id) wrapperWithCxxObject:(IceUtil::Shared*)cxxObject; +@end diff --git a/objc/src/Ice/Makefile b/objc/src/Ice/Makefile new file mode 100644 index 00000000000..c3c88356e95 --- /dev/null +++ b/objc/src/Ice/Makefile @@ -0,0 +1,140 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +LIBFILENAME = $(call mklibfilename,IceObjC$(libsuffix),$(VERSION)) +SONAME = $(call mksoname,IceObjC$(libsuffix),$(SOVERSION)) +LIBNAME = $(call mklibname,IceObjC$(libsuffix)) + +TARGETS = $(call mklibtargets,$(libdir)/$(LIBFILENAME),$(libdir)/$(SONAME),$(libdir)/$(LIBNAME)) + +SLICE_OBJS = BuiltinSequences.o \ + Identity.o \ + Locator.o \ + LocatorF.o \ + LocalException.o \ + Metrics.o \ + Process.o \ + ProcessF.o \ + PropertiesAdmin.o \ + RemoteLogger.o \ + Router.o \ + RouterF.o \ + SliceChecksumDict.o \ + Version.o + +OBJC_OBJS = DispatchInterceptor.o \ + Request.o \ + $(SLICE_OBJS) + +OBJCXX_OBJS = Communicator.o \ + Connection.o \ + Current.o \ + Exception.o \ + Dispatcher.o \ + IdentityI.o \ + Initialize.o \ + Logger.o \ + Object.o \ + ObjectAdapter.o \ + Properties.o \ + Proxy.o \ + Stream.o \ + SlicedData.o \ + Util.o \ + VersionI.o \ + Wrapper.o \ + ImplicitContext.o \ + Endpoint.o + +OBJS := $(OBJC_OBJS) $(OBJCXX_OBJS) + +HDIR = $(includedir)/objc/Ice +SDIR = $(slicedir)/Ice + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -Iinclude $(CPPFLAGS) +SLICE2OBJCFLAGS := --ice --include-dir objc/Ice $(SLICE2OBJCFLAGS) +DEPENDFLAGS = --obj-dir +LINKWITH := $(BASELIBS) + +ifeq ($(wildcard .depend/*.d),) + +ice_cpp_include = $(ice_cpp_dir)/include + +$(OBJCXX_OBJS:.o=.mm): \ + $(patsubst $(ice_cpp_include)/IceUtil/%.h,include/IceUtilCpp/%.h,$(wildcard $(ice_cpp_include)/IceUtil/*.h)) \ + $(patsubst $(ice_cpp_include)/Ice/%.h,include/IceCpp/%.h,$(wildcard $(ice_cpp_include)/Ice/*.h)) \ + $(patsubst $(ice_cpp_include)/IceSSL/%.h,include/IceSSLCpp/%.h,$(wildcard $(ice_cpp_include)/IceSSL/*.h)) + +include/IceUtilCpp/%.h: $(ice_cpp_include)/IceUtil/%.h + @echo Creating $@ from $< + @mkdir -p include/IceUtilCpp + @sed -e "s%IceUtil/%IceUtilCpp/%g" $< > $@ + +include/IceCpp/%.h: $(ice_cpp_include)/Ice/%.h + @echo Creating $@ from $< + @mkdir -p include/IceCpp + @sed -e "s%IceUtil/%IceUtilCpp/%g;s%Ice/%IceCpp/%g" $< > $@ + +include/IceSSLCpp/%.h: $(ice_cpp_include)/IceSSL/%.h + @echo Creating $@ from $< + @mkdir -p include/IceSSLCpp + @sed -e "s%IceUtil/%IceUtilCpp/%g;s%Ice/%IceCpp/%g;s%IceSSL/%IceSSLCpp/%g" $< > $@ + +endif + +$(libdir)/$(LIBFILENAME): $(OBJS) + rm -f $@ + $(call mkshlib,$@,$(SONAME),$(OBJS),$(LINKWITH)) + +$(libdir)/$(SONAME): $(libdir)/$(LIBFILENAME) + rm -f $@ + ln -s $(LIBFILENAME) $@ + +$(libdir)/$(LIBNAME): $(libdir)/$(SONAME) + rm -f $@ + ln -s $(SONAME) $@ + +# Prevent generation of these files from .ice files + +$(HDIR)/ImplicitContext.h ImplicitContext.m: + @echo + +$(HDIR)/Communicator.h Communicator.m: + @echo + +$(HDIR)/Current.h Current.m: + @echo + +$(HDIR)/Logger.h Logger.m: + @echo + +$(HDIR)/ObjectAdapter.h ObjectAdapter.m: + @echo + +$(HDIR)/Properties.h Properties.m: + @echo + +$(HDIR)/Endpoint.h Endpoint.m: + @echo + +$(HDIR)/Connection.h Connection.m: + @echo + +$(HDIR)/ObjectFactory.h ObjectFactory.m: + @echo + +install:: all + $(call installlib,$(install_libdir),$(libdir),$(LIBFILENAME),$(SONAME),$(LIBNAME)) + +clean:: + rm -rf include diff --git a/objc/src/Ice/Object.mm b/objc/src/Ice/Object.mm new file mode 100644 index 00000000000..cd2b7704fed --- /dev/null +++ b/objc/src/Ice/Object.mm @@ -0,0 +1,567 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <ObjectI.h> +#import <StreamI.h> +#import <CurrentI.h> +#import <Util.h> +#import <Request.h> + +#import <objc/Ice/LocalException.h> + +#include <IceCpp/Object.h> +#include <IceCpp/IncomingAsync.h> +#include <IceCpp/Initialize.h> +#include <IceCpp/ObjectAdapter.h> + +#import <Foundation/NSAutoreleasePool.h> + +int +ICEInternalLookupString(NSString* const array[], size_t count, NSString* __unsafe_unretained str) +{ + size_t low = 0; + size_t high = count - 1; + while(low <= high) + { + size_t mid = (low + high) / 2; + switch([array[mid] compare:str]) + { + case NSOrderedDescending: + if(mid == 0) + { + return -1; + } + high = mid - 1; + break; + case NSOrderedAscending: + low = mid + 1; + break; + case NSOrderedSame: + return mid; + default: + return -1; // Can't be reached + } + } + return -1; +} + +static NSString* +operationModeToString(ICEOperationMode mode) +{ + switch(mode) + { + case ICENormal: + return @"::Ice::Normal"; + + case ICENonmutating: + return @"::Ice::Nonmutating"; + + case ICEIdempotent: + return @"::Ice::Idempotent"; + + default: + return [NSString stringWithFormat:@"unknown value(%d)", mode]; + } +} + +void +ICEInternalCheckModeAndSelector(id target, ICEOperationMode expected, SEL sel, ICECurrent* current) +{ + ICEOperationMode received = current.mode; + if(expected != received) + { + if(expected == ICEIdempotent && received == ICENonmutating) + { + // + // Fine: typically an old client still using the deprecated nonmutating keyword + // + + // + // Note that expected == Nonmutating and received == Idempotent is not ok: + // the server may still use the deprecated nonmutating keyword to detect updates + // and the client should not break this (deprecated) feature. + // + } + else + { + ICEMarshalException* ex = [ICEMarshalException marshalException:__FILE__ line:__LINE__]; + [ex setReason_:[NSString stringWithFormat:@"unexpected operation mode. expected = %@ received=%@", + operationModeToString(expected), operationModeToString(received)]]; + @throw ex; + } + } + + if(![target respondsToSelector:sel]) + { + @throw [ICEOperationNotExistException operationNotExistException:__FILE__ + line:__LINE__ + id_:current.id_ + facet:current.facet + operation:current.operation]; + } +} + +namespace IceObjC +{ + +class ObjectI : public ObjectWrapper, public Ice::BlobjectArrayAsync +{ +public: + + ObjectI(id<ICEObject>); + + virtual void ice_invoke_async(const Ice::AMD_Object_ice_invokePtr&, + const std::pair<const Ice::Byte*, const Ice::Byte*>&, + const Ice::Current&); + + virtual ICEObject* getObject() + { + return _object; + } + + // We must explicitely CFRetain/CFRelease so that the garbage + // collector does not trash the _object. + virtual void __incRef() + { + CFRetain(_object); + } + + virtual void __decRef() + { + CFRelease(_object); + } + +private: + + ICEObject* _object; +}; + +class BlobjectI : public ObjectWrapper, public Ice::BlobjectArrayAsync +{ +public: + + BlobjectI(ICEBlobject*); + + virtual void ice_invoke_async(const Ice::AMD_Object_ice_invokePtr&, + const std::pair<const Ice::Byte*, const Ice::Byte*>&, + const Ice::Current&); + + virtual ICEObject* getObject() + { + return _blobject; + } + + // We must explicitely CFRetain/CFRelease so that the garbage + // collector does not trash the _blobject. + virtual void __incRef() + { + CFRetain(_blobject); + } + + virtual void __decRef() + { + CFRelease(_blobject); + } + +private: + + ICEBlobject* _blobject; + id _target; +}; + +} + +IceObjC::ObjectI::ObjectI(id<ICEObject> object) : _object((ICEObject*)object) +{ +} + +void +IceObjC::ObjectI::ice_invoke_async(const Ice::AMD_Object_ice_invokePtr& cb, + const std::pair<const Ice::Byte*, const Ice::Byte*>& inParams, + const Ice::Current& current) +{ + ICEInputStream* is = nil; + ICEOutputStream* os = nil; + { + Ice::InputStreamPtr s = Ice::createInputStream(current.adapter->getCommunicator(), inParams); + is = [ICEInputStream wrapperWithCxxObjectNoAutoRelease:s.get()]; + } + { + Ice::OutputStreamPtr s = Ice::createOutputStream(current.adapter->getCommunicator()); + os = [ICEOutputStream wrapperWithCxxObjectNoAutoRelease:s.get()]; + } + + NSException* exception = nil; + BOOL ok = YES; // Keep the compiler happy + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + ICECurrent* c = [[ICECurrent alloc] initWithCurrent:current]; + @try + { + ok = [_object dispatch__:c is:is os:os]; + } + @catch(id ex) + { + exception = [ex retain]; + } + @finally + { + [c release]; + [is release]; + [pool drain]; + } + + if(exception != nil) + { + [os release]; + rethrowCxxException(exception, true); // True = release the exception. + } + + std::vector<Ice::Byte> outParams; + [os os]->finished(outParams); + [os release]; + + cb->ice_response(ok, std::make_pair(&outParams[0], &outParams[0] + outParams.size())); +} + +IceObjC::BlobjectI::BlobjectI(ICEBlobject* blobject) : _blobject(blobject), _target([blobject target__]) +{ +} + +void +IceObjC::BlobjectI::ice_invoke_async(const Ice::AMD_Object_ice_invokePtr& cb, + const std::pair<const Ice::Byte*, const Ice::Byte*>& inEncaps, + const Ice::Current& current) +{ + NSException* exception = nil; + BOOL ok = YES; // Keep the compiler happy. + NSMutableData* outE = nil; + + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + ICECurrent* c = [[ICECurrent alloc] initWithCurrent:current]; + NSData* inE = [NSData dataWithBytesNoCopy:const_cast<Ice::Byte*>(inEncaps.first) + length:(inEncaps.second - inEncaps.first) + freeWhenDone:NO]; + @try + { + ok = [_target ice_invoke:inE outEncaps:&outE current:c]; + [outE retain]; + } + @catch(id ex) + { + exception = [ex retain]; + } + @finally + { + [c release]; + [pool drain]; + } + + if(exception != nil) + { + rethrowCxxException(exception, true); // True = release the exception. + } + + cb->ice_response(ok, std::make_pair((ICEByte*)[outE bytes], (ICEByte*)[outE bytes] + [outE length])); + [outE release]; +} + +@implementation ICEInternalPrefixTable +@end + +@implementation ICEObject (ICEInternal) + +-(id)init +{ + self = [super init]; + if(!self) + { + return nil; + } + object__ = 0; + delegate__ = 0; + return self; +} + +-(Ice::Object*) object__ +{ + @synchronized([self class]) + { + if(object__ == 0) + { + // + // NOTE: IceObjC::ObjectI implements it own reference counting and there's no need + // to call __incRef/__decRef here. The C++ object and Objective-C object are sharing + // the same reference count (the one of the Objective-C object). This is necessary + // to properly release both objects when there's either no more C++ handle/ObjC + // reference to the object (without this, servants added to the object adapter + // couldn't be retained or released easily). + // + object__ = (IceObjC::ObjectWrapper*)new IceObjC::ObjectI(self); + } + } + return (IceObjC::ObjectWrapper*)object__; +} + +-(void) dealloc +{ + if(object__) + { + delete (IceObjC::ObjectWrapper*)object__; + object__ = 0; + } + [delegate__ release]; + [super dealloc]; +} + +-(void) finalize +{ + if(object__) + { + delete (IceObjC::ObjectWrapper*)object__; + object__ = 0; + } + [super finalize]; +} + +@end + +@implementation ICEObject + +static NSString* ICEObject_ids__[1] = +{ + @"::Ice::Object" +}; + +static NSString* ICEObject_all__[4] = +{ + @"ice_id", + @"ice_ids", + @"ice_isA", + @"ice_ping" +}; + +-(id)initWithDelegate:(id)delegate +{ + self = [super init]; + if(!self) + { + return nil; + } + + object__ = 0; + delegate__ = [delegate retain]; + return self; +} + ++(id)objectWithDelegate:(id)delegate +{ + return [[[ICEObject alloc] initWithDelegate:delegate] autorelease]; +} + ++(BOOL) ice_isA___:(id)servant current:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os +{ + ICEEncodingVersion* encoding = [is startEncapsulation]; + NSString* id__ = [is readString]; + [is endEncapsulation]; + [os startEncapsulation:encoding format:ICEDefaultFormat]; + BOOL ret__ = [servant ice_isA:id__ current:current]; + [os writeBool:ret__]; + [os endEncapsulation]; + return YES; +} + ++(BOOL) ice_ping___:(id)servant current:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os +{ + ICEEncodingVersion* encoding = [is startEncapsulation]; + [is endEncapsulation]; + [os startEncapsulation:encoding format:ICEDefaultFormat]; + [servant ice_ping:current]; + [os endEncapsulation]; + return YES; +} + ++(BOOL) ice_id___:(id)servant current:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os +{ + ICEEncodingVersion* encoding = [is startEncapsulation]; + [is endEncapsulation]; + [os startEncapsulation:encoding format:ICEDefaultFormat]; + NSString* ret__ = [servant ice_id:current]; + [os writeString:ret__]; + [os endEncapsulation]; + return YES; +} + ++(BOOL) ice_ids___:(id)servant current:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os +{ + ICEEncodingVersion* encoding = [is startEncapsulation]; + [is endEncapsulation]; + [os startEncapsulation:encoding format:ICEDefaultFormat]; + NSArray* ret__ = [servant ice_ids:current]; + [os writeStringSeq:ret__]; + [os endEncapsulation]; + return YES; +} + +-(BOOL) ice_isA:(NSString*)typeId +{ + return [self ice_isA:typeId current:nil]; +} + +-(BOOL) ice_isA:(NSString*)typeId current:(ICECurrent*)current +{ + int count, index; + NSString*const* staticIds = [[self class] staticIds__:&count idIndex:&index]; + return ICEInternalLookupString(staticIds, count, typeId) >= 0; +} + +-(void) ice_ping +{ + [self ice_ping:nil]; +} + +-(void) ice_ping:(ICECurrent*)current +{ + // Nothing to do. +} + +-(NSString*) ice_id +{ + return [self ice_id:nil]; +} + +-(NSString*) ice_id:(ICECurrent*)current +{ + return [[self class] ice_staticId]; +} + +-(NSArray*) ice_ids +{ + return [self ice_ids:nil]; +} + +-(NSArray*) ice_ids:(ICECurrent*)current +{ + int count, index; + NSString*const* staticIds = [[self class] staticIds__:&count idIndex:&index]; + return [NSArray arrayWithObjects:staticIds count:count]; +} + ++(NSString*) ice_staticId +{ + int count, index; + NSString*const* staticIds = [self staticIds__:&count idIndex:&index]; + return staticIds[index]; +} + +-(void) ice_preMarshal +{ +} + +-(void) ice_postUnmarshal +{ +} + ++(NSString*const*) staticIds__:(int*)count idIndex:(int*)idx +{ + *count = sizeof(ICEObject_ids__) / sizeof(NSString*); + *idx = 0; + return ICEObject_ids__; +} + +-(BOOL) ice_dispatch:(id<ICERequest>)request +{ + @try + { + ICERequest* requestI = (ICERequest*)request; + return [requestI callDispatch:self]; + } + @catch(ICELocalException*) + { + @throw; + } + return FALSE; +} + +-(BOOL) dispatch__:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os +{ + switch(ICEInternalLookupString(ICEObject_all__, sizeof(ICEObject_all__) / sizeof(NSString*), current.operation)) + { + case 0: + return [ICEObject ice_id___:self current:current is:is os:os]; + case 1: + return [ICEObject ice_ids___:self current:current is:is os:os]; + case 2: + return [ICEObject ice_isA___:self current:current is:is os:os]; + case 3: + return [ICEObject ice_ping___:self current:current is:is os:os]; + default: + @throw [ICEOperationNotExistException requestFailedException:__FILE__ + line:__LINE__ + id_:current.id_ + facet:current.facet + operation:current.operation]; + } +} + +-(void) write__:(id<ICEOutputStream>)os +{ + [os startObject:nil]; + [self writeImpl__:os]; + [os endObject]; +} + +-(void) read__:(id<ICEInputStream>)is +{ + [is startObject]; + [self readImpl__:is]; + [is endObject:NO]; +} + +-(void) writeImpl__:(id<ICEOutputStream>)os +{ + NSAssert(NO, @"writeImpl__ requires override"); +} + +-(void) readImpl__:(id<ICEInputStream>)is +{ + NSAssert(NO, @"readImpl__ requires override"); +} + +-(id) copyWithZone:(NSZone*)zone +{ + return [[[self class] allocWithZone:zone] init]; +} + +-(id)target__ +{ + return (delegate__ == 0) ? self : delegate__; +} +@end + +@implementation ICEBlobject +-(Ice::Object*) object__ +{ + @synchronized([self class]) + { + if(object__ == 0) + { + // + // NOTE: IceObjC::ObjectI implements it own reference counting and there's no need + // to call __incRef/__decRef here. The C++ object and Objective-C object are sharing + // the same reference count (the one of the Objective-C object). This is necessary + // to properly release both objects when there's either no more C++ handle/ObjC + // reference to the object (without this, servants added to the object adapter + // couldn't be retained or released easily). + // + object__ = (IceObjC::ObjectWrapper*)new IceObjC::BlobjectI(self); + } + } + return (IceObjC::ObjectWrapper*)object__; +} +@end diff --git a/objc/src/Ice/ObjectAdapter.mm b/objc/src/Ice/ObjectAdapter.mm new file mode 100644 index 00000000000..89282d4312d --- /dev/null +++ b/objc/src/Ice/ObjectAdapter.mm @@ -0,0 +1,565 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <ObjectAdapterI.h> +#import <CommunicatorI.h> +#import <ProxyI.h> +#import <IdentityI.h> +#import <ObjectI.h> +#import <Util.h> + +#include <IceCpp/Locator.h> +#include <IceCpp/ServantLocator.h> + +namespace +{ +class DefaultServantLocator : public Ice::ServantLocator +{ +public: + + DefaultServantLocator(const Ice::ObjectPtr& s) : + _servant(s) + { + } + + virtual Ice::ObjectPtr + locate(const Ice::Current&, Ice::LocalObjectPtr&) + { + return _servant; + } + + virtual void + finished(const Ice::Current&, const Ice::ObjectPtr&, const Ice::LocalObjectPtr&) + { + } + + virtual void + deactivate(const std::string&) + { + } + + const Ice::ObjectPtr& + servant() const + { + return _servant; + } + +private: + Ice::ObjectPtr _servant; +}; +} + +#define OBJECTADAPTER dynamic_cast<Ice::ObjectAdapter*>(static_cast<IceUtil::Shared*>(cxxObject_)) + +@implementation ICEObjectAdapter +-(Ice::ObjectAdapter*) adapter +{ + return OBJECTADAPTER; +} +// +// @protocol ICEObjectAdapter methods. +// + +-(id<ICECommunicator>) getCommunicator +{ + NSException* nsex = nil; + try + { + return [ICECommunicator wrapperWithCxxObject:OBJECTADAPTER->getCommunicator().get()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(NSString*) getName +{ + NSException* nsex = nil; + try + { + return [toNSString(OBJECTADAPTER->getName()) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(void) activate +{ + NSException* nsex = nil; + try + { + OBJECTADAPTER->activate(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) hold +{ + NSException* nsex = nil; + try + { + OBJECTADAPTER->hold(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) waitForHold +{ + NSException* nsex = nil; + try + { + OBJECTADAPTER->waitForHold(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) deactivate +{ + NSException* nsex = nil; + try + { + OBJECTADAPTER->deactivate(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) waitForDeactivate +{ + NSException* nsex = nil; + try + { + OBJECTADAPTER->waitForDeactivate(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(BOOL) isDeactivated +{ + NSException* nsex = nil; + try + { + return OBJECTADAPTER->isDeactivated(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return NO; // Keep the compiler happy. +} + +-(void) destroy +{ + NSException* nsex = nil; + try + { + OBJECTADAPTER->destroy(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(id<ICEObjectPrx>) add:(ICEObject*)servant identity:(ICEIdentity*)ident +{ + NSException* nsex = nil; + try + { + return [ICEObjectPrx objectPrxWithObjectPrx__:OBJECTADAPTER->add([servant object__], [ident identity])]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICEObjectPrx>) addFacet:(ICEObject*)servant identity:(ICEIdentity*)ident facet:(NSString*)facet +{ + NSException* nsex = nil; + try + { + return [ICEObjectPrx objectPrxWithObjectPrx__:OBJECTADAPTER->addFacet([servant object__], [ident identity], + fromNSString(facet))]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICEObjectPrx>) addWithUUID:(ICEObject*)servant +{ + NSException* nsex = nil; + try + { + return [ICEObjectPrx objectPrxWithObjectPrx__:OBJECTADAPTER->addWithUUID([servant object__])]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICEObjectPrx>) addFacetWithUUID:(ICEObject*)servant facet:(NSString*)facet +{ + NSException* nsex = nil; + try + { + return [ICEObjectPrx objectPrxWithObjectPrx__:OBJECTADAPTER->addFacetWithUUID([servant object__], + fromNSString(facet))]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(void) addDefaultServant:(ICEObject*)servant category:(NSString*)category +{ + NSException* nsex = nil; + try + { + Ice::ServantLocatorPtr servantLocator = new DefaultServantLocator([servant object__]); + OBJECTADAPTER->addServantLocator(servantLocator, fromNSString(category)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(ICEObject*) remove:(ICEIdentity*)ident +{ + NSException* nsex = nil; + try + { + Ice::ObjectPtr wrapper = OBJECTADAPTER->remove([ident identity]); + return [[IceObjC::ObjectWrapperPtr::dynamicCast(wrapper)->getObject() retain] autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(ICEObject*) removeFacet:(ICEIdentity*)ident facet:(NSString*)facet +{ + NSException* nsex = nil; + try + { + Ice::ObjectPtr wrapper = OBJECTADAPTER->removeFacet([ident identity], fromNSString(facet)); + return [[IceObjC::ObjectWrapperPtr::dynamicCast(wrapper)->getObject() retain] autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(NSDictionary*) removeAllFacets:(ICEIdentity*)ident +{ + NSException* nsex = nil; + try + { + Ice::FacetMap wrappers = OBJECTADAPTER->removeAllFacets([ident identity]); + NSMutableDictionary* servants = [[[NSMutableDictionary alloc] initWithCapacity:wrappers.size()] autorelease]; + for(Ice::FacetMap::const_iterator p = wrappers.begin(); p != wrappers.end(); ++p) + { + NSObject<NSCopying>* key = toObjC(p->first); + [servants setObject:IceObjC::ObjectWrapperPtr::dynamicCast(p->second)->getObject() forKey:key]; + [key release]; + } + return servants; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICEObject*) find:(ICEIdentity*)ident +{ + NSException* nsex = nil; + try + { + Ice::ObjectPtr wrapper = OBJECTADAPTER->find([ident identity]); + return [[IceObjC::ObjectWrapperPtr::dynamicCast(wrapper)->getObject() retain] autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICEObject*) findFacet:(ICEIdentity*)ident facet:(NSString*)facet +{ + NSException* nsex = nil; + try + { + Ice::ObjectPtr wrapper = OBJECTADAPTER->findFacet([ident identity], fromNSString(facet)); + return [[IceObjC::ObjectWrapperPtr::dynamicCast(wrapper)->getObject() retain] autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(NSDictionary*) findAllFacets:(ICEIdentity*)ident +{ + NSException* nsex = nil; + try + { + Ice::FacetMap wrappers = OBJECTADAPTER->findAllFacets([ident identity]); + NSMutableDictionary* servants = [[[NSMutableDictionary alloc] initWithCapacity:wrappers.size()] autorelease]; + for(Ice::FacetMap::const_iterator p = wrappers.begin(); p != wrappers.end(); ++p) + { + NSObject<NSCopying>* key = toObjC(p->first); + [servants setObject:IceObjC::ObjectWrapperPtr::dynamicCast(p->second)->getObject() forKey:key]; + [key release]; + } + return servants; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICEObject*) findByProxy:(id<ICEObjectPrx>)proxy +{ + NSException* nsex = nil; + try + { + Ice::ObjectPtr wrapper = OBJECTADAPTER->findByProxy([(ICEObjectPrx*)proxy objectPrx__]); + return [[IceObjC::ObjectWrapperPtr::dynamicCast(wrapper)->getObject() retain] autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICEObject*) findDefaultServant:(NSString*)category +{ + NSException* nsex = nil; + try + { + Ice::ServantLocatorPtr servantLocator = OBJECTADAPTER->findServantLocator(fromNSString(category)); + if(servantLocator == 0) + { + return nil; + } + DefaultServantLocator* defaultServantLocator = dynamic_cast<DefaultServantLocator*>(servantLocator.get()); + if(defaultServantLocator == 0) + { + return nil; // should never happen! + } + else + { + Ice::ObjectPtr wrapper = defaultServantLocator->servant(); + return [[IceObjC::ObjectWrapperPtr::dynamicCast(wrapper)->getObject() retain] autorelease]; + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICEObjectPrx>) createProxy:(ICEIdentity*)ident +{ + NSException* nsex = nil; + try + { + return [ICEObjectPrx objectPrxWithObjectPrx__:OBJECTADAPTER->createProxy([ident identity])]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICEObjectPrx>) createDirectProxy:(ICEIdentity*)ident +{ + NSException* nsex = nil; + try + { + return [ICEObjectPrx objectPrxWithObjectPrx__:OBJECTADAPTER->createDirectProxy([ident identity])]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(id<ICEObjectPrx>) createIndirectProxy:(ICEIdentity*)ident +{ + NSException* nsex = nil; + try + { + return [ICEObjectPrx objectPrxWithObjectPrx__:OBJECTADAPTER->createIndirectProxy([ident identity])]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(void) setLocator:(id<ICELocatorPrx>)loc +{ + NSException* nsex = nil; + try + { + OBJECTADAPTER->setLocator(Ice::LocatorPrx::uncheckedCast(Ice::ObjectPrx([(ICEObjectPrx*)loc objectPrx__]))); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) refreshPublishedEndpoints +{ + NSException* nsex = nil; + try + { + OBJECTADAPTER->refreshPublishedEndpoints(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(ICEEndpointSeq*) getEndpoints +{ + NSException* nsex = nil; + try + { + return [toNSArray(OBJECTADAPTER->getEndpoints()) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return nil; +} + +-(ICEEndpointSeq*) getPublishedEndpoints +{ + NSException* nsex = nil; + try + { + return [toNSArray(OBJECTADAPTER->getPublishedEndpoints()) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return nil; +} + +@end diff --git a/objc/src/Ice/ObjectAdapterI.h b/objc/src/Ice/ObjectAdapterI.h new file mode 100644 index 00000000000..1711cfd6958 --- /dev/null +++ b/objc/src/Ice/ObjectAdapterI.h @@ -0,0 +1,21 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/ObjectAdapter.h> + +#import <Wrapper.h> + +#include <IceCpp/ObjectAdapter.h> + +@class ICECommunicator; + +@interface ICEObjectAdapter : ICEInternalWrapper<ICEObjectAdapter> +-(Ice::ObjectAdapter*) adapter; +@end + diff --git a/objc/src/Ice/ObjectI.h b/objc/src/Ice/ObjectI.h new file mode 100644 index 00000000000..e882c5eb8e5 --- /dev/null +++ b/objc/src/Ice/ObjectI.h @@ -0,0 +1,37 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Object.h> + +#include <IceCpp/Object.h> + +// +// Forward declarations. +// +@class ICECurrent; +@class ICEInputStream; +@class ICEOutputStream; + +namespace IceObjC +{ + +class ObjectWrapper : virtual public Ice::Object +{ +public: + + virtual ~ObjectWrapper() { } + virtual ICEObject* getObject() = 0; +}; +typedef IceUtil::Handle<ObjectWrapper> ObjectWrapperPtr; + +}; + +@interface ICEObject (ICEInternal) +-(Ice::Object*) object__; +@end diff --git a/objc/src/Ice/Properties.mm b/objc/src/Ice/Properties.mm new file mode 100644 index 00000000000..7713ea9e6bc --- /dev/null +++ b/objc/src/Ice/Properties.mm @@ -0,0 +1,304 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <PropertiesI.h> +#import <Util.h> + +@implementation ICEProperties +-(id) initWithCxxObject:(IceUtil::Shared*)cxxObject +{ + self = [super initWithCxxObject:cxxObject]; + if(!self) + { + return nil; + } + properties_ = dynamic_cast<Ice::Properties*>(cxxObject); + return self; +} +-(Ice::Properties*) properties +{ + return (Ice::Properties*)properties_; +} + +// @protocol ICEProperties methods. + +-(NSString*) getProperty:(NSString*)key +{ + NSException* nsex = nil; + try + { + return [toNSString(properties_->getProperty(fromNSString(key))) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(NSString*) getPropertyWithDefault:(NSString*)key value:(NSString*)value +{ + NSException* nsex = nil; + try + { + return [toNSString(properties_->getPropertyWithDefault(fromNSString(key), fromNSString(value))) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(int) getPropertyAsInt:(NSString*)key +{ + NSException* nsex = nil; + try + { + return properties_->getPropertyAsInt(fromNSString(key)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return 0; // Keep the compiler happy. +} +-(int) getPropertyAsIntWithDefault:(NSString*)key value:(int)value +{ + NSException* nsex = nil; + try + { + return properties_->getPropertyAsIntWithDefault(fromNSString(key), value); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return 0; // Keep the compiler happy. +} +-(NSArray*) getPropertyAsList:(NSString*)key +{ + NSException* nsex = nil; + try + { + return [toNSArray(properties_->getPropertyAsList(fromNSString(key))) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(NSArray*) getPropertyAsListWithDefault:(NSString*)key value:(NSArray*)value +{ + NSException* nsex = nil; + try + { + std::vector<std::string> s; + fromNSArray(value, s); + return [toNSArray(properties_->getPropertyAsListWithDefault(fromNSString(key), s)) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(NSDictionary*) getPropertiesForPrefix:(NSString*)prefix +{ + NSException* nsex = nil; + try + { + return [toNSDictionary(properties_->getPropertiesForPrefix(fromNSString(prefix))) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(void) setProperty:(NSString*)key value:(NSString*)value +{ + NSException* nsex = nil; + try + { + properties_->setProperty(fromNSString(key), fromNSString(value)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} +-(NSArray*) getCommandLineOptions +{ + NSException* nsex = nil; + try + { + return [toNSArray(properties_->getCommandLineOptions()) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(NSArray*) parseCommandLineOptions:(NSString*)prefix options:(NSArray*)options +{ + NSException* nsex = nil; + try + { + std::vector<std::string> o; + fromNSArray(options, o); + return [toNSArray(properties_->parseCommandLineOptions(fromNSString(prefix), o)) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(NSArray*) parseIceCommandLineOptions:(NSArray*)options +{ + NSException* nsex = nil; + try + { + std::vector<std::string> o; + fromNSArray(options, o); + return [toNSArray(properties_->parseIceCommandLineOptions(o)) autorelease]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(void) load:(NSString*)file +{ + NSException* nsex = nil; + try + { + properties_->load(fromNSString(file)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} +-(id<ICEProperties>) clone +{ + NSException* nsex = nil; + try + { + return [ICEProperties wrapperWithCxxObject:properties_->clone().get()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +@end + +namespace +{ + +class UpdateCallbackI : public Ice::PropertiesAdminUpdateCallback +{ +public: + + UpdateCallbackI(id<ICEPropertiesAdminUpdateCallback> callback) : + _callback(callback) + { + [(ICEPropertiesAdminUpdateCallback*)callback setPropertiesAdminUpdateCallback:this]; + } + + void + updated(const Ice::PropertyDict& properties) + { + [_callback updated:[toNSDictionary(properties) autorelease]]; + } + +private: + + id<ICEPropertiesAdminUpdateCallback> _callback; +}; + +} + +#define PROPERTIESADMINUPDATECALLBACK \ + dynamic_cast<Ice::PropertiesAdminUpdateCallback*>(static_cast<IceUtil::Shared*>(cxxObject_)) + +@implementation ICEPropertiesAdminUpdateCallback +-(void) dealloc +{ + if(PROPERTIESADMINUPDATECALLBACK) + { + PROPERTIESADMINUPDATECALLBACK->__decRef(); + } + [super dealloc]; +} + +-(void) setPropertiesAdminUpdateCallback:(Ice::PropertiesAdminUpdateCallback*)cxxObject +{ + assert(!PROPERTIESADMINUPDATECALLBACK); + cxxObject_ = static_cast<IceUtil::Shared*>(cxxObject); + PROPERTIESADMINUPDATECALLBACK->__incRef(); +} + +-(Ice::PropertiesAdminUpdateCallback*) propertiesAdminUpdateCallback +{ + return PROPERTIESADMINUPDATECALLBACK; +} +@end + +#define NATIVEPROPERTIESADMIN dynamic_cast<Ice::NativePropertiesAdmin*>(static_cast<IceUtil::Shared*>(cxxObject_)) + +@implementation ICENativePropertiesAdmin +-(void) addUpdateCallback:(id<ICEPropertiesAdminUpdateCallback>)callback +{ + NSAssert([callback isKindOfClass:[ICEPropertiesAdminUpdateCallback class]], + @"callback not extends ICEPropertiesAdminUpdateCallback class"); + if([(ICEPropertiesAdminUpdateCallback*)callback propertiesAdminUpdateCallback]) + { + NATIVEPROPERTIESADMIN->addUpdateCallback( + [(ICEPropertiesAdminUpdateCallback*)callback propertiesAdminUpdateCallback]); + } + else + { + NATIVEPROPERTIESADMIN->addUpdateCallback(new UpdateCallbackI(callback)); + } +} + +-(void) removeUpdateCallback:(id<ICEPropertiesAdminUpdateCallback>)callback +{ + NSAssert([callback isKindOfClass:[ICEPropertiesAdminUpdateCallback class]], + @"callback not extends ICEPropertiesAdminUpdateCallback class"); + + NATIVEPROPERTIESADMIN->removeUpdateCallback( + [(ICEPropertiesAdminUpdateCallback*)callback propertiesAdminUpdateCallback]); +} +@end diff --git a/objc/src/Ice/PropertiesI.h b/objc/src/Ice/PropertiesI.h new file mode 100644 index 00000000000..18e71076804 --- /dev/null +++ b/objc/src/Ice/PropertiesI.h @@ -0,0 +1,30 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Properties.h> + +#import <Wrapper.h> + +#include <IceCpp/Properties.h> +#include <IceCpp/NativePropertiesAdmin.h> + +@interface ICEProperties : ICEInternalWrapper<ICEProperties> +{ + Ice::Properties* properties_; +} +-(Ice::Properties*)properties; +@end + +@interface ICEPropertiesAdminUpdateCallback () +-(void) setPropertiesAdminUpdateCallback:(Ice::PropertiesAdminUpdateCallback*)callback; +-(Ice::PropertiesAdminUpdateCallback*) propertiesAdminUpdateCallback; +@end + +@interface ICENativePropertiesAdmin : ICEInternalWrapper<ICENativePropertiesAdmin> +@end diff --git a/objc/src/Ice/Proxy.mm b/objc/src/Ice/Proxy.mm new file mode 100644 index 00000000000..d0754cbedf8 --- /dev/null +++ b/objc/src/Ice/Proxy.mm @@ -0,0 +1,1721 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <ProxyI.h> +#import <Util.h> +#import <StreamI.h> +#import <VersionI.h> +#import <CommunicatorI.h> +#import <IdentityI.h> +#import <ConnectionI.h> + +#import <objc/Ice/Object.h> +#import <objc/Ice/LocalException.h> +#import <objc/Ice/Router.h> +#import <objc/Ice/Locator.h> + +#include <IceCpp/Initialize.h> +#include <IceCpp/Proxy.h> +#include <IceCpp/LocalException.h> +#include <IceCpp/Router.h> +#include <IceCpp/Locator.h> + +#import <objc/runtime.h> +#import <objc/message.h> + +#import <Foundation/NSThread.h> +#import <Foundation/NSInvocation.h> +#import <Foundation/NSAutoreleasePool.h> + +#include <Block.h> + +#define OBJECTPRX ((IceProxy::Ice::Object*)objectPrx__) +#define ASYNCRESULT ((Ice::AsyncResult*)asyncResult__) + +namespace +{ + +class BeginInvokeAsyncCallback : public IceUtil::Shared +{ +public: + +BeginInvokeAsyncCallback(void (^completed)(id<ICEInputStream>, BOOL), + void (^exception)(ICEException*), + void (^sent)(BOOL), + BOOL returnsData) : + _completed(Block_copy(completed)), + _exception(Block_copy(exception)), + _sent(Block_copy(sent)), + _returnsData(returnsData) +{ +} + +virtual ~BeginInvokeAsyncCallback() +{ + Block_release(_completed); + Block_release(_exception); + Block_release(_sent); +} + +void completed(const Ice::AsyncResultPtr& result) +{ + BOOL ok = YES; // Keep the compiler happy. + id<ICEInputStream> is = nil; + NSException* nsex = nil; + Ice::ObjectPrx proxy = result->getProxy(); + try + { + std::vector<Ice::Byte> outParams; + ok = proxy->end_ice_invoke(outParams, result); + if(_returnsData) + { + Ice::InputStreamPtr s = Ice::createInputStream(proxy->ice_getCommunicator(), outParams); + is = [ICEInputStream wrapperWithCxxObjectNoAutoRelease:s.get()]; + } + else if(!outParams.empty()) + { + if(ok) + { + if(outParams.size() != 6) + { + throw Ice::EncapsulationException(__FILE__, __LINE__); + } + } + else + { + Ice::InputStreamPtr s = Ice::createInputStream(proxy->ice_getCommunicator(), outParams); + try + { + s->startEncapsulation(); + s->throwException(); + } + catch(const Ice::UserException& ex) + { + s->endEncapsulation(); + throw Ice::UnknownUserException(__FILE__, __LINE__, ex.ice_name()); + } + } + } + } + catch(const std::exception& ex) + { + if(is != nil) + { + [is release]; + is = nil; + } + nsex = toObjCException(ex); + } + + NSException* exception = nil; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + @try + { + if(nsex != nil) + { + @try + { + @throw nsex; + } + @catch(ICEException* ex) + { + if(_exception) + { + _exception(ex); + } + return; + } + } + + _completed(is, ok); + } + @catch(id e) + { + exception = [e retain]; + } + @finally + { + [is release]; + [pool drain]; + } + + if(exception != nil) + { + rethrowCxxException(exception, true); // True = release the exception. + } +} + +void sent(const Ice::AsyncResultPtr& result) +{ + if(!_sent) + { + return; + } + + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSException* exception = nil; + @try + { + _sent(result->sentSynchronously()); + } + @catch(id e) + { + exception = [e retain]; + } + @finally + { + [pool drain]; + } + + if(exception != nil) + { + rethrowCxxException(exception, true); // True = release the exception. + } +} + +private: + +void (^_completed)(id<ICEInputStream>, BOOL); +void (^_exception)(ICEException*); +void (^_sent)(BOOL); +BOOL _returnsData; + +}; + +}; + +@implementation ICEAsyncResult +-(ICEAsyncResult*) initWithAsyncResult__:(const Ice::AsyncResultPtr&)arg + operation:(NSString*)op + proxy:(id<ICEObjectPrx>)p; +{ + self = [super init]; + if(!self) + { + return nil; + } + + asyncResult__ = arg.get(); + ASYNCRESULT->__incRef(); + operation_ = [op retain]; + proxy_ = [p retain]; + return self; +} + +-(Ice::AsyncResult*) asyncResult__ +{ + return ASYNCRESULT; +} + +-(void) dealloc +{ + ASYNCRESULT->__decRef(); + asyncResult__ = 0; + [operation_ release]; + [proxy_ release]; + [super dealloc]; +} + +-(void) finalize +{ + ASYNCRESULT->__decRef(); + asyncResult__ = 0; + [super finalize]; +} + ++(ICEAsyncResult*) asyncResultWithAsyncResult__:(const Ice::AsyncResultPtr&)arg +{ + return [self asyncResultWithAsyncResult__:arg operation:nil proxy:nil]; +} ++(ICEAsyncResult*) asyncResultWithAsyncResult__:(const Ice::AsyncResultPtr&)arg + operation:(NSString*)op + proxy:(id<ICEObjectPrx>)p +{ + if(!arg) + { + return nil; + } + else + { + return [[[self alloc] initWithAsyncResult__:arg operation:op proxy:p] autorelease]; + } +} +-(NSString*) operation +{ + return operation_; +} + +-(id<ICECommunicator>) getCommunicator +{ + return [ICECommunicator wrapperWithCxxObject:ASYNCRESULT->getCommunicator().get()]; +} + +-(id<ICEConnection>) getConnection +{ + return [ICEConnection wrapperWithCxxObject:ASYNCRESULT->getConnection().get()]; +} + +-(id<ICEObjectPrx>) getProxy +{ + return [[proxy_ retain] autorelease]; +} + +-(BOOL) isCompleted +{ + return ASYNCRESULT->isCompleted(); +} + +-(void) waitForCompleted +{ + ASYNCRESULT->waitForCompleted(); +} + +-(BOOL) isSent +{ + return ASYNCRESULT->isSent(); +} + +-(void) waitForSent +{ + ASYNCRESULT->waitForSent(); +} + +-(BOOL) sentSynchronously +{ + return ASYNCRESULT->sentSynchronously(); +} + +-(void) throwLocalException +{ + NSException* nsex; + try + { + ASYNCRESULT->throwLocalException(); + return; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; +} + +-(NSString*) getOperation +{ + if(operation_ != nil) + { + return [[operation_ retain] autorelease]; + } + else + { + return [toNSString(ASYNCRESULT->getOperation()) autorelease]; + } +} +@end + +@implementation ICEObjectPrx + +-(ICEObjectPrx*) initWithObjectPrx__:(const Ice::ObjectPrx&)arg +{ + self = [super init]; + if(!self) + { + return nil; + } + communicator__ = [ICECommunicator wrapperWithCxxObjectNoAutoRelease:arg->ice_getCommunicator().get()]; + objectPrx__ = arg.get(); + OBJECTPRX->__incRef(); + return self; +} + +-(IceProxy::Ice::Object*) objectPrx__ +{ + return (IceProxy::Ice::Object*)objectPrx__; +} + +-(void) dealloc +{ + OBJECTPRX->__decRef(); + objectPrx__ = 0; + [communicator__ release]; + [super dealloc]; +} + +-(void) finalize +{ + OBJECTPRX->__decRef(); + objectPrx__ = 0; + [super finalize]; +} + ++(ICEObjectPrx*) objectPrxWithObjectPrx__:(const Ice::ObjectPrx&)arg +{ + if(!arg) + { + return nil; + } + else + { + return [[[self alloc] initWithObjectPrx__:arg] autorelease]; + } +} + ++(id) uncheckedCast:(id<ICEObjectPrx>)proxy +{ + if(proxy != nil) + { + if([(ICEObjectPrx*)proxy isKindOfClass:self]) + { + return [[proxy retain] autorelease]; + } + else + { + return [[[self alloc] initWithObjectPrx__:[(ICEObjectPrx*)proxy objectPrx__]] autorelease]; + } + } + return nil; +} ++(id) uncheckedCast:(id<ICEObjectPrx>)proxy facet:(NSString*)facet +{ + return [self uncheckedCast:[proxy ice_facet:facet]]; +} ++(id) checkedCast:(id<ICEObjectPrx>)proxy +{ + if(proxy != nil) + { + if([(ICEObjectPrx*)proxy isKindOfClass:self]) + { + return [[proxy retain] autorelease]; + } + else if([(ICEObjectPrx*)proxy conformsToProtocol:[self protocol__]] || + [proxy ice_isA:[self ice_staticId]]) + { + return [[[self alloc] initWithObjectPrx__:[(ICEObjectPrx*)proxy objectPrx__]] autorelease]; + } + } + return nil; +} ++(id) checkedCast:(id<ICEObjectPrx>)proxy facet:(NSString*)facet +{ + @try + { + return [self checkedCast:[proxy ice_facet:facet]]; + } + @catch(ICEFacetNotExistException* ex) + { + return nil; + } +} ++(id) checkedCast:(id<ICEObjectPrx>)proxy context:(ICEContext*)context +{ + if(proxy != nil) + { + if([(ICEObjectPrx*)proxy isKindOfClass:self]) + { + return [[proxy retain] autorelease]; + } + else if([(ICEObjectPrx*)proxy conformsToProtocol:[self protocol__]] || + [proxy ice_isA:[self ice_staticId] context:context]) + { + return [[[self alloc] initWithObjectPrx__:[(ICEObjectPrx*)proxy objectPrx__]] autorelease]; + } + } + return nil; +} ++(id) checkedCast:(id<ICEObjectPrx>)proxy facet:(NSString*)facet context:(ICEContext*)context +{ + @try + { + return [self checkedCast:[proxy ice_facet:facet] context:context]; + } + @catch(ICEFacetNotExistException* ex) + { + return nil; + } +} ++(NSString*) ice_staticId +{ + return @"::Ice::Object"; +} + ++(Protocol*) protocol__ +{ + return objc_getProtocol(class_getName([self class])); +} + +-(id<ICEOutputStream>) createOutputStream__ +{ + NSException* nsex = nil; + try + { + Ice::OutputStreamPtr os = Ice::createOutputStream(OBJECTPRX->ice_getCommunicator()); + return [ICEOutputStream wrapperWithCxxObjectNoAutoRelease:os.get()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(void) checkAsyncTwowayOnly__:(NSString*)operation +{ + // + // No mutex lock necessary, there is nothing mutable in this + // operation. + // + + if(![self ice_isTwoway]) + { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"`%@' can only be called with a twoway proxy", operation] + userInfo:nil]; + } +} + +-(void) invoke__:(NSString*)operation + mode:(ICEOperationMode)mode + format:(ICEFormatType)format + marshal:(ICEMarshalCB)marshal + unmarshal:(ICEUnmarshalCB)unmarshal + context:(ICEContext*)context +{ + if(unmarshal && !OBJECTPRX->ice_isTwoway()) + { + @throw [ICETwowayOnlyException twowayOnlyException:__FILE__ line:__LINE__ operation:operation]; + } + + ICEOutputStream<ICEOutputStream>* os = nil; + if(marshal) + { + os = [self createOutputStream__]; + try + { + [os os]->startEncapsulation(IceInternal::getCompatibleEncoding(OBJECTPRX->ice_getEncodingVersion()), + (Ice::FormatType)format); + } + catch(const std::exception& ex) + { + [os release]; + @throw toObjCException(ex); + } + + @try + { + marshal(os); + } + @catch(id ex) + { + [os release]; + @throw ex; + } + } + + BOOL ok = YES; // Keep the compiler happy. + ICEInputStream<ICEInputStream>* is = nil; + NSException* nsex = nil; + try + { + std::vector<Ice::Byte> inParams; + if(os) + { + [os os]->endEncapsulation(); + [os os]->finished(inParams); + [os release]; + os = nil; + } + + std::vector<Ice::Byte> outParams; + if(context != nil) + { + Ice::Context ctx; + fromNSDictionary(context, ctx); + ok = OBJECTPRX->ice_invoke(fromNSString(operation), (Ice::OperationMode)mode, inParams, outParams, ctx); + } + else + { + ok = OBJECTPRX->ice_invoke(fromNSString(operation), (Ice::OperationMode)mode, inParams, outParams); + } + + if(unmarshal) + { + Ice::InputStreamPtr s = Ice::createInputStream(OBJECTPRX->ice_getCommunicator(), outParams); + is = [ICEInputStream wrapperWithCxxObjectNoAutoRelease:s.get()]; + } + else if(!outParams.empty()) + { + if(ok) + { + if(outParams.size() != 6) + { + throw Ice::EncapsulationException(__FILE__, __LINE__); + } + } + else + { + Ice::InputStreamPtr s = Ice::createInputStream(OBJECTPRX->ice_getCommunicator(), outParams); + try + { + s->startEncapsulation(); + s->throwException(); + } + catch(const Ice::UserException& ex) + { + s->endEncapsulation(); + throw Ice::UnknownUserException(__FILE__, __LINE__, ex.ice_name()); + } + } + } + } + catch(const std::exception& ex) + { + if(os != nil) + { + [os release]; + os = nil; + } + if(is != nil) + { + [is release]; + is = nil; + } + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + + NSAssert(os == nil, @"output stream not cleared"); + if(is) + { + @try + { + unmarshal(is, ok); + } + @finally + { + [is release]; + } + } +} + +-(id<ICEAsyncResult>) begin_invoke__:(NSString*)operation + mode:(ICEOperationMode)mode + format:(ICEFormatType)format + marshal:(void(^)(id<ICEOutputStream>))marshal + returnsData:(BOOL)returnsData + context:(ICEContext*)context +{ + if(returnsData) + { + [self checkAsyncTwowayOnly__:operation]; + } + + ICEOutputStream<ICEOutputStream>* os = nil; + if(marshal) + { + os = [self createOutputStream__]; + try + { + [os os]->startEncapsulation(IceInternal::getCompatibleEncoding(OBJECTPRX->ice_getEncodingVersion()), + (Ice::FormatType)format); + } + catch(const std::exception& ex) + { + [os release]; + @throw toObjCException(ex); + } + + @try + { + marshal(os); + } + @catch(id ex) + { + [os release]; + @throw ex; + } + } + + NSException* nsex = nil; + try + { + std::vector<Ice::Byte> inParams; + if(os) + { + [os os]->endEncapsulation(); + [os os]->finished(inParams); + [os release]; + os = nil; + } + + Ice::AsyncResultPtr r; + if(context != nil) + { + Ice::Context ctx; + fromNSDictionary(context, ctx); + r = OBJECTPRX->begin_ice_invoke(fromNSString(operation), (Ice::OperationMode)mode, inParams, ctx); + } + else + { + r = OBJECTPRX->begin_ice_invoke(fromNSString(operation), (Ice::OperationMode)mode, inParams); + } + return [ICEAsyncResult asyncResultWithAsyncResult__:r operation:operation proxy:self]; + } + catch(const std::exception& ex) + { + if(os != nil) + { + [os release]; + os = nil; + } + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return nil; // Keep the compiler happy. +} + +-(id<ICEAsyncResult>) begin_invoke__:(NSString*)operation + mode:(ICEOperationMode)mode + format:(ICEFormatType)format + marshal:(void(^)(id<ICEOutputStream>))marshal + returnsData:(BOOL)returnsData + completed:(void(^)(id<ICEInputStream>, BOOL))completed + response:(BOOL)response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent + context:(ICEContext*)context +{ + if(returnsData) + { + [self checkAsyncTwowayOnly__:operation]; + if(!response) + { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"Response callback is nil" + userInfo:nil]; + } + } + + if(!exception) + { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"Exception callback is nil" + userInfo:nil]; + } + + ICEOutputStream<ICEOutputStream>* os = nil; + if(marshal) + { + os = [self createOutputStream__]; + try + { + [os os]->startEncapsulation(IceInternal::getCompatibleEncoding(OBJECTPRX->ice_getEncodingVersion()), + (Ice::FormatType)format); + } + catch(const std::exception& ex) + { + [os release]; + @throw toObjCException(ex); + } + + @try + { + marshal(os); + } + @catch(id ex) + { + [os release]; + @throw ex; + } + } + + NSException* nsex = nil; + try + { + std::vector<Ice::Byte> inParams; + if(os) + { + [os os]->endEncapsulation(); + [os os]->finished(inParams); + [os release]; + os = nil; + } + + Ice::CallbackPtr cb = Ice::newCallback(new BeginInvokeAsyncCallback(completed, exception, sent, returnsData), + &BeginInvokeAsyncCallback::completed, + &BeginInvokeAsyncCallback::sent); + Ice::AsyncResultPtr r; + if(context != nil) + { + Ice::Context ctx; + fromNSDictionary(context, ctx); + r = OBJECTPRX->begin_ice_invoke(fromNSString(operation), (Ice::OperationMode)mode, inParams, ctx, cb); + } + else + { + r = OBJECTPRX->begin_ice_invoke(fromNSString(operation), (Ice::OperationMode)mode, inParams, cb); + } + return [ICEAsyncResult asyncResultWithAsyncResult__:r operation:operation proxy:self]; + } + catch(const IceUtil::IllegalArgumentException& ex) + { + if(os != nil) + { + [os release]; + os = nil; + } + nsex = [NSException exceptionWithName:NSInvalidArgumentException reason:[toNSString(ex.reason()) autorelease] + userInfo:nil]; + } + catch(const std::exception& ex) + { + if(os != nil) + { + [os release]; + os = nil; + } + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return nil; // Keep the compiler happy. +} +-(id<ICEAsyncResult>) begin_invoke__:(NSString*)op + mode:(ICEOperationMode)mode + format:(ICEFormatType)format + marshal:(void(^)(id<ICEOutputStream>))marshal + response:(void(^)())response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent + context:(ICEContext*)ctx +{ + void(^completed)(id<ICEInputStream>, BOOL) = ^(id<ICEInputStream>, BOOL) { + if(response) + { + response(); + } + }; + return [self begin_invoke__:op + mode:mode + format:format + marshal:marshal + returnsData:NO + completed:completed + response:TRUE + exception:exception + sent:sent + context:ctx]; +} + +-(id<ICEAsyncResult>) begin_invoke__:(NSString*)op + mode:(ICEOperationMode)mode + format:(ICEFormatType)format + marshal:(void(^)(id<ICEOutputStream>))marshal + completed:(void(^)(id<ICEInputStream>, BOOL))completed + response:(BOOL)response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent + context:(ICEContext*)ctx +{ + return [self begin_invoke__:op + mode:mode + format:format + marshal:marshal + returnsData:TRUE + completed:completed + response:response + exception:exception + sent:sent context:ctx]; +} + +-(void)end_invoke__:(NSString*)operation unmarshal:(ICEUnmarshalCB)unmarshal result:(id<ICEAsyncResult>)r +{ + ICEAsyncResult* result = (ICEAsyncResult*)r; + if(operation != [result operation]) + { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"Incorrect operation for end_%@ method: %@", + operation, [result operation]] + userInfo:nil]; + } + if(result == nil) + { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"ICEAsyncResult is nil" + userInfo:nil]; + } + + BOOL ok = YES; // Keep the compiler happy. + NSException* nsex = nil; + ICEInputStream* is = nil; + try + { + std::vector<Ice::Byte> outParams; + ok = OBJECTPRX->end_ice_invoke(outParams, [result asyncResult__]); + + if(unmarshal) + { + Ice::InputStreamPtr s = Ice::createInputStream(OBJECTPRX->ice_getCommunicator(), outParams); + is = [ICEInputStream wrapperWithCxxObjectNoAutoRelease:s.get()]; + } + else if(!outParams.empty()) + { + if(ok) + { + if(outParams.size() != 6) + { + throw Ice::EncapsulationException(__FILE__, __LINE__); + } + } + else + { + Ice::InputStreamPtr s = Ice::createInputStream(OBJECTPRX->ice_getCommunicator(), outParams); + try + { + s->startEncapsulation(); + s->throwException(); + } + catch(const Ice::UserException& ex) + { + s->endEncapsulation(); + throw Ice::UnknownUserException(__FILE__, __LINE__, ex.ice_name()); + } + } + } + } + catch(const IceUtil::IllegalArgumentException& ex) + { + if(is != nil) + { + [is release]; + is = nil; + } + nsex = [NSException exceptionWithName:NSInvalidArgumentException reason:[toNSString(ex.reason()) autorelease] + userInfo:nil]; + } + catch(const std::exception& ex) + { + if(is != nil) + { + [is release]; + is = nil; + } + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + + if(is != nil) + { + @try + { + unmarshal(is, ok); + } + @finally + { + [is release]; + } + } +} + +-(id) copyWithZone:(NSZone *)zone +{ + return [self retain]; +} + +-(NSUInteger) hash +{ + return (NSUInteger)OBJECTPRX->__hash(); +} +-(NSString*) description +{ + return [toNSString(OBJECTPRX->ice_toString()) autorelease]; +} +-(BOOL) isEqual:(id)o_ +{ + if(self == o_) + { + return YES; + } + if(!o_ || ![o_ isKindOfClass:[ICEObjectPrx class]]) + { + return NO; + } + return *OBJECTPRX == *[o_ objectPrx__]; +} + +-(NSComparisonResult) compareIdentity:(id<ICEObjectPrx>)aProxy +{ + IceProxy::Ice::Object* lhs = OBJECTPRX; + IceProxy::Ice::Object* rhs = [(ICEObjectPrx*)aProxy objectPrx__]; + if(Ice::proxyIdentityEqual(lhs, rhs)) + { + return NSOrderedSame; + } + else if(Ice::proxyIdentityLess(lhs, rhs)) + { + return NSOrderedAscending; + } + else + { + return NSOrderedDescending; + } +} + +-(NSComparisonResult) compareIdentityAndFacet:(id<ICEObjectPrx>)aProxy +{ + IceProxy::Ice::Object* lhs = OBJECTPRX; + IceProxy::Ice::Object* rhs = [(ICEObjectPrx*)aProxy objectPrx__]; + if(Ice::proxyIdentityAndFacetEqual(lhs, rhs)) + { + return NSOrderedSame; + } + else if(Ice::proxyIdentityAndFacetLess(lhs, rhs)) + { + return NSOrderedAscending; + } + else + { + return NSOrderedDescending; + } +} + +-(id<ICECommunicator>) ice_getCommunicator +{ + return [[communicator__ retain] autorelease]; +} + +-(NSString*) ice_toString +{ + return [toNSString(OBJECTPRX->ice_toString()) autorelease]; +} + +-(BOOL) ice_isA:(NSString*)typeId +{ + __block BOOL ret__; + cppCall(^ { ret__ = OBJECTPRX->ice_isA(fromNSString(typeId)); }); + return ret__; +} +-(BOOL) ice_isA:(NSString*)typeId context:(ICEContext*)context +{ + __block BOOL ret__; + cppCall(^(const Ice::Context& ctx) { ret__ = OBJECTPRX->ice_isA(fromNSString(typeId), ctx); }, context); + return ret__; +} +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId +{ + return beginCppCall(^(Ice::AsyncResultPtr& result) + { + result = OBJECTPRX->begin_ice_isA(fromNSString(typeId)); + }, self); +} +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId context:(ICEContext*)context +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::Context& ctx) + { + result = OBJECTPRX->begin_ice_isA(fromNSString(typeId), ctx); + }, context, self); +} +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId + response:(void(^)(BOOL))response + exception:(void(^)(ICEException*))exception +{ + return [self begin_ice_isA:typeId response:response exception:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId + context:(ICEContext*)context + response:(void(^)(BOOL))response + exception:(void(^)(ICEException*))exception + +{ + return [self begin_ice_isA:typeId context:context response:response exception:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId + response:(void(^)(BOOL))response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) + { + result = OBJECTPRX->begin_ice_isA(fromNSString(typeId), cb); + }, + ^(const Ice::AsyncResultPtr& result) { + BOOL ret__ = OBJECTPRX->end_ice_isA(result); + if(response) + { + response(ret__); + } + }, + exception, sent, self); + +} +-(id<ICEAsyncResult>) begin_ice_isA:(NSString*)typeId + context:(ICEContext*)context + response:(void(^)(BOOL))response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::Context& ctx, const Ice::CallbackPtr& cb) + { + result = OBJECTPRX->begin_ice_isA(fromNSString(typeId), ctx, cb); + }, + context, + ^(const Ice::AsyncResultPtr& result) { + BOOL ret__ = OBJECTPRX->end_ice_isA(result); + if(response) + { + response(ret__); + } + }, + exception, sent, self); +} +-(BOOL) end_ice_isA:(id<ICEAsyncResult>)result +{ + __block BOOL ret__; + endCppCall(^(const Ice::AsyncResultPtr& r) { ret__ = OBJECTPRX->end_ice_isA(r); }, result); + return ret__; +} + +-(void) ice_ping +{ + cppCall(^ { OBJECTPRX->ice_ping(); }); +} +-(void) ice_ping:(ICEContext*)context +{ + cppCall(^(const Ice::Context& ctx) { OBJECTPRX->ice_ping(ctx); }, context); +} +-(id<ICEAsyncResult>) begin_ice_ping +{ + return beginCppCall(^(Ice::AsyncResultPtr& result) { result = OBJECTPRX->begin_ice_ping(); }, self); +} +-(id<ICEAsyncResult>) begin_ice_ping:(ICEContext*)context +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::Context& ctx) + { + result = OBJECTPRX->begin_ice_ping(ctx); + }, context, self); +} + +-(id<ICEAsyncResult>) begin_ice_ping:(void(^)())response exception:(void(^)(ICEException*))exception +{ + return [self begin_ice_ping:response exception:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_ice_ping:(ICEContext*)context + response:(void(^)())response + exception:(void(^)(ICEException*))exception + +{ + return [self begin_ice_ping:context response:response exception:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_ice_ping:(void(^)())response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) + { + result = OBJECTPRX->begin_ice_ping(cb); + }, + ^(const Ice::AsyncResultPtr& result) { + OBJECTPRX->end_ice_ping(result); + if(response) + { + response(); + } + }, + exception, sent, self); +} + +-(id<ICEAsyncResult>) begin_ice_ping:(ICEContext*)context + response:(void(^)())response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::Context& ctx, const Ice::CallbackPtr& cb) + { + result = OBJECTPRX->begin_ice_ping(ctx, cb); + }, + context, + ^(const Ice::AsyncResultPtr& result) { + OBJECTPRX->end_ice_ping(result); + if(response) + { + response(); + } + }, + exception, sent, self); +} +-(void) end_ice_ping:(id<ICEAsyncResult>)result +{ + endCppCall(^(const Ice::AsyncResultPtr& r) { OBJECTPRX->end_ice_ping(r); }, result); +} + +-(NSArray*) ice_ids +{ + __block NSArray* ret__; + cppCall(^ { ret__ = [toNSArray(OBJECTPRX->ice_ids()) autorelease]; }); + return ret__; +} +-(NSArray*) ice_ids:(ICEContext*)context +{ + __block NSArray* ret__; + cppCall(^(const Ice::Context& ctx) { ret__ = [toNSArray(OBJECTPRX->ice_ids(ctx)) autorelease]; }, context); + return ret__; +} +-(id<ICEAsyncResult>) begin_ice_ids +{ + return beginCppCall(^(Ice::AsyncResultPtr& result) { result = OBJECTPRX->begin_ice_ids(); } , self); +} + +-(id<ICEAsyncResult>) begin_ice_ids:(ICEContext*)context +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::Context& ctx) + { + result = OBJECTPRX->begin_ice_ids(ctx); + }, context, self); +} +-(id<ICEAsyncResult>) begin_ice_ids:(void(^)(NSArray*))response exception:(void(^)(ICEException*))exception +{ + return [self begin_ice_ids:response exception:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_ice_ids:(ICEContext*)context + response:(void(^)(NSArray*))response + exception:(void(^)(ICEException*))exception +{ + return [self begin_ice_ids:context response:response exception:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_ice_ids:(void(^)(NSArray*))response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) + { + result = OBJECTPRX->begin_ice_ids(cb); + }, + ^(const Ice::AsyncResultPtr& result) { + NSArray* ret__ = [toNSArray(OBJECTPRX->end_ice_ids(result)) autorelease]; + if(response) + { + response(ret__); + } + }, + exception, sent, self); +} +-(id<ICEAsyncResult>) begin_ice_ids:(ICEContext*)context + response:(void(^)(NSArray*))response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::Context& ctx, const Ice::CallbackPtr& cb) + { + result = OBJECTPRX->begin_ice_ids(ctx, cb); + }, + context, + ^(const Ice::AsyncResultPtr& result) { + NSArray* ret__ = [toNSArray(OBJECTPRX->end_ice_ids(result)) autorelease]; + if(response) + { + response(ret__); + } + }, + exception, sent, self); +} +-(NSArray*) end_ice_ids:(id<ICEAsyncResult>)result +{ + __block NSArray* ret__; + endCppCall(^(const Ice::AsyncResultPtr& r) { ret__ = [toNSArray(OBJECTPRX->end_ice_ids(r)) autorelease]; }, + result); + return ret__; +} + +-(NSString*) ice_id +{ + __block NSString* ret__; + cppCall(^ { ret__ = [toNSString(OBJECTPRX->ice_id()) autorelease]; }); + return ret__; +} +-(NSString*) ice_id:(ICEContext*)context +{ + __block NSString* ret__; + cppCall(^(const Ice::Context& ctx) { ret__ = [toNSString(OBJECTPRX->ice_id(ctx)) autorelease]; }, context); + return ret__; +} +-(id<ICEAsyncResult>) begin_ice_id +{ + return beginCppCall(^(Ice::AsyncResultPtr& result) { result = OBJECTPRX->begin_ice_id(); } , self); +} +-(id<ICEAsyncResult>) begin_ice_id:(ICEContext*)context +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::Context& ctx) + { + result = OBJECTPRX->begin_ice_id(ctx); + }, context, self); +} +-(id<ICEAsyncResult>) begin_ice_id:(void(^)(NSString*))response exception:(void(^)(ICEException*))exception +{ + return [self begin_ice_id:response exception:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_ice_id:(ICEContext*)context + response:(void(^)(NSString*))response + exception:(void(^)(ICEException*))exception + +{ + return [self begin_ice_id:context response:response exception:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_ice_id:(void(^)(NSString*))response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) + { + result = OBJECTPRX->begin_ice_id(cb); + }, + ^(const Ice::AsyncResultPtr& result) { + NSString* ret__ = [toNSString(OBJECTPRX->end_ice_id(result)) autorelease]; + if(response) + { + response(ret__); + } + }, + exception, sent, self); +} +-(id<ICEAsyncResult>) begin_ice_id:(ICEContext*)context + response:(void(^)(NSString*))response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::Context& ctx, const Ice::CallbackPtr& cb) + { + result = OBJECTPRX->begin_ice_id(ctx, cb); + }, + context, + ^(const Ice::AsyncResultPtr& result) { + NSString* ret__ = [toNSString(OBJECTPRX->end_ice_id(result)) autorelease]; + if(response) + { + response(ret__); + } + }, + exception, sent, self); +} +-(NSString*) end_ice_id:(id<ICEAsyncResult>)result +{ + __block NSString* ret__; + endCppCall(^(const Ice::AsyncResultPtr& r) { ret__ = [toNSString(OBJECTPRX->end_ice_id(r)) autorelease]; }, + result); + return ret__; +} + +-(BOOL) ice_invoke:(NSString*)operation + mode:(ICEOperationMode)mode + inEncaps:(NSData*)inEncaps + outEncaps:(NSMutableData**)outEncaps +{ + __block BOOL ret__; + cppCall(^ { + std::pair<const Ice::Byte*, const Ice::Byte*> inP((ICEByte*)[inEncaps bytes], + (ICEByte*)[inEncaps bytes] + [inEncaps length]); + std::vector<Ice::Byte> outP; + ret__ = OBJECTPRX->ice_invoke(fromNSString(operation), (Ice::OperationMode)mode, inP, outP); + *outEncaps = [NSMutableData dataWithBytes:&outP[0] length:outP.size()]; + }); + return ret__; +} + +-(BOOL) ice_invoke:(NSString*)operation + mode:(ICEOperationMode)mode + inEncaps:(NSData*)inEncaps + outEncaps:(NSMutableData**)outEncaps + context:(ICEContext*)context +{ + __block BOOL ret__; + cppCall(^(const Ice::Context& ctx) { + std::pair<const Ice::Byte*, const Ice::Byte*> inP((ICEByte*)[inEncaps bytes], + (ICEByte*)[inEncaps bytes] + [inEncaps length]); + std::vector<Ice::Byte> outP; + ret__ = OBJECTPRX->ice_invoke(fromNSString(operation), (Ice::OperationMode)mode, inP, outP, ctx); + *outEncaps = [NSMutableData dataWithBytes:&outP[0] length:outP.size()]; + }, context); + return ret__; +} +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation mode:(ICEOperationMode)mode inEncaps:(NSData*)inEncaps +{ + return beginCppCall(^(Ice::AsyncResultPtr& result) + { + std::pair<const Ice::Byte*, const Ice::Byte*> + inP((ICEByte*)[inEncaps bytes], (ICEByte*)[inEncaps bytes] + [inEncaps length]); + result = OBJECTPRX->begin_ice_invoke(fromNSString(operation), + (Ice::OperationMode)mode, + inP); + }, self); +} +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation + mode:(ICEOperationMode)mode + inEncaps:(NSData*)inEncaps + context:(ICEContext*)context +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::Context& ctx) + { + std::pair<const Ice::Byte*, const Ice::Byte*> + inP((ICEByte*)[inEncaps bytes], (ICEByte*)[inEncaps bytes] + [inEncaps length]); + result = OBJECTPRX->begin_ice_invoke(fromNSString(operation), + (Ice::OperationMode)mode, + inP, + ctx); + }, context, self); +} +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation + mode:(ICEOperationMode)mode + inEncaps:(NSData*)inEncaps + response:(void(^)(BOOL, NSMutableData*))response + exception:(void(^)(ICEException*))exception +{ + return [self begin_ice_invoke:operation mode:mode inEncaps:inEncaps response:response exception:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation + mode:(ICEOperationMode)mode + inEncaps:(NSData*)inEncaps + context:(ICEContext*)context + response:(void(^)(BOOL, NSMutableData*))response + exception:(void(^)(ICEException*))exception +{ + return [self begin_ice_invoke:operation mode:mode inEncaps:inEncaps context:context response:response + exception:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation + mode:(ICEOperationMode)mode + inEncaps:(NSData*)inEncaps + response:(void(^)(BOOL, NSMutableData*))response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) + { + std::pair<const Ice::Byte*, const Ice::Byte*> + inP((ICEByte*)[inEncaps bytes], (ICEByte*)[inEncaps bytes] + [inEncaps length]); + result = OBJECTPRX->begin_ice_invoke(fromNSString(operation), + (Ice::OperationMode)mode, + inP, + cb); + }, + ^(const Ice::AsyncResultPtr& result) { + std::pair<const ::Ice::Byte*, const ::Ice::Byte*> outP; + BOOL ret__ = OBJECTPRX->___end_ice_invoke(outP, result); + NSMutableData* outEncaps = + [NSMutableData dataWithBytes:outP.first length:(outP.second - outP.first)]; + if(response) + { + response(ret__, outEncaps); + } + }, + exception, sent, self); +} +-(id<ICEAsyncResult>) begin_ice_invoke:(NSString*)operation + mode:(ICEOperationMode)mode + inEncaps:(NSData*)inEncaps + context:(ICEContext*)context + response:(void(^)(BOOL, NSMutableData*))response + exception:(void(^)(ICEException*))exception + sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::Context& ctx, const Ice::CallbackPtr& cb) + { + std::pair<const Ice::Byte*, const Ice::Byte*> + inP((ICEByte*)[inEncaps bytes], (ICEByte*)[inEncaps bytes] + [inEncaps length]); + result = OBJECTPRX->begin_ice_invoke(fromNSString(operation), + (Ice::OperationMode)mode, + inP, + ctx, + cb); + }, + context, + ^(const Ice::AsyncResultPtr& result) { + std::pair<const ::Ice::Byte*, const ::Ice::Byte*> outP; + BOOL ret__ = OBJECTPRX->___end_ice_invoke(outP, result); + NSMutableData* outEncaps = + [NSMutableData dataWithBytes:outP.first length:(outP.second - outP.first)]; + if(response) + { + response(ret__, outEncaps); + } + }, + exception, sent, self); +} +-(BOOL) end_ice_invoke:(NSMutableData**)outEncaps result:(id<ICEAsyncResult>)result + +{ + __block BOOL ret__; + endCppCall(^(const Ice::AsyncResultPtr& r) + { + std::vector<Ice::Byte> outP; + ret__ = OBJECTPRX->end_ice_invoke(outP, r); + *outEncaps = [NSMutableData dataWithBytes:&outP[0] length:outP.size()]; + }, result); + return ret__; +} + +-(ICEIdentity*) ice_getIdentity +{ + return [ICEIdentity identityWithIdentity:OBJECTPRX->ice_getIdentity()]; +} +-(id) ice_identity:(ICEIdentity*)identity +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_identity([identity identity])]; +} +-(ICEMutableContext*) ice_getContext +{ + return [toNSDictionary(OBJECTPRX->ice_getContext()) autorelease]; +} +-(id) ice_context:(ICEContext*)context +{ + Ice::Context ctx; + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_context(fromNSDictionary(context, ctx))]; +} +-(NSString*) ice_getFacet +{ + return [toNSString(OBJECTPRX->ice_getFacet()) autorelease]; +} +-(id) ice_facet:(NSString*)facet +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_facet(fromNSString(facet))]; +} +-(NSString*) ice_getAdapterId +{ + return [toNSString(OBJECTPRX->ice_getAdapterId()) autorelease]; +} + +-(ICEEndpointSeq*) ice_getEndpoints +{ + return [toNSArray(OBJECTPRX->ice_getEndpoints()) autorelease]; +} + +-(id) ice_endpoints:(ICEEndpointSeq*)endpoints +{ + Ice::EndpointSeq cxxEndpoints; + fromNSArray(endpoints, cxxEndpoints); + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_endpoints(cxxEndpoints)]; +} + +-(id) ice_adapterId:(NSString*)adapterId +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_adapterId(fromNSString(adapterId))]; +} + +-(ICEInt) ice_getLocatorCacheTimeout +{ + return OBJECTPRX->ice_getLocatorCacheTimeout(); +} +-(id) ice_locatorCacheTimeout:(ICEInt)timeout +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_locatorCacheTimeout(timeout)]; +} +-(BOOL) ice_isConnectionCached +{ + return OBJECTPRX->ice_isConnectionCached(); +} +-(id) ice_connectionCached:(BOOL)cached +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_connectionCached(cached)]; +} +-(ICEEndpointSelectionType) ice_getEndpointSelection +{ + return (ICEEndpointSelectionType)OBJECTPRX->ice_getEndpointSelection(); +} +-(id) ice_endpointSelection:(ICEEndpointSelectionType)type +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_endpointSelection((Ice::EndpointSelectionType)type)]; +} +-(BOOL) ice_isSecure +{ + return OBJECTPRX->ice_isSecure(); +} +-(id) ice_secure:(BOOL)secure +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_secure(secure)]; +} + +-(ICEEncodingVersion*) ice_getEncodingVersion +{ + return [ICEEncodingVersion encodingVersionWithEncodingVersion:OBJECTPRX->ice_getEncodingVersion()]; +} + +-(id) ice_encodingVersion:(ICEEncodingVersion*)encoding; +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_encodingVersion([encoding encodingVersion])]; +} + +-(BOOL) ice_isPreferSecure +{ + return OBJECTPRX->ice_isPreferSecure(); +} +-(id) ice_preferSecure:(BOOL)preferSecure +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_preferSecure(preferSecure)]; +} +-(id<ICERouterPrx>) ice_getRouter +{ + return (id<ICERouterPrx>)[ICERouterPrx objectPrxWithObjectPrx__:OBJECTPRX->ice_getRouter()]; +} +-(id) ice_router:(id<ICERouterPrx>)router +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_router( + Ice::RouterPrx::uncheckedCast(Ice::ObjectPrx([(ICEObjectPrx*)router objectPrx__])))]; +} +-(id<ICELocatorPrx>) ice_getLocator +{ + return (id<ICELocatorPrx>)[ICELocatorPrx objectPrxWithObjectPrx__:OBJECTPRX->ice_getLocator()]; +} +-(id) ice_locator:(id<ICELocatorPrx>)locator +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_locator( + Ice::LocatorPrx::uncheckedCast(Ice::ObjectPrx([(ICEObjectPrx*)locator objectPrx__])))]; +} +// -(BOOL) ice_isCollocationOptimized +// { +// return OBJECTPRX->ice_isCollocationOptimized(); +// } +// -(id) ice_collocationOptimized:(BOOL)collocOptimized +// { +// return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_collocationOptimized(collocOptimized)]; +// } +-(id) ice_twoway +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_twoway()]; +} +-(BOOL) ice_isTwoway +{ + return OBJECTPRX->ice_isTwoway(); +} +-(id) ice_oneway +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_oneway()]; +} +-(BOOL) ice_isOneway +{ + return OBJECTPRX->ice_isOneway(); +} +-(id) ice_batchOneway +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_batchOneway()]; +} +-(BOOL) ice_isBatchOneway +{ + return OBJECTPRX->ice_isBatchOneway(); +} +-(id) ice_datagram +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_datagram()]; +} +-(BOOL) ice_isDatagram +{ + return OBJECTPRX->ice_isDatagram(); +} +-(id) ice_batchDatagram +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_batchDatagram()]; +} +-(BOOL) ice_isBatchDatagram +{ + return OBJECTPRX->ice_isBatchDatagram(); +} +-(id) ice_compress:(BOOL)compress +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_compress(compress)]; +} +-(id) ice_timeout:(int)timeout +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_timeout(timeout)]; +} +-(id) ice_connectionId:(NSString*)connectionId +{ + return [[self class] objectPrxWithObjectPrx__:OBJECTPRX->ice_connectionId(fromNSString(connectionId))]; +} +-(id<ICEConnection>) ice_getConnection +{ + NSException* nsex = nil; + try + { + return [ICEConnection wrapperWithCxxObject:OBJECTPRX->ice_getConnection().get()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(id<ICEConnection>) ice_getCachedConnection +{ + NSException* nsex = nil; + try + { + return [ICEConnection wrapperWithCxxObject:OBJECTPRX->ice_getCachedConnection().get()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(void) ice_flushBatchRequests +{ + NSException* nsex = nil; + try + { + OBJECTPRX->ice_flushBatchRequests(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(id<ICEAsyncResult>) begin_ice_flushBatchRequests +{ + return beginCppCall(^(Ice::AsyncResultPtr& result) + { + result = OBJECTPRX->begin_ice_flushBatchRequests(); + }, self); +} +-(id<ICEAsyncResult>) begin_ice_flushBatchRequests:(void(^)(ICEException*))exception +{ + return [self begin_ice_flushBatchRequests:exception sent:nil]; +} +-(id<ICEAsyncResult>) begin_ice_flushBatchRequests:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent +{ + return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) + { + result = OBJECTPRX->begin_ice_flushBatchRequests(cb); + }, + ^(const Ice::AsyncResultPtr& result) { + OBJECTPRX->end_ice_flushBatchRequests(result); + }, + exception, sent, self); +} +-(void) end_ice_flushBatchRequests:(id<ICEAsyncResult>)result +{ + endCppCall(^(const Ice::AsyncResultPtr& r) + { + OBJECTPRX->end_ice_flushBatchRequests(r); + }, result); +} +@end diff --git a/objc/src/Ice/ProxyI.h b/objc/src/Ice/ProxyI.h new file mode 100644 index 00000000000..771b6c1b177 --- /dev/null +++ b/objc/src/Ice/ProxyI.h @@ -0,0 +1,32 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Proxy.h> + +#include <IceCpp/Proxy.h> + +@interface ICEAsyncResult : NSObject<ICEAsyncResult> +{ +@private + void* asyncResult__; + NSString* operation_; + id<ICEObjectPrx> proxy_; +} +-(ICEAsyncResult*)initWithAsyncResult__:(const Ice::AsyncResultPtr&)arg operation:(NSString*)op proxy:(id<ICEObjectPrx>)p; +-(Ice::AsyncResult*) asyncResult__; ++(ICEAsyncResult*)asyncResultWithAsyncResult__:(const Ice::AsyncResultPtr&)arg; ++(ICEAsyncResult*)asyncResultWithAsyncResult__:(const Ice::AsyncResultPtr&)arg operation:(NSString*)op proxy:(id<ICEObjectPrx>)p; +-(NSString*)operation; +@end + +@interface ICEObjectPrx () +-(ICEObjectPrx*)initWithObjectPrx__:(const Ice::ObjectPrx&)arg; +-(IceProxy::Ice::Object*) objectPrx__; ++(ICEObjectPrx*)objectPrxWithObjectPrx__:(const Ice::ObjectPrx&)arg; +@end diff --git a/objc/src/Ice/Request.h b/objc/src/Ice/Request.h new file mode 100644 index 00000000000..31fa49e1a95 --- /dev/null +++ b/objc/src/Ice/Request.h @@ -0,0 +1,23 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Object.h> + +@interface ICERequest : NSObject<ICERequest> +{ + @private + ICECurrent* current; + id<ICEInputStream> is; + id<ICEOutputStream> os; + BOOL needReset; +} ++(id) request:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os; +-(id) init:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os; +-(BOOL) callDispatch:(ICEObject*)servant; +@end diff --git a/objc/src/Ice/Request.m b/objc/src/Ice/Request.m new file mode 100644 index 00000000000..45d32a89097 --- /dev/null +++ b/objc/src/Ice/Request.m @@ -0,0 +1,59 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <Request.h> + +@implementation ICERequest +-(ICECurrent*) getCurrent +{ + return current; +} + ++(id) request:(ICECurrent*)current is:(id<ICEInputStream>)is os:(id<ICEOutputStream>)os +{ + ICERequest* result = [((ICERequest*)[ICERequest alloc]) init:current is:is os:os]; + [result autorelease]; + return result; +} + +-(id) init:(ICECurrent*)current_ is:(id<ICEInputStream>)is_ os:(id<ICEOutputStream>)os_ +{ + if(![super init]) + { + return nil; + } + current = [current_ retain]; + is = [is_ retain]; + os = [os_ retain]; + needReset = NO; + return self; +} + +-(BOOL) callDispatch:(ICEObject*)servant +{ + if(needReset == NO) + { + needReset = YES; + } + else + { + [is rewind]; + [os reset:NO]; + } + return [servant dispatch__:current is:is os:os]; +} + +-(void) dealloc +{ + [current release]; + [is release]; + [os release]; + [super dealloc]; +} +@end diff --git a/objc/src/Ice/SlicedData.mm b/objc/src/Ice/SlicedData.mm new file mode 100644 index 00000000000..040a391c2a9 --- /dev/null +++ b/objc/src/Ice/SlicedData.mm @@ -0,0 +1,89 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in +// the ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <SlicedDataI.h> +#import <Util.h> + +#import <IceCpp/SlicedData.h> + +@implementation ICESlicedData + +-(id) initWithSlicedData:(Ice::SlicedData*)slicedData +{ + self = [super init]; + if(!self) + { + return nil; + } + self->slicedData__ = slicedData; + self->slicedData__->__incRef(); + return self; +} + +-(void) dealloc +{ + self->slicedData__->__decRef(); + [super dealloc]; +} + +-(Ice::SlicedData*) slicedData +{ + return slicedData__; +} + +@end + +@implementation ICEUnknownSlicedObject + +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + self->unknownTypeId_ = nil; + self->slicedData_ = nil; + return self; +} + +-(void) dealloc +{ + [slicedData_ release]; + [unknownTypeId_ release]; + [super dealloc]; +} + +-(NSString*) getUnknownTypeId +{ + return [[unknownTypeId_ retain] autorelease]; +} + +-(ICESlicedData*) getSlicedData +{ + return [[slicedData_ retain] autorelease]; +} + +-(void) write__:(id<ICEOutputStream>)os +{ + [os startObject:slicedData_]; + [os endObject]; +} + +-(void) read__:(id<ICEInputStream>)is +{ + [is startObject]; + slicedData_ = [is endObject:YES]; + + // Initialize unknown type ID to type ID of first slice. + Ice::SlicedData* slicedData = [((ICESlicedData*)slicedData_) slicedData]; + assert(!slicedData->slices.empty()); + unknownTypeId_ = toNSString(slicedData->slices[0]->typeId); +} +@end diff --git a/objc/src/Ice/SlicedDataI.h b/objc/src/Ice/SlicedDataI.h new file mode 100644 index 00000000000..665bee44617 --- /dev/null +++ b/objc/src/Ice/SlicedDataI.h @@ -0,0 +1,21 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in +// the ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/SlicedData.h> + +#include <IceCpp/SlicedData.h> + +@interface ICESlicedData : NSObject<ICESlicedData> +{ +@private + Ice::SlicedData* slicedData__; +} +-(id) initWithSlicedData:(Ice::SlicedData*)slicedData; +-(Ice::SlicedData*) slicedData; +@end diff --git a/objc/src/Ice/Stream.mm b/objc/src/Ice/Stream.mm new file mode 100644 index 00000000000..d3dc9a7e780 --- /dev/null +++ b/objc/src/Ice/Stream.mm @@ -0,0 +1,3440 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <StreamI.h> +#import <CommunicatorI.h> +#import <ProxyI.h> +#import <Util.h> +#import <ObjectI.h> +#import <SlicedDataI.h> +#import <VersionI.h> + +#import <objc/Ice/LocalException.h> + +#include <IceCpp/Stream.h> +#include <IceCpp/SlicedData.h> + +#import <objc/runtime.h> + +id ICENone = nil; + +namespace IceObjC +{ + +class ObjectWriter : public Ice::ObjectWriter +{ +public: + + ObjectWriter(ICEObject* obj, ICEOutputStream* stream) : _obj(obj), _stream(stream) + { + } + + virtual void + write(const Ice::OutputStreamPtr& stream) const + { + @try + { + [_obj write__:_stream]; + } + @catch(id ex) + { + rethrowCxxException(ex); + } + } + + virtual void ice_preMarshal() + { + [_obj ice_preMarshal]; + } + +private: + + ICEObject* _obj; + ICEOutputStream* _stream; +}; + +class ObjectReader : public Ice::ObjectReader +{ +public: + + // We must explicitely CFRetain/CFRelease so that the garbage + // collector does not trash the _obj. + ObjectReader(ICEObject* obj) : _obj(obj) + { + CFRetain(_obj); + } + + virtual ~ObjectReader() + { + CFRelease(_obj); + } + + virtual void + read(const Ice::InputStreamPtr& stream) + { + @try + { + // + // TODO: explain why calling getWrapperWithCxxObjectNoAutoRelease is safe here + // + ICEInputStream* is = [ICEInputStream getWrapperWithCxxObjectNoAutoRelease:stream.get()]; + assert(is != 0); + [_obj read__:is]; + } + @catch(id ex) + { + rethrowCxxException(ex); + } + } + + ICEObject* + getObject() + { + return _obj; + } + + virtual void ice_postUnmarshal() + { + [_obj ice_postUnmarshal]; + } + +private: + + ICEObject* _obj; +}; +typedef IceUtil::Handle<ObjectReader> ObjectReaderPtr; + +class ReadObjectBase : public Ice::ReadObjectCallback +{ +public: + + ReadObjectBase(Class expectedType) : _expectedType(expectedType) + { + } + + void checkType(ICEObject*); + +private: + + Class _expectedType; +}; + +void +ReadObjectBase::checkType(ICEObject* o) +{ + if(o != nil && ![o isKindOfClass:_expectedType]) + { + NSString* actualType = [o ice_id]; + NSString* expectedType = [_expectedType ice_staticId]; + NSString* reason = [NSString stringWithFormat:@"expected element of type `%@' but received `%@'", + expectedType, actualType]; + + @throw [ICEUnexpectedObjectException unexpectedObjectException:__FILE__ + line:__LINE__ + reason_:reason + type:actualType + expectedType:expectedType]; + } +} + +class ReadObject : public ReadObjectBase +{ +public: + + ReadObject(ICEObject** addr, Class expectedType, bool autorelease) : + ReadObjectBase(expectedType), _addr(addr), _autorelease(autorelease) + { + } + + virtual void + invoke(const Ice::ObjectPtr& obj) + { + @try + { + if(obj) + { + ICEObject* o = ObjectReaderPtr::dynamicCast(obj)->getObject(); + checkType(o); + *_addr = [o retain]; + if(_autorelease) + { + [*_addr autorelease]; + } + } + else + { + *_addr = nil; + } + } + @catch(id ex) + { + rethrowCxxException(ex); + } + } + +private: + + ICEObject** _addr; + bool _autorelease; +}; + +class ReadObjectAtIndex : public ReadObjectBase +{ +public: + + ReadObjectAtIndex(NSMutableArray* array, ICEInt index, Class expectedType) : + ReadObjectBase(expectedType), _array(array), _index(index) + { + } + + virtual void + invoke(const Ice::ObjectPtr& obj) + { + @try + { + if(obj) + { + ICEObject* o = ObjectReaderPtr::dynamicCast(obj)->getObject(); + checkType(o); + [_array replaceObjectAtIndex:_index withObject:o]; + } + } + @catch(id ex) + { + rethrowCxxException(ex); + } + } + +private: + + NSMutableArray* _array; + ICEInt _index; +}; + +class ReadObjectForKey : public ReadObjectBase +{ +public: + + // We must explicitely CFRetain/CFRelease so that the garbage + // collector does not trash the _key. + ReadObjectForKey(NSMutableDictionary* dict, id key, Class expectedType) : + ReadObjectBase(expectedType), _dict(dict), _key(key) + { + CFRetain(_key); + } + + virtual ~ReadObjectForKey() + { + CFRelease(_key); + } + + virtual void + invoke(const Ice::ObjectPtr& obj) + { + @try + { + if(obj) + { + ICEObject* o = ObjectReaderPtr::dynamicCast(obj)->getObject(); + checkType(o); + [_dict setObject:o forKey:_key]; + } + else + { + [_dict setObject:[NSNull null] forKey:_key]; + } + } + @catch(id ex) + { + rethrowCxxException(ex); + } + } + +private: + + NSMutableDictionary* _dict; + id _key; +}; + +class ExceptionWriter : public Ice::UserExceptionWriter +{ +public: + + ExceptionWriter(const Ice::CommunicatorPtr& communicator, ICEOutputStream* stream, ICEUserException* ex) : + Ice::UserExceptionWriter(communicator), + _stream(stream), + _ex(ex) + { + + } + + virtual bool + usesClasses() const + { + return [_ex usesClasses__]; + } + + virtual std::string + ice_name() const + { + return [[_ex ice_name] UTF8String]; + } + + virtual Ice::UserException* + ice_clone() const + { + return new ExceptionWriter(*this); + } + + virtual void + ice_throw() const + { + throw *this; + } + + virtual void + write(const Ice::OutputStreamPtr& stream) const + { + [_ex write__:_stream]; + } + +private: + + ICEOutputStream* _stream; + ICEUserException* _ex; +}; + +class ExceptionReader : public Ice::UserExceptionReader +{ +public: + + ExceptionReader(const Ice::CommunicatorPtr& communicator, ICEInputStream* stream, ICEUserException* ex) : + Ice::UserExceptionReader(communicator), + _stream(stream), + _ex(ex) + { + } + + void + read(const Ice::InputStreamPtr& stream) const + { + [_ex read__:_stream]; + } + + virtual std::string + ice_name() const + { + return [[_ex ice_name] UTF8String]; + } + + virtual bool + usesClasses() const + { + return [_ex usesClasses__]; + } + + virtual Ice::UserException* + ice_clone() const + { + assert(false); + return 0; + } + + virtual void + ice_throw() const + { + throw *this; + } + + ICEUserException* getException() const + { + return _ex; + } + +private: + + ICEInputStream* _stream; + ICEUserException* _ex; +}; + +class UserExceptionReaderFactoryI : public Ice::UserExceptionReaderFactory +{ +public: + + UserExceptionReaderFactoryI(const Ice::CommunicatorPtr& communicator, ICEInputStream* is) : + _communicator(communicator), + _is(is) + { + } + + virtual void createAndThrow(const std::string& typeId) const + { + ICEUserException* ex = nil; + std::string objcId = toObjCSliceId(typeId, + [[ICECommunicator wrapperWithCxxObject:_communicator.get()] getPrefixTable]); + Class c = objc_lookUpClass(objcId.c_str()); + if(c != nil) + { + ex = [[c alloc] init]; + throw ExceptionReader(_communicator, _is, ex); + } + } + +private: + + Ice::CommunicatorPtr _communicator; + ICEInputStream* _is; +}; + +} + +@interface ICEInternalNone : NSObject +@end + +@implementation ICEInternalNone ++(void)load +{ + ICENone = [[ICEInternalNone alloc] init]; +} +-(id) copyWithZone:(NSZone *)zone +{ + return self; +} +-(id) retain +{ + return self; +} +-(NSUInteger) retainCount +{ + return NSUIntegerMax; +} +-(oneway void) release +{ +} +-(id) autorelease +{ + return self; +} +@end + +@implementation ICEInputStream +-(id) initWithCxxObject:(IceUtil::Shared*)cxxObject +{ + self = [super initWithCxxObject:cxxObject]; + if(!self) + { + return nil; + } + is_ = dynamic_cast<Ice::InputStream*>(cxxObject); + return self; +} + ++(Ice::Object*)createObjectReader:(ICEObject*)obj +{ + return new IceObjC::ObjectReader(obj); +} + +-(Ice::InputStream*) is +{ + return is_; +} + +// @protocol ICEInputStream methods + +-(id<ICECommunicator>) communicator +{ + return [ICECommunicator wrapperWithCxxObject:is_->communicator().get()]; +} + +-(void) sliceObjects:(BOOL)b +{ + NSException* nsex = nil; + try + { + is_->sliceObjects(b); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(BOOL)readBool +{ + NSException* nsex = nil; + try + { + bool value; + is_->read(value); + return value; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return NO; // Keep the compiler happy. +} + +-(NSMutableData*) readBoolSeq +{ + return [[self newBoolSeq] autorelease]; +} + +-(NSMutableData*) newBoolSeq +{ + NSException* nsex = nil; + try + { + std::pair<const bool*, const bool*> seq; + IceUtil::ScopedArray<bool> result; + is_->read(seq, result); + return [[NSMutableData alloc] initWithBytes:seq.first length:(seq.second - seq.first) * sizeof(BOOL)]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICEByte) readByte +{ + NSException* nsex = nil; + try + { + Ice::Byte value; + is_->read(value); + return value; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return 0; // Keep the compiler happy. +} + +-(NSMutableData*) readByteSeq +{ + return [[self newByteSeq] autorelease]; +} + +-(NSMutableData*) newByteSeq +{ + NSException* nsex = nil; + try + { + std::pair<const Ice::Byte*, const Ice::Byte*> seq; + is_->read(seq); + return [[NSMutableData alloc] initWithBytes:seq.first length:(seq.second - seq.first)]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; +} + +-(NSData*) readByteSeqNoCopy +{ + NSException* nsex = nil; + try + { + std::pair<const Ice::Byte*, const Ice::Byte*> seq; + is_->read(seq); + return [NSData dataWithBytesNoCopy:const_cast<Ice::Byte*>(seq.first) + length:(seq.second - seq.first) freeWhenDone:NO]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICEShort) readShort +{ + NSException* nsex = nil; + try + { + Ice::Short value; + is_->read(value); + return value; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return 0; // Keep the compiler happy. +} + +-(NSMutableData*) readShortSeq +{ + return [[self newShortSeq] autorelease]; +} + +-(NSMutableData*) newShortSeq +{ + NSException* nsex = nil; + try + { + std::pair<const Ice::Short*, const Ice::Short*> seq; + IceUtil::ScopedArray<Ice::Short> result; + is_->read(seq, result); + return [[NSMutableData alloc] initWithBytes:seq.first length:(seq.second - seq.first) * sizeof(ICEShort)]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICEInt) readInt +{ + NSException* nsex = nil; + try + { + Ice::Int value; + is_->read(value); + return value; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return 0; // Keep the compiler happy. +} + +-(NSMutableData*) readIntSeq +{ + return [[self newIntSeq] autorelease]; +} + +-(NSMutableData*) newIntSeq +{ + NSException* nsex = nil; + try + { + std::pair<const Ice::Int*, const Ice::Int*> seq; + IceUtil::ScopedArray<Ice::Int> result; + is_->read(seq, result); + return [[NSMutableData alloc] initWithBytes:seq.first length:(seq.second - seq.first) * sizeof(ICEInt)]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICELong) readLong +{ + NSException* nsex = nil; + try + { + Ice::Long value; + is_->read(value); + return value; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return 0; // Keep the compiler happy. +} + +-(NSMutableData*) readLongSeq +{ + return [[self newLongSeq] autorelease]; +} + +-(NSMutableData*) newLongSeq +{ + NSException* nsex = nil; + try + { + std::pair<const Ice::Long*, const Ice::Long*> seq; + IceUtil::ScopedArray<Ice::Long> result; + is_->read(seq, result); + return [[NSMutableData alloc] initWithBytes:seq.first length:(seq.second - seq.first) * sizeof(ICELong)]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICEFloat) readFloat +{ + NSException* nsex = nil; + try + { + Ice::Float value; + is_->read(value); + return value; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return 0.f; // Keep the compiler happy. +} + +-(NSMutableData*) readFloatSeq +{ + return [[self newFloatSeq] autorelease]; +} + +-(NSMutableData*) newFloatSeq +{ + NSException* nsex = nil; + try + { + std::pair<const Ice::Float*, const Ice::Float*> seq; + IceUtil::ScopedArray<Ice::Float> result; + is_->read(seq, result); + return [[NSMutableData alloc] initWithBytes:seq.first length:(seq.second - seq.first) * sizeof(ICEFloat)]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICEDouble) readDouble +{ + NSException* nsex = nil; + try + { + Ice::Double value; + is_->read(value); + return value; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return 0.0; // Keep the compiler happy. +} + +-(NSMutableData*) readDoubleSeq +{ + return [[self newDoubleSeq] autorelease]; +} + +-(NSMutableData*) newDoubleSeq +{ + NSException* nsex = nil; + try + { + std::pair<const Ice::Double*, const Ice::Double*> seq; + IceUtil::ScopedArray<Ice::Double> result; + is_->read(seq, result); + return [[NSMutableData alloc] initWithBytes:seq.first length:(seq.second - seq.first) * sizeof(ICEDouble)]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(NSMutableString*)readString +{ + return [[self newString] autorelease]; +} + +-(NSMutableString*)newString +{ + NSException* nsex = nil; + try + { + std::string value; + is_->read(value); + return toNSMutableString(value); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(NSMutableArray*) readStringSeq +{ + return [[self newStringSeq] autorelease]; +} + +-(NSMutableArray*) newStringSeq +{ + NSException* nsex = nil; + try + { + Ice::StringSeq value; + is_->read(value); + return toNSArray(value); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(ICEInt) readEnumerator:(ICEInt)min max:(ICEInt)max +{ + NSException* nsex = nil; + ICEInt val = 0; // Keep the compiler happy. + try + { + if(is_->getEncoding() == Ice::Encoding_1_0) + { + if(max <= 0x7f) + { + val = [self readByte]; + } + else if(max <= 0x7fff) + { + val = [self readShort]; + } + else + { + val = [self readInt]; + } + } + else + { + val = [self readSize]; + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + if(val > max || val < min) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"enumerator out of range"]; + } + return val; +} + +// +// Size of an enum. Slice enum underling type is specified as ICEInt so +// all Slice enums have the same size as an ICEInt. +// +#define ENUM_SIZE sizeof(ICEInt) + +-(NSMutableData*) readEnumSeq:(ICEInt)min max:(ICEInt)max +{ + return [[self newEnumSeq:(ICEInt)min max:(ICEInt)max] autorelease]; +} + +-(NSMutableData*) newEnumSeq:(ICEInt)min max:(ICEInt)max +{ + int minWireSize; + if(max <= 0x7f) + { + minWireSize = 1; + } + else if(max <= 0x7fff) + { + minWireSize = 2; + } + else + { + minWireSize = 4; + } + + NSException* nsex = nil; + NSMutableData* ret = 0; + try + { + int count = is_->readAndCheckSeqSize(minWireSize); + if((ret = [[NSMutableData alloc] initWithLength:(count * ENUM_SIZE)]) == 0) + { + return ret; + } + + ICEInt *v = (ICEInt *)[ret bytes]; + if(max <= 0x7f) + { + while(count-- > 0) + { + *v = [self readByte]; + if(*v > max || *v < min) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ + reason_:@"enumerator out of range"]; + } + ++v; + } + } + else if(max <= 0x7fff) + { + while(count-- > 0) + { + *v = [self readShort]; + if(*v > max || *v < min) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ + reason_:@"enumerator out of range"]; + } + ++v; + } + } + else + { + while(count-- > 0) + { + *v = [self readInt]; + if(*v > max || *v < min) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ + reason_:@"enumerator out of range"]; + } + ++v; + } + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return ret; +} + +-(ICEInt) readSize +{ + NSException* nsex = nil; + try + { + return is_->readSize(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return 0; // Keep the compiler happy. +} + +-(ICEInt) readAndCheckSeqSize:(ICEInt)minSize +{ + NSException* nsex = nil; + try + { + return is_->readAndCheckSeqSize(minSize); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return 0; // Keep the compiler happy. +} + +-(id<ICEObjectPrx>) readProxy:(Class)type +{ + return [[self newProxy:type] autorelease]; +} + +-(id<ICEObjectPrx>) newProxy:(Class)type +{ + NSException* nsex = nil; + try + { + Ice::ObjectPrx p = is_->readProxy(); + if(!p) + { + return nil; + } + else + { + return [[type alloc] initWithObjectPrx__:p]; + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} +-(void) readObject:(ICEObject**)object +{ + [self readObject:object expectedType:[ICEObject class]]; +} +-(void) readObject:(ICEObject**)object expectedType:(Class)type +{ + NSException* nsex = nil; + try + { + is_->readObject(new IceObjC::ReadObject(object, type, true)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} +-(void) newObject:(ICEObject*ICE_STRONG_QUALIFIER*)object +{ + [self newObject:object expectedType:[ICEObject class]]; +} +-(void) newObject:(ICEObject*ICE_STRONG_QUALIFIER*)object expectedType:(Class)type +{ + NSException* nsex = nil; + try + { + is_->readObject(new IceObjC::ReadObject(object, type, false)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(NSMutableArray*) readObjectSeq:(Class)type +{ + return [[self newObjectSeq:(Class)type] autorelease]; +} + +-(NSMutableArray*) newObjectSeq:(Class)type +{ + ICEInt sz = [self readAndCheckSeqSize:1]; + NSMutableArray* arr = [[NSMutableArray alloc] initWithCapacity:sz]; + NSException* nsex = nil; + try + { + int i; + id null = [NSNull null]; + for(i = 0; i < sz; i++) + { + [arr addObject:null]; + is_->readObject(new IceObjC::ReadObjectAtIndex(arr, i, type)); + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + [arr release]; + @throw nsex; + } + return arr; +} + +-(NSMutableDictionary*) readObjectDict:(Class)keyHelper expectedType:(Class)type +{ + return [[self newObjectDict:(Class)keyHelper expectedType:(Class)type] autorelease]; +} + +-(NSMutableDictionary*) newObjectDict:(Class)keyHelper expectedType:(Class)type +{ + ICEInt sz = [self readAndCheckSeqSize:[keyHelper minWireSize] + 1]; + NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] initWithCapacity:sz]; + id key = nil; + for(int i = 0; i < sz; ++i) + { + @try + { + key = [keyHelper readRetained:self]; + } + @catch(id ex) + { + [dictionary release]; + @throw ex; + } + + NSException* nsex = nil; + try + { + is_->readObject(new IceObjC::ReadObjectForKey(dictionary, key, type)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + [key release]; + [dictionary release]; + @throw nsex; + } + [key release]; + } + return dictionary; +} + +-(NSMutableArray*) readSequence:(Class)helper +{ + return [[self newSequence:(Class)helper] autorelease]; +} + +-(NSMutableArray*) newSequence:(Class)helper +{ + ICEInt sz = [self readAndCheckSeqSize:[helper minWireSize]]; + NSMutableArray* arr = [[NSMutableArray alloc] initWithCapacity:sz]; + id obj = nil; + @try + { + while(sz-- > 0) + { + obj = [helper readRetained:self]; + if(obj == nil) + { + [arr addObject:[NSNull null]]; + } + else + { + [arr addObject:obj]; + [obj release]; + } + } + } + @catch(id ex) + { + [arr release]; + [obj release]; + @throw ex; + } + return arr; +} + +-(NSMutableDictionary*) readDictionary:(ICEKeyValueTypeHelper)helper +{ + return [[self newDictionary:(ICEKeyValueTypeHelper)helper] autorelease]; +} + +-(NSMutableDictionary*) newDictionary:(ICEKeyValueTypeHelper)helper +{ + ICEInt sz = [self readAndCheckSeqSize:[helper.key minWireSize] + [helper.value minWireSize]]; + NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] initWithCapacity:sz]; + id key = nil; + id value = nil; + @try + { + while(sz-- > 0) + { + key = [helper.key readRetained:self]; + value = [helper.value readRetained:self]; + if(value == nil) + { + [dictionary setObject:[NSNull null] forKey:key]; + } + else + { + [dictionary setObject:value forKey:key]; + [value release]; + } + [key release]; + } + } + @catch(id ex) + { + [dictionary release]; + [key release]; + [value release]; + @throw ex; + } + return dictionary; +} + +-(BOOL) readOptional:(ICEInt)tag format:(ICEOptionalFormat)format +{ + NSException* nsex = nil; + try + { + return is_->readOptional(tag, static_cast<Ice::OptionalFormat>(format)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return NO; // Keep the compiler happy. +} + +-(void) throwException +{ + ICEUserException* ex = nil; + NSException* nsex = nil; + try + { + Ice::UserExceptionReaderFactoryPtr factory = + new IceObjC::UserExceptionReaderFactoryI(is_->communicator().get(), self); + is_->throwException(factory); + } + catch(const IceObjC::ExceptionReader& reader) + { + ex = reader.getException(); + @throw [ex autorelease]; // NOTE: exceptions are always auto-released, no need for the caller to do it. + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + @throw nsex; + } +} + +-(void) startObject +{ + NSException* nsex = nil; + try + { + is_->startObject(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(id<ICESlicedData>) endObject:(BOOL)preserve +{ + NSException* nsex = nil; + try + { + Ice::SlicedDataPtr slicedData = is_->endObject(preserve); + return slicedData ? [[ICESlicedData alloc] initWithSlicedData:slicedData.get()] : nil; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return nil; // Make compiler happy +} + +-(void) startException +{ + NSException* nsex = nil; + try + { + is_->startException(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(id<ICESlicedData>) endException:(BOOL)preserve +{ + NSException* nsex = nil; + try + { + Ice::SlicedDataPtr slicedData = is_->endException(preserve); + return slicedData ? [[ICESlicedData alloc] initWithSlicedData:slicedData.get()] : nil; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return nil; // Make compiler happy +} + +-(void) startSlice +{ + NSException* nsex = nil; + try + { + is_->startSlice(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) endSlice +{ + NSException* nsex = nil; + try + { + is_->endSlice(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) skipSlice +{ + NSException* nsex = nil; + try + { + is_->skipSlice(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(ICEEncodingVersion*) startEncapsulation +{ + NSException* nsex = nil; + try + { + return [ICEEncodingVersion encodingVersionWithEncodingVersion:is_->startEncapsulation()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return nil; // Keep the compiler happy. +} + +-(void) endEncapsulation +{ + NSException* nsex = nil; + try + { + is_->endEncapsulation(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(ICEEncodingVersion*) skipEncapsulation +{ + NSException* nsex = nil; + try + { + return [ICEEncodingVersion encodingVersionWithEncodingVersion:is_->skipEncapsulation()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return nil; // Keep the compiler happy. +} + +-(ICEEncodingVersion*) getEncoding +{ + return [ICEEncodingVersion encodingVersionWithEncodingVersion:is_->getEncoding()]; +} + +-(void) readPendingObjects +{ + NSException* nsex = nil; + try + { + is_->readPendingObjects(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) rewind +{ + NSException* nsex = nil; + try + { + is_->rewind(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) skip:(ICEInt)sz +{ + NSException* nsex = nil; + try + { + is_->skip(sz); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) skipSize +{ + NSException* nsex = nil; + try + { + is_->skipSize(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +@end + +@implementation ICEOutputStream +-(id) initWithCxxObject:(IceUtil::Shared*)cxxObject +{ + self = [super initWithCxxObject:cxxObject]; + if(!self) + { + return nil; + } + os_ = dynamic_cast<Ice::OutputStream*>(cxxObject); + objectWriters_ = 0; + return self; +} + +-(Ice::OutputStream*) os +{ + return os_; +} + +-(void) dealloc +{ + if(objectWriters_) + { + delete objectWriters_; + } + [super dealloc]; +} + +-(void) finalize +{ + if(objectWriters_) + { + delete objectWriters_; + } + [super finalize]; +} + +// @protocol ICEOutputStream methods + +-(id<ICECommunicator>) communicator +{ + return [ICECommunicator wrapperWithCxxObject:os_->communicator().get()]; +} + +-(void)writeBool:(BOOL)v +{ + NSException* nsex = nil; + try + { + os_->write(static_cast<bool>(v)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeBoolSeq:(NSData*)v +{ + NSException* nsex = nil; + try + { + v == nil ? os_->writeSize(0) + : os_->write((bool*)[v bytes], (bool*)[v bytes] + [v length] / sizeof(BOOL)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeByte:(ICEByte)v +{ + NSException* nsex = nil; + try + { + os_->write(static_cast<Ice::Byte>(v)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeByteSeq:(NSData*)v +{ + NSException* nsex = nil; + try + { + v == nil ? os_->writeSize(0) + : os_->write((ICEByte*)[v bytes], (ICEByte*)[v bytes] + [v length]); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeShort:(ICEShort)v +{ + NSException* nsex = nil; + try + { + os_->write(static_cast<Ice::Short>(v)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeShortSeq:(NSData*)v +{ + NSException* nsex = nil; + try + { + v == nil ? os_->writeSize(0) + : os_->write((ICEShort*)[v bytes], (ICEShort*)[v bytes] + [v length] / sizeof(ICEShort)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeInt:(ICEInt)v +{ + NSException* nsex = nil; + try + { + os_->write(static_cast<Ice::Int>(v)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeIntSeq:(NSData*)v +{ + NSException* nsex = nil; + try + { + v == nil ? os_->writeSize(0) + : os_->write((ICEInt*)[v bytes], (ICEInt*)[v bytes] + [v length] / sizeof(ICEInt)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeLong:(ICELong)v +{ + NSException* nsex = nil; + try + { + os_->write(static_cast<Ice::Long>(v)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeLongSeq:(NSData*)v +{ + NSException* nsex = nil; + try + { + v == nil ? os_->writeSize(0) + : os_->write((ICELong*)[v bytes], (ICELong*)[v bytes] + [v length] / sizeof(ICELong)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeFloat:(ICEFloat)v +{ + NSException* nsex = nil; + try + { + os_->write(static_cast<Ice::Float>(v)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeFloatSeq:(NSData*)v +{ + NSException* nsex = nil; + try + { + v == nil ? os_->writeSize(0) + : os_->write((ICEFloat*)[v bytes], (ICEFloat*)[v bytes] + [v length] / sizeof(ICEFloat)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeDouble:(ICEDouble)v +{ + NSException* nsex = nil; + try + { + os_->write(static_cast<Ice::Double>(v)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeDoubleSeq:(NSData*)v +{ + NSException* nsex = nil; + try + { + v == nil ? os_->writeSize(0) + : os_->write((ICEDouble*)[v bytes], + (ICEDouble*)[v bytes] + [v length] / sizeof(ICEDouble)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeString:(NSString*)v +{ + NSException* nsex = nil; + try + { + os_->write(fromNSString(v)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeStringSeq:(NSArray*)v +{ + NSException* nsex = nil; + try + { + std::vector<std::string> s; + os_->write(fromNSArray(v, s)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void)writeSequence:(NSArray*)arr helper:(Class)helper +{ + if(arr == nil) + { + [self writeSize:0]; + return; + } + + [self writeSize:[arr count]]; + for(id i in arr) + { + [helper write:(i == [NSNull null] ? nil : i) stream:self]; + } +} + +-(void) writeDictionary:(NSDictionary*)dictionary helper:(ICEKeyValueTypeHelper)helper +{ + if(dictionary == nil) + { + [self writeSize:0]; + return; + } + + [self writeSize:[dictionary count]]; + NSEnumerator* e = [dictionary keyEnumerator]; + id key; + while((key = [e nextObject])) + { + if(key == [NSNull null]) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"illegal NSNull value"]; + } + [helper.key write:key stream:self]; + NSObject *obj = [dictionary objectForKey:key]; + [helper.value write:(obj == [NSNull null] ? nil : obj) stream:self]; + } +} + +-(BOOL) writeOptional:(ICEInt)tag format:(ICEOptionalFormat)format +{ + NSException* nsex = nil; + try + { + return os_->writeOptional(tag, static_cast<Ice::OptionalFormat>(format)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } + return NO; // Keep the compiler happy. +} + +-(void) writeEnumerator:(ICEInt)v min:(int)min max:(int)max +{ + if(v > max || v < min) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"enumerator out of range"]; + } + NSException* nsex = nil; + try + { + if(os_->getEncoding() == Ice::Encoding_1_0) + { + if(max <= 0x7f) + { + os_->write(static_cast<Ice::Byte>(v)); + } + else if(max <= 0x7fff) + { + os_->write(static_cast<Ice::Short>(v)); + } + else + { + os_->write(static_cast<Ice::Int>(v)); + } + } + else + { + os_->writeSize(static_cast<Ice::Int>(v)); + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +// +// The C standard does not fix the size of an enum. The compiler is free +// to choose an enum size that depends on the number of enumerators, and +// the choice may vary depending on the processor. This means that we don't +// know what the size of an enum is until run time, so the marshaling +// has to be generic and copy with enums that could be 8, 16, or 32 bits wide. +// +-(void) writeEnumSeq:(NSData*)v min:(ICEInt)min max:(ICEInt)max +{ + NSException* nsex = nil; + try + { + int count = v == nil ? 0 : [v length] / ENUM_SIZE; + [self writeSize:count]; + if(count == 0) + { + return; + } + + const ICEInt* p = (const ICEInt*)[v bytes]; + if(max <= 0x7f) + { + while(count-- > 0) + { + if(*p > max || *p < min) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ + reason_:@"enumerator out of range"]; + } + [self writeByte:*p++]; + } + } + else if(max <= 0x7fff) + { + while(count-- > 0) + { + if(*p > max || *p < min) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ + reason_:@"enumerator out of range"]; + } + [self writeShort:*p++]; + } + } + else + { + while(count-- > 0) + { + if(*p > max || *p < min) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ + reason_:@"enumerator out of range"]; + } + [self writeInt:*p++]; + } + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeSize:(ICEInt)v +{ + NSException* nsex = nil; + try + { + os_->writeSize(v); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + + +-(void) writeProxy:(id<ICEObjectPrx>)v +{ + NSException* nsex = nil; + try + { + os_->writeProxy([(ICEObjectPrx*)v objectPrx__]); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeObject:(ICEObject*)v +{ + NSException* nsex = nil; + try + { + if(v == nil) + { + os_->writeObject(0); + } + else + { + os_->writeObject([self addObject:v]); + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) writeObjectSeq:(NSArray*)arr +{ + if(arr == nil) + { + [self writeSize:0]; + return; + } + + [self writeSize:[arr count]]; + for(id i in arr) + { + [self writeObject:(i == [NSNull null] ? nil : i)]; + } +} + +-(void) writeObjectDict:(NSDictionary*)dictionary helper:(Class)helper +{ + if(dictionary == nil) + { + [self writeSize:0]; + return; + } + + [self writeSize:[dictionary count]]; + NSEnumerator* e = [dictionary keyEnumerator]; + id key; + while((key = [e nextObject])) + { + if(key == [NSNull null]) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"illegal NSNull value"]; + } + [helper write:key stream:self]; + id obj = [dictionary objectForKey:key]; + [self writeObject:(obj == [NSNull null] ? nil : obj)]; + } +} + +-(void) writeException:(ICEUserException*)ex +{ + IceObjC::ExceptionWriter writer(os_->communicator().get(), self, ex); + os_->writeException(writer); +} + +-(void) startObject:(id<ICESlicedData>)slicedData +{ + NSException* nsex = nil; + try + { + if(slicedData != nil) + { + os_->startObject([self writeSlicedData:slicedData]); + } + else + { + os_->startObject(0); + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) endObject +{ + NSException* nsex = nil; + try + { + os_->endObject(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) startException:(id<ICESlicedData>)slicedData +{ + NSException* nsex = nil; + try + { + if(slicedData != nil) + { + os_->startException([self writeSlicedData:slicedData]); + } + else + { + os_->startException(0); + } + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) endException +{ + NSException* nsex = nil; + try + { + os_->endException(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) startSlice:(NSString*)typeId compactId:(ICEInt)compactId lastSlice:(BOOL)lastSlice +{ + NSException* nsex = nil; + try + { + os_->startSlice([typeId UTF8String], compactId, static_cast<bool>(lastSlice)); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) endSlice +{ + NSException* nsex = nil; + try + { + os_->endSlice(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) startEncapsulation +{ + NSException* nsex = nil; + try + { + os_->startEncapsulation(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) startEncapsulation:(ICEEncodingVersion*)encoding format:(ICEFormatType)format +{ + NSException* nsex = nil; + try + { + os_->startEncapsulation([encoding encodingVersion], (Ice::FormatType)format); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(void) endEncapsulation +{ + NSException* nsex = nil; + try + { + os_->endEncapsulation(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(ICEEncodingVersion*) getEncoding +{ + return [ICEEncodingVersion encodingVersionWithEncodingVersion:os_->getEncoding()]; +} + +-(void) writePendingObjects +{ + NSException* nsex = nil; + try + { + os_->writePendingObjects(); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(NSMutableData*) finished +{ + NSException* nsex = nil; + try + { + std::vector<Ice::Byte> buf; + os_->finished(buf); + return [NSMutableData dataWithBytes:&buf[0] length:buf.size()]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(NSData*) finishedNoCopy +{ + NSException* nsex = nil; + try + { + std::pair<const Ice::Byte*, const Ice::Byte*> b = os_->finished(); + return [NSData dataWithBytesNoCopy:const_cast<Ice::Byte*>(b.first) length:(b.second - b.first) freeWhenDone:NO]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; + return nil; // Keep the compiler happy. +} + +-(void) reset:(BOOL)clearBuffer +{ + NSException* nsex = nil; + try + { + os_->reset(clearBuffer); + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + if(nsex != nil) + { + @throw nsex; + } +} + +-(Ice::Object*) addObject:(ICEObject*)object +{ + // + // Ice::ObjectWriter is a subclass of Ice::Object that wraps an Objective-C object for marshaling. + // It is possible that this Objective-C object has already been marshaled, therefore we first must + // check the object map to see if this object is present. If so, we use the existing ObjectWriter, + // otherwise we create a new one. + // + if(!objectWriters_) + { + objectWriters_ = new std::map<ICEObject*, Ice::ObjectPtr>(); + } + std::map<ICEObject*, Ice::ObjectPtr>::const_iterator p = objectWriters_->find(object); + if(p != objectWriters_->end()) + { + return p->second.get(); + } + else + { + Ice::ObjectWriterPtr writer = new IceObjC::ObjectWriter(object, self); + objectWriters_->insert(std::make_pair(object, writer)); + return writer.get(); + } +} + +-(Ice::SlicedData*) writeSlicedData:(id<ICESlicedData>)sd +{ + NSAssert([sd isKindOfClass:[ICESlicedData class]], @"invalid sliced data object"); + Ice::SlicedData* origSlicedData = [((ICESlicedData*)sd) slicedData]; + Ice::SliceInfoSeq slices; + for(Ice::SliceInfoSeq::const_iterator p = origSlicedData->slices.begin(); p != origSlicedData->slices.end(); ++p) + { + Ice::SliceInfoPtr info = new Ice::SliceInfo; + info->typeId = (*p)->typeId; + info->compactId = (*p)->compactId; + info->bytes = (*p)->bytes; + info->hasOptionalMembers = (*p)->hasOptionalMembers; + info->isLastSlice = (*p)->isLastSlice; + + for(std::vector<Ice::ObjectPtr>::const_iterator q = (*p)->objects.begin(); q != (*p)->objects.end(); ++q) + { + if(*q) + { + assert(IceObjC::ObjectReaderPtr::dynamicCast(*q)); + info->objects.push_back([self addObject:IceObjC::ObjectReaderPtr::dynamicCast(*q)->getObject()]); + } + else + { + info->objects.push_back(0); + } + } + slices.push_back(info); + } + return new Ice::SlicedData(slices); +} + +@end + +@implementation ICEStreamHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + NSAssert(NO, @"requires override"); + return nil; +} ++(id) read:(id<ICEInputStream>)stream +{ + return [[self readRetained:stream] autorelease]; + return nil; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + NSAssert(NO, @"requires override"); +} ++(id) readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + NSAssert(NO, @"requires override"); + return nil; +} ++(id) readOpt:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + return [[self readOptRetained:stream tag:tag] autorelease]; + return nil; +} ++(void) writeOpt:(id)obj stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + NSAssert(NO, @"requires override"); +} ++(ICEInt) minWireSize +{ + NSAssert(NO, @"requires override"); + return 0; +} +@end + +@implementation ICEBoolHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [[NSNumber alloc] initWithBool:[stream readBool]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + if(obj == nil) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"illegal NSNull value"]; + } + [stream writeBool:[obj boolValue]]; +} ++(id)readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatF1]) + { + return [[NSNumber alloc] initWithBool:[stream readBool]]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + BOOL value; + if([ICEOptionalGetter getBool:v value:&value] && [stream writeOptional:tag format:ICEOptionalFormatF1]) + { + [stream writeBool:value]; + } +} ++(ICEInt) minWireSize +{ + return 1; +} +@end + +@implementation ICEByteHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [[NSNumber alloc] initWithUnsignedChar:[stream readByte]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + if(obj == nil) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"illegal NSNull value"]; + } + [stream writeByte:[obj unsignedCharValue]]; +} ++(id)readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatF1]) + { + return [[NSNumber alloc] initWithUnsignedChar:[stream readByte]]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + ICEByte value; + if([ICEOptionalGetter getByte:v value:&value] && [stream writeOptional:tag format:ICEOptionalFormatF1]) + { + [stream writeByte:value]; + } +} ++(ICEInt) minWireSize +{ + return 1; +} +@end + +@implementation ICEShortHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [[NSNumber alloc] initWithShort:[stream readShort]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + if(obj == nil) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"illegal NSNull value"]; + } + [stream writeShort:[obj shortValue]]; +} ++(id)readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatF2]) + { + return [[NSNumber alloc] initWithShort:[stream readShort]]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + ICEShort value; + if([ICEOptionalGetter getShort:v value:&value] && [stream writeOptional:tag format:ICEOptionalFormatF2]) + { + [stream writeShort:value]; + } +} ++(ICEInt) minWireSize +{ + return 2; +} +@end + +@implementation ICEIntHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [[NSNumber alloc] initWithInt:[stream readInt]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + if(obj == nil) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"illegal NSNull value"]; + } + [stream writeInt:[obj intValue]]; +} ++(id)readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatF4]) + { + return [[NSNumber alloc] initWithInt:[stream readInt]]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + ICEInt value; + if([ICEOptionalGetter getInt:v value:&value] && [stream writeOptional:tag format:ICEOptionalFormatF4]) + { + [stream writeInt:value]; + } +} ++(ICEInt) minWireSize +{ + return 4; +} +@end + +@implementation ICELongHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [[NSNumber alloc] initWithLong:[stream readLong]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + if(obj == nil) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"illegal NSNull value"]; + } + [stream writeLong:[obj longValue]]; +} ++(id)readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatF8]) + { + return [[NSNumber alloc] initWithLong:[stream readLong]]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + ICELong value; + if([ICEOptionalGetter getLong:v value:&value] && [stream writeOptional:tag format:ICEOptionalFormatF8]) + { + [stream writeLong:value]; + } +} ++(ICEInt) minWireSize +{ + return 8; +} +@end + +@implementation ICEFloatHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [[NSNumber alloc] initWithFloat:[stream readFloat]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + if(obj == nil) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"illegal NSNull value"]; + } + [stream writeFloat:[obj floatValue]]; +} ++(id)readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatF4]) + { + return [[NSNumber alloc] initWithFloat:[stream readFloat]]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + ICEFloat value; + if([ICEOptionalGetter getFloat:v value:&value] && [stream writeOptional:tag format:ICEOptionalFormatF4]) + { + [stream writeFloat:value]; + } +} ++(ICEInt) minWireSize +{ + return 4; +} +@end + +@implementation ICEDoubleHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [[NSNumber alloc] initWithDouble:[stream readDouble]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + if(obj == nil) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"illegal NSNull value"]; + } + [stream writeDouble:[obj doubleValue]]; +} ++(id)readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatF8]) + { + return [[NSNumber alloc] initWithDouble:[stream readDouble]]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + ICEDouble value; + if([ICEOptionalGetter getDouble:v value:&value] && [stream writeOptional:tag format:ICEOptionalFormatF8]) + { + [stream writeDouble:value]; + } +} ++(ICEInt) minWireSize +{ + return 8; +} +@end + +@implementation ICEStringHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newString]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + if(obj == [NSNull null]) + { + obj = nil; + } + [stream writeString:obj]; +} ++(id)readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatVSize]) + { + return [stream newString]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + NSString* value; + if([ICEOptionalGetter get:v value:&value type:[NSString class]] && + [stream writeOptional:tag format:ICEOptionalFormatVSize]) + { + [stream writeString:v]; + } +} ++(ICEInt) minWireSize +{ + return 1; +} +@end + +@implementation ICEEnumHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [[NSNumber alloc] initWithInt:[stream readEnumerator:[self getMinValue] max:[self getMaxValue]]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + if(obj == nil) + { + @throw [ICEMarshalException marshalException:__FILE__ line:__LINE__ reason_:@"illegal NSNull value"]; + } + [stream writeEnumerator:[obj intValue] min:[self getMinValue] max:[self getMaxValue]]; +} ++(id)readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatSize]) + { + return [[NSNumber alloc] initWithInt:[stream readEnumerator:[self getMinValue] max:[self getMaxValue]]]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + ICEInt value; + if([ICEOptionalGetter getInt:v value:&value] && [stream writeOptional:tag format:ICEOptionalFormatSize]) + { + [stream writeEnumerator:value min:[self getMinValue] max:[self getMaxValue]]; + } +} ++(ICEInt) getMinValue +{ + NSAssert(NO, @"ICEEnumHelper getMinValue requires override"); + return 0; +} ++(ICEInt) getMaxValue +{ + NSAssert(NO, @"ICEEnumHelper getMaxValue requires override"); + return 0; +} ++(ICEInt) minWireSize +{ + return 1; +} +@end + +@implementation ICEObjectHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + // + // This will only work with the 1.1 encoding. With the 1.0 encoding + // objects are read when readPendingObjects is called. + // + ICEObject* obj; + [stream newObject:&obj]; + return (id)obj; +} ++(void)readRetained:(ICEObject**)v stream:(id<ICEInputStream>)stream +{ + [stream newObject:v]; +} ++(void)read:(ICEObject**)v stream:(id<ICEInputStream>)stream +{ + [stream readObject:v]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeObject:obj]; +} ++(id)readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatClass]) + { + return [self readRetained:stream]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + ICEObject* value; + if([ICEOptionalGetter get:v value:&value type:[ICEObject class]] && + [stream writeOptional:tag format:ICEOptionalFormatClass]) + { + [self write:value stream:stream]; + } +} ++(void)readOptRetained:(id *)v stream:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatClass]) + { + [self readRetained:(ICEObject**)v stream:stream]; + } + else + { + *v = ICENone; + } +} ++(void)readOpt:(id *)v stream:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatClass]) + { + [self read:(ICEObject**)v stream:stream]; + } + else + { + *v = ICENone; + } +} ++(ICEInt) minWireSize +{ + return 1; +} +@end + +@implementation ICEProxyHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newProxy:[ICEObjectPrx class]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeProxy:obj]; +} ++(id)readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatFSize]) + { + return [ICEVarLengthOptionalHelper readRetained:stream helper:self]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + ICEObjectPrx* value; + if([ICEOptionalGetter get:v value:&value type:[ICEObjectPrx class]] && + [stream writeOptional:tag format:ICEOptionalFormatFSize]) + { + [ICEVarLengthOptionalHelper write:v stream:stream helper:self]; + } +} ++(ICEInt) minWireSize +{ + return 2; +} +@end + +@implementation ICEStructHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + id p = [[self getType] new]; + @try + { + [p read__:stream]; + } + @catch(NSException *ex) + { + [p release]; + @throw ex; + } + return p; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + if(obj == nil) + { + obj = [[self getType] new]; + @try + { + [obj write__:stream]; + } + @finally + { + [obj release]; + } + } + else + { + [obj write__:stream]; + } +} ++(id) readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + Class helper = [self getOptionalHelper]; + if([stream readOptional:tag format:[helper optionalFormat]]) + { + return [helper readRetained:stream helper:self]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)s tag:(ICEInt)tag +{ + Class helper = [self getOptionalHelper]; + NSObject* a; + if([ICEOptionalGetter get:v value:&a type:[self getType]] && [s writeOptional:tag format:[helper optionalFormat]]) + { + [helper write:a stream:s helper:self]; + } +} ++(Class) getType +{ + NSAssert(NO, @"getType requires override"); + return nil; +} ++(Class) getOptionalHelper +{ + NSAssert(NO, @"getOptionalHelper requires override"); + return nil; +} ++(ICEInt) minWireSize +{ + NSAssert(NO, @"minWireSize requires override"); + return 0; +} +@end + +@implementation ICEArraySequenceHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newSequence:[self getElementHelper]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeSequence:obj helper:[self getElementHelper]]; +} ++(id) readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + Class helper = [self getOptionalHelper]; + if([stream readOptional:tag format:[helper optionalFormat]]) + { + return [helper readRetained:stream helper:self]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)s tag:(ICEInt)tag +{ + Class helper = [self getOptionalHelper]; + NSArray* a; + if([ICEOptionalGetter get:v value:&a type:[NSArray class]] && [s writeOptional:tag format:[helper optionalFormat]]) + { + [helper write:a stream:s helper:self]; + } +} ++(Class) getElementHelper +{ + NSAssert(NO, @"getElementHelper requires override"); + return nil; +} ++(Class) getOptionalHelper +{ + NSAssert(NO, @"getOptionalHelper requires override"); + return nil; +} ++(ICEInt) minWireSize +{ + return 1; +} ++(ICEInt) count:(id)obj +{ + return [obj count]; +} +@end + +@implementation ICEDataSequenceHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + NSAssert(NO, @"readRetained requires override"); + return nil; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + NSAssert(NO, @"write requires override"); +} ++(id) readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatVSize]) + { + return [ICEFixedSequenceOptionalHelper readRetained:stream helper:self]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + NSData* a; + if([ICEOptionalGetter get:v value:&a type:[NSData class]] && + [stream writeOptional:tag format:ICEOptionalFormatVSize]) + { + [ICEFixedSequenceOptionalHelper write:a stream:stream helper:self]; + } +} ++(ICEInt) minWireSize +{ + return 1; +} ++(ICEInt) count:(id)obj +{ + return [obj length] / [[self getElementHelper] minWireSize]; +} ++(Class) getElementHelper +{ + return [ICEShortHelper class]; +} +@end + +@implementation ICEBoolSequenceHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newBoolSeq]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeBoolSeq:obj]; +} ++(id) readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatVSize]) + { + return [stream newBoolSeq]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + NSData* a; + if([ICEOptionalGetter get:v value:&a type:[NSData class]] && + [stream writeOptional:tag format:ICEOptionalFormatVSize]) + { + [stream writeBoolSeq:a]; + } +} ++(Class) getElementHelper +{ + return [ICEBoolHelper class]; +} +@end + +@implementation ICEByteSequenceHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newByteSeq]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeByteSeq:obj]; +} ++(id) readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + if([stream readOptional:tag format:ICEOptionalFormatVSize]) + { + return [stream newByteSeq]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)stream tag:(ICEInt)tag +{ + NSData* a; + if([ICEOptionalGetter get:v value:&a type:[NSData class]] && + [stream writeOptional:tag format:ICEOptionalFormatVSize]) + { + [stream writeByteSeq:a]; + } +} ++(Class) getElementHelper +{ + return [ICEIntHelper class]; +} +@end + +@implementation ICEShortSequenceHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newShortSeq]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeShortSeq:obj]; +} ++(Class) getElementHelper +{ + return [ICEShortHelper class]; +} +@end + +@implementation ICEIntSequenceHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newIntSeq]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeIntSeq:obj]; +} ++(Class) getElementHelper +{ + return [ICEIntHelper class]; +} +@end + +@implementation ICELongSequenceHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newLongSeq]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeLongSeq:obj]; +} ++(Class) getElementHelper +{ + return [ICELongHelper class]; +} +@end + +@implementation ICEFloatSequenceHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newFloatSeq]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeFloatSeq:obj]; +} ++(Class) getElementHelper +{ + return [ICEFloatHelper class]; +} +@end + +@implementation ICEDoubleSequenceHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newDoubleSeq]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeDoubleSeq:obj]; +} ++(Class) getElementHelper +{ + return [ICEDoubleHelper class]; +} +@end + +@implementation ICEEnumSequenceHelper ++(ICEInt) count:(id)obj +{ + return [obj length] / ENUM_SIZE; +} ++(Class) getElementHelper +{ + return [ICEEnumHelper class]; +} +@end + +@implementation ICEStringSequenceHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newStringSeq]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeStringSeq:obj]; +} ++(Class) getElementHelper +{ + return [ICEStringHelper class]; +} ++(Class) getOptionalHelper +{ + return [ICEVarLengthOptionalHelper class]; +} +@end + +@implementation ICEObjectSequenceHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newObjectSeq:[ICEObject class]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeObjectSeq:obj]; +} ++(Class) getElementHelper +{ + return [ICEObjectHelper class]; +} ++(Class) getOptionalHelper +{ + return [ICEVarLengthOptionalHelper class]; +} +@end + +@implementation ICEProxySequenceHelper ++(Class) getElementHelper +{ + return [ICEProxyHelper class]; +} ++(Class) getOptionalHelper +{ + return [ICEVarLengthOptionalHelper class]; +} +@end + +@implementation ICEDictionaryHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + return [stream newDictionary:[self getKeyValueHelper]]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + [stream writeDictionary:obj helper:[self getKeyValueHelper]]; +} ++(id) readOptRetained:(id<ICEInputStream>)stream tag:(ICEInt)tag +{ + Class helper = [self getOptionalHelper]; + if([stream readOptional:tag format:[helper optionalFormat]]) + { + return [helper readRetained:stream helper:self]; + } + return ICENone; +} ++(void) writeOpt:(id)v stream:(id<ICEOutputStream>)s tag:(ICEInt)tag +{ + Class helper = [self getOptionalHelper]; + NSDictionary* a; + if([ICEOptionalGetter get:v value:&a type:[NSDictionary class]] && + [s writeOptional:tag format:[helper optionalFormat]]) + { + [helper write:a stream:s helper:self]; + } +} ++(Class) getOptionalHelper +{ + NSAssert(NO, @"getOptionalHelper requires override"); + return nil; +} ++(ICEKeyValueTypeHelper) getKeyValueHelper +{ + NSAssert(NO, @"ICEDictionaryHelper getKeyValueHelper requires override"); + ICEKeyValueTypeHelper dummy; + return dummy; // Keep compiler quiet +} ++(ICEInt) minWireSize +{ + return 1; +} ++(ICEInt) count:(id)obj +{ + return [obj count]; +} +@end + +@implementation ICEObjectDictionaryHelper ++(id) readRetained:(id<ICEInputStream>)stream +{ + NSAssert(NO, @"ICEObjectDictionaryHelper readRetained requires override"); + return nil; +} + ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream +{ + NSAssert(NO, @"ICEObjectDictionaryHelper write requires override"); +} +@end + +@implementation ICEVarLengthOptionalHelper ++(id) readRetained:(id<ICEInputStream>)stream helper:(Class)helper +{ + [stream skip:4]; + return [helper readRetained:stream]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream helper:(Class)helper +{ + Ice::OutputStream* os = [(ICEOutputStream*)stream os]; + os->write(static_cast<Ice::Int>(0)); + Ice::OutputStream::size_type p = os->pos(); + [helper write:obj stream:stream]; + os->rewrite(static_cast<Ice::Int>(os->pos() - p), p - 4); +} ++(ICEOptionalFormat) optionalFormat +{ + return ICEOptionalFormatFSize; +} +@end + +@implementation ICEFixedLengthOptionalHelper ++(id) readRetained:(id<ICEInputStream>)stream helper:(Class)helper +{ + [stream skipSize]; + return [helper readRetained:stream]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream helper:(Class)helper +{ + [stream writeSize:[helper minWireSize]]; + [helper write:obj stream:stream]; +} ++(ICEOptionalFormat) optionalFormat +{ + return ICEOptionalFormatVSize; +} +@end + +@implementation ICEFixedSequenceOptionalHelper ++(id) readRetained:(id<ICEInputStream>)stream helper:(Class)helper +{ + [stream skipSize]; + return [helper readRetained:stream]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream helper:(Class)helper +{ + // + // The container size is the number of elements * the size of + // an element and the size-encoded number of elements (1 or + // 5 depending on the number of elements). + // + ICEInt n = [helper count:obj]; + ICEInt sz = [[helper getElementHelper] minWireSize]; + [stream writeSize:sz * n + (n < 255 ? 1 : 5)]; + [helper write:obj stream:stream]; +} ++(ICEOptionalFormat) optionalFormat +{ + return ICEOptionalFormatVSize; +} +@end + +@implementation ICEFixedSize1SequenceOptionalHelper ++(id) readRetained:(id<ICEInputStream>)stream helper:(Class)helper +{ + return [helper readRetained:stream]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream helper:(Class)helper +{ + [helper write:obj stream:stream]; +} ++(ICEOptionalFormat) optionalFormat +{ + return ICEOptionalFormatVSize; +} +@end + +@implementation ICEFixedDictionaryOptionalHelper ++(id) readRetained:(id<ICEInputStream>)stream helper:(Class)helper +{ + [stream skipSize]; + return [helper readRetained:stream]; +} ++(void) write:(id)obj stream:(id<ICEOutputStream>)stream helper:(Class)helper +{ + // + // The container size is the number of elements * the size of + // an element and the size-encoded number of elements (1 or + // 5 depending on the number of elements). + // + ICEInt n = [helper count:obj]; + ICEKeyValueTypeHelper h = [helper getKeyValueHelper]; + ICEInt sz = [h.key minWireSize] + [h.value minWireSize]; + [stream writeSize:sz * n + (n < 255 ? 1 : 5)]; + [helper write:obj stream:stream]; +} ++(ICEOptionalFormat) optionalFormat +{ + return ICEOptionalFormatVSize; +} +@end + +@implementation ICEOptionalGetter ++(BOOL) get:(id)value type:(Class)cl +{ + if(value == ICENone) + { + return NO; + } + else + { + if(value != nil && ![value isKindOfClass:cl]) + { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"unexpected type" userInfo:cl]; + } + return YES; + } +} ++(BOOL) get:(id)value value:(id*)v type:(Class)cl +{ + if([self get:value type:cl]) + { + *v = value; + return YES; + } + return NO; +} ++(BOOL) getRetained:(id)value value:(id*)v type:(Class)cl +{ + BOOL r = [self get:value value:v type:cl]; + [*v retain]; + return r; +} ++(BOOL) getByte:(id)value value:(ICEByte*)v +{ + if([self get:value type:[NSNumber class]]) + { + *v = [value unsignedCharValue]; + return YES; + } + return NO; +} ++(BOOL) getBool:(id)value value:(BOOL*)v +{ + if([self get:value type:[NSNumber class]]) + { + *v = [value boolValue]; + return YES; + } + return NO; +} ++(BOOL) getShort:(id)value value:(ICEShort*)v +{ + if([self get:value type:[NSNumber class]]) + { + *v = [value shortValue]; + return YES; + } + return NO; +} ++(BOOL) getInt:(id)value value:(ICEInt*)v +{ + if([self get:value type:[NSNumber class]]) + { + *v = [value intValue]; + return YES; + } + return NO; +} ++(BOOL) getLong:(id)value value:(ICELong*)v +{ + if([self get:value type:[NSNumber class]]) + { + *v = [value longValue]; + return YES; + } + return NO; +} ++(BOOL) getFloat:(id)value value:(ICEFloat*)v +{ + if([self get:value type:[NSNumber class]]) + { + *v = [value floatValue]; + return YES; + } + return NO; +} ++(BOOL) getDouble:(id)value value:(ICEDouble*)v +{ + if([self get:value type:[NSNumber class]]) + { + *v = [value doubleValue]; + return YES; + } + return NO; +} +@end diff --git a/objc/src/Ice/StreamI.h b/objc/src/Ice/StreamI.h new file mode 100644 index 00000000000..b0263dc62f3 --- /dev/null +++ b/objc/src/Ice/StreamI.h @@ -0,0 +1,29 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Stream.h> +#import <Wrapper.h> + +#include <IceCpp/Stream.h> + +@interface ICEInputStream : ICEInternalWrapper<ICEInputStream> +{ + Ice::InputStream* is_; +} ++(Ice::Object*)createObjectReader:(ICEObject*)obj; +-(Ice::InputStream*) is; +@end + +@interface ICEOutputStream : ICEInternalWrapper<ICEOutputStream> +{ + Ice::OutputStream* os_; + std::map<ICEObject*, Ice::ObjectPtr>* objectWriters_; +} +-(Ice::OutputStream*) os; +@end diff --git a/objc/src/Ice/Util.h b/objc/src/Ice/Util.h new file mode 100644 index 00000000000..ab7f0834a99 --- /dev/null +++ b/objc/src/Ice/Util.h @@ -0,0 +1,242 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <Foundation/NSException.h> + +#import <objc/Ice/Config.h> +#import <objc/Ice/Current.h> + +#include <IceCpp/Proxy.h> +#include <IceCpp/Endpoint.h> + +#import <EndpointI.h> + +#include <exception> +#include <vector> +#include <map> +#include <string> + +@class ICEAsyncResult; +@class ICEObjectPrx; +@class ICEException; +@class ICEEndpoint; + +void cppCall(void (^fn)()); +void cppCall(void (^fn)(const Ice::Context&), ICEContext*); +ICEAsyncResult* beginCppCall(void (^fn)(Ice::AsyncResultPtr&), ICEObjectPrx* = nil); +ICEAsyncResult* beginCppCall(void (^fn)(Ice::AsyncResultPtr&, const Ice::CallbackPtr&), + void (^completed)(const Ice::AsyncResultPtr&), + void (^exception)(ICEException*), + void (^sent)(BOOL), + ICEObjectPrx* = nil); +ICEAsyncResult* beginCppCall(void (^fn)(Ice::AsyncResultPtr&, const Ice::Context&), ICEContext*, ICEObjectPrx* = nil); +ICEAsyncResult* beginCppCall(void (^fn)(Ice::AsyncResultPtr&, const Ice::Context&, const Ice::CallbackPtr&), + ICEContext*, + void (^completed)(const Ice::AsyncResultPtr&), + void (^exception)(ICEException*), + void (^sent)(BOOL), + ICEObjectPrx* = nil); +void endCppCall(void (^fn)(const Ice::AsyncResultPtr&), ICEAsyncResult*); + + +NSException* toObjCException(const std::exception&); +void rethrowCxxException(id, bool = false); + +// +// The toXXX methods don't auto release the returned object: the caller +// must assume ownership of the returned object. +// + +inline NSObject<NSCopying>* toObjC(bool v) { return [[NSNumber alloc] initWithBool:v]; } +inline NSObject<NSCopying>* toObjC(ICEByte v) { return [[NSNumber alloc] initWithUnsignedChar:v]; } +inline NSObject<NSCopying>* toObjC(ICEShort v) { return [[NSNumber alloc] initWithShort:v]; } +inline NSObject<NSCopying>* toObjC(ICEInt v) { return [[NSNumber alloc] initWithInt:v]; } +inline NSObject<NSCopying>* toObjC(ICELong v) { return [[NSNumber alloc] initWithLongLong:v]; } +inline NSObject<NSCopying>* toObjC(ICEFloat v) { return [[NSNumber alloc] initWithFloat:v]; } +inline NSObject<NSCopying>* toObjC(ICEDouble v) { return [[NSNumber alloc] initWithDouble:v]; } + +inline void fromObjC(id object, bool& v) { v = [object boolValue]; } +inline void fromObjC(id object, ICEByte& v) { v = [object unsignedCharValue]; } +inline void fromObjC(id object, ICEShort& v) { v = [object shortValue]; } +inline void fromObjC(id object, ICEInt& v) { v = [object intValue];} +inline void fromObjC(id object, ICELong& v) { v = [object longLongValue]; } +inline void fromObjC(id object, ICEFloat& v) { v = [object floatValue]; } +inline void fromObjC(id object, ICEDouble& v) { v = [object doubleValue]; } + +inline NSObject<NSCopying>* +toObjC(const std::string& s) +{ + return [[NSString alloc] initWithUTF8String:s.c_str()]; +} + +inline void +fromObjC(id object, std::string& s) +{ + s = object == [NSNull null] ? ::std::string() : [object UTF8String]; +} + +NSObject<NSCopying>* toObjC(const Ice::EndpointPtr& endpoint); +void fromObjC(id object, Ice::EndpointPtr& endpoint); + +inline NSMutableArray* +toNSArray(const char* arr[], size_t size) +{ + NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity:size]; + for(size_t i = 0; i < size; ++i) + { + NSObject* obj = [[NSString alloc] initWithUTF8String:arr[i]]; + [array addObject:obj]; + [obj release]; + } + return array; +} + +template<typename T> NSMutableArray* +toNSArray(const std::vector<T>& seq) +{ + NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity:seq.size()]; + for(typename std::vector<T>::const_iterator p = seq.begin(); p != seq.end(); ++p) + { + NSObject* obj = toObjC(*p); + [array addObject:obj]; + [obj release]; + } + return array; +} + +template<typename T> NSMutableData* +toNSData(const std::vector<T>& seq) +{ + NSMutableData* array = [[NSMutableData alloc] initWithLength:seq.size() * sizeof(T)]; + T* target = (T*)[array bytes]; + for(typename std::vector<T>::const_iterator p = seq.begin(); p != seq.end(); ++p) + { + *target++ = *p; + } + return array; +} + +template<typename T> std::vector<T>& +fromNSArray(NSArray* array, std::vector<T>& seq) +{ + if(array != nil) + { + seq.reserve([array count]); + NSEnumerator* enumerator = [array objectEnumerator]; + id obj = nil; + while((obj = [enumerator nextObject])) + { + T v; + fromObjC(obj, v); + seq.push_back(v); + } + } + return seq; +} + +template<typename T> std::vector<T>& +fromNSData(NSData* array, std::vector<T>& seq) +{ + if(array != nil) + { + int len = [array length] / sizeof(T); + seq.reserve(len); + T* src = (T*)[array bytes]; + while(len-- > 0) + { + seq.push_back(*src++); + } + } + return seq; +} + +template<typename K, typename V> NSMutableDictionary* +toNSDictionary(const std::map<K, V>& dict) +{ + NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] initWithCapacity:dict.size()]; + for(typename std::map<K, V>::const_iterator p = dict.begin(); p != dict.end(); ++p) + { + NSObject<NSCopying>* key = toObjC(p->first); + NSObject* value = toObjC(p->second); + [dictionary setObject:value forKey:key]; + [key release]; + [value release]; + } + return dictionary; +} + +template<typename K, typename V> std::map<K, V>& +fromNSDictionary(NSDictionary* dictionary, std::map<K, V>& dict) +{ + if(dictionary != nil) + { + NSEnumerator* enumerator = [dictionary keyEnumerator]; + id obj = nil; + while((obj = [enumerator nextObject])) + { + K k; + fromObjC(obj, k); + V v; + fromObjC([dictionary objectForKey:obj], v); + dict.insert(std::pair<K, V>(k, v)); + } + } + return dict; +} + +inline NSString* +toNSString(const char* s) +{ + return [[NSString alloc] initWithCString:s encoding:[NSString defaultCStringEncoding]]; +} + +inline NSString* +toNSString(const std::string& s) +{ + return [[NSString alloc] initWithUTF8String:s.c_str()]; +} + +inline NSMutableString* +toNSMutableString(const std::string& s) +{ + return [[NSMutableString alloc] initWithUTF8String:s.c_str()]; +} + +inline std::string +fromNSString(NSString* s) +{ + return s == nil ? std::string() : [s UTF8String]; +} + +std::string toObjCSliceId(const std::string&, NSDictionary*); + +namespace IceObjC +{ + +class Exception : public IceUtil::Exception +{ +public: + + Exception(id<NSObject>); + Exception(const Exception&); + virtual ~Exception() throw(); + + virtual std::string ice_name() const; + virtual void ice_print(std::ostream& os) const; + virtual Exception* ice_clone() const; + virtual void ice_throw() const; + + id<NSObject> exception() const { return _ex; } + +private: + + id<NSObject> _ex; +}; + +} diff --git a/objc/src/Ice/Util.mm b/objc/src/Ice/Util.mm new file mode 100644 index 00000000000..99bd95358ac --- /dev/null +++ b/objc/src/Ice/Util.mm @@ -0,0 +1,477 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <Util.h> +#import <ExceptionI.h> +#import <StreamI.h> +#import <ProxyI.h> + +#import <objc/Ice/LocalException.h> + +#include <IceCpp/LocalException.h> +#include <IceCpp/Initialize.h> + +#include <Block.h> + +#import <objc/runtime.h> +#import <Foundation/NSAutoreleasePool.h> + +namespace +{ + +class AsyncCallback : public IceUtil::Shared +{ +public: + +AsyncCallback(void (^completed)(const Ice::AsyncResultPtr&), void (^exception)(ICEException*), void (^sent)(BOOL)) : + _completed(Block_copy(completed)), _exception(Block_copy(exception)), _sent(Block_copy(sent)) +{ +} + +virtual ~AsyncCallback() +{ + Block_release(_completed); + Block_release(_exception); + Block_release(_sent); +} + +void completed(const Ice::AsyncResultPtr& result) +{ + NSException* exception = nil; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + @try + { + try + { + _completed(result); + } + catch(const Ice::Exception& ex) + { + @try + { + NSException* nsex = toObjCException(ex); + @throw nsex; + } + @catch(ICEException* e) + { + if(_exception) + { + _exception(e); + } + } + } + } + @catch(NSException* e) + { + exception = [e retain]; + } + @finally + { + [pool drain]; + } + + if(exception != nil) + { + rethrowCxxException(exception, true); // True = release the exception. + } +} + +void sent(const Ice::AsyncResultPtr& result) +{ + if(!_sent) + { + return; + } + + NSException* exception = nil; + @autoreleasepool + { + @try + { + _sent(result->sentSynchronously()); + } + @catch(NSException* e) + { + exception = [e retain]; + } + } + + if(exception != nil) + { + rethrowCxxException(exception, true); // True = release the exception. + } +} + +private: + +void (^_completed)(const Ice::AsyncResultPtr&); +void (^_exception)(ICEException*); +void (^_sent)(BOOL); + +}; + +}; + +void cppCall(void (^fn)()) +{ + NSException* nsex = nil; + try + { + fn(); + return; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; +} + +void cppCall(void (^fn)(const Ice::Context&), ICEContext* context) +{ + NSException* nsex = nil; + try + { + Ice::Context ctx; + fromNSDictionary(context, ctx); + fn(ctx); + return; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; +} + +ICEAsyncResult* beginCppCall(void (^fn)(Ice::AsyncResultPtr&), ICEObjectPrx* prx) +{ + NSException* nsex = nil; + try + { + Ice::AsyncResultPtr r; + fn(r); + return [ICEAsyncResult asyncResultWithAsyncResult__:r operation:nil proxy:prx]; + } + catch(const IceUtil::IllegalArgumentException& ex) + { + nsex = [NSException exceptionWithName:NSInvalidArgumentException reason:[toNSString(ex.reason()) autorelease] + userInfo:nil]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; +} + +ICEAsyncResult* beginCppCall(void (^fn)(Ice::AsyncResultPtr&, const Ice::CallbackPtr&), + void (^completed)(const Ice::AsyncResultPtr&), + void (^exception)(ICEException*), + void (^sent)(BOOL), + ICEObjectPrx* prx) +{ + NSException* nsex = nil; + try + { + AsyncCallback* cb = new AsyncCallback(completed, exception, sent); + Ice::AsyncResultPtr r; + Ice::CallbackPtr callback = Ice::newCallback(cb, &AsyncCallback::completed, &AsyncCallback::sent); + fn(r, callback); + return [ICEAsyncResult asyncResultWithAsyncResult__:r operation:nil proxy:prx]; + } + catch(const IceUtil::IllegalArgumentException& ex) + { + nsex = [NSException exceptionWithName:NSInvalidArgumentException reason:[toNSString(ex.reason()) autorelease] + userInfo:nil]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; +} + +ICEAsyncResult* beginCppCall(void (^fn)(Ice::AsyncResultPtr&, const Ice::Context&), + ICEContext* context, + ICEObjectPrx* prx) +{ + NSException* nsex = nil; + try + { + Ice::Context ctx; + fromNSDictionary(context, ctx); + Ice::AsyncResultPtr r; + fn(r, ctx); + return [ICEAsyncResult asyncResultWithAsyncResult__:r operation:nil proxy:prx]; + } + catch(const IceUtil::IllegalArgumentException& ex) + { + nsex = [NSException exceptionWithName:NSInvalidArgumentException reason:[toNSString(ex.reason()) autorelease] + userInfo:nil]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; +} + +ICEAsyncResult* beginCppCall(void (^fn)(Ice::AsyncResultPtr&, const Ice::Context&, const Ice::CallbackPtr&), + ICEContext* context, + void (^completed)(const Ice::AsyncResultPtr&), + void (^exception)(ICEException*), + void (^sent)(BOOL), + ICEObjectPrx* prx) +{ + NSException* nsex = nil; + try + { + Ice::Context ctx; + fromNSDictionary(context, ctx); + AsyncCallback* cb = new AsyncCallback(completed, exception, sent); + Ice::AsyncResultPtr r; + Ice::CallbackPtr callback = Ice::newCallback(cb, &AsyncCallback::completed, &AsyncCallback::sent); + fn(r, ctx, callback); + return [ICEAsyncResult asyncResultWithAsyncResult__:r operation:nil proxy:prx]; + } + catch(const IceUtil::IllegalArgumentException& ex) + { + nsex = [NSException exceptionWithName:NSInvalidArgumentException reason:[toNSString(ex.reason()) autorelease] + userInfo:nil]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; +} + +void endCppCall(void (^fn)(const Ice::AsyncResultPtr&), ICEAsyncResult* r) +{ + NSException* nsex = nil; + try + { + fn([r asyncResult__]); + return; + } + catch(const IceUtil::IllegalArgumentException& ex) + { + nsex = [NSException exceptionWithName:NSInvalidArgumentException reason:[toNSString(ex.reason()) autorelease] + userInfo:nil]; + } + catch(const std::exception& ex) + { + nsex = toObjCException(ex); + } + @throw nsex; +} + +NSException* +toObjCException(const std::exception& ex) +{ + NSException* nsex; + { + const Ice::LocalException* lex = dynamic_cast<const Ice::LocalException*>(&ex); + if(lex) + { + std::string typeId = std::string("ICE") + lex->ice_name().substr(5); + Class c = objc_getClass(typeId.c_str()); + if(c != nil) + { + nsex = [c localExceptionWithLocalException:*lex]; + } + else + { + Ice::UnknownLocalException ulex(__FILE__, __LINE__, ex.what()); + nsex = [ICEUnknownLocalException localExceptionWithLocalException:ulex]; + } + } + else + { + const Ice::UserException* uex = dynamic_cast<const Ice::UserException*>(&ex); + if(uex) + { + Ice::UnknownUserException uuex(__FILE__, __LINE__, ex.what()); + nsex = [ICEUnknownUserException localExceptionWithLocalException:uuex]; + } + else + { + const IceObjC::Exception* objCEx = dynamic_cast<const IceObjC::Exception*>(&ex); + if(objCEx) + { + id<NSObject> oex = objCEx->exception(); + if(oex == nil) + { + nsex = [NSException exceptionWithName:@"unknown Objective-C exception" + reason:[NSString stringWithUTF8String:ex.what()] + userInfo:nil]; + } + else if([oex isKindOfClass:[NSException class]]) + { + nsex = [[(NSException*)oex retain] autorelease]; + } + else + { + nsex = [NSException exceptionWithName:@"unknown Objective-C exception" + reason:[oex description] + userInfo:nil]; + } + } + else + { + // + // std::exception from the Ice runtime are translated to NSException. + // + //Ice::UnknownException e(__FILE__, __LINE__, ex.what()); + //nsex = [ICEUnknownException localExceptionWithLocalException:e]; + nsex = [NSException exceptionWithName:@"std::exception" + reason:[NSString stringWithUTF8String:ex.what()] + userInfo:nil]; + } + } + } + } + return nsex; +} + +void +rethrowCxxException(id e, bool release) +{ + @try + { + @throw e; + } + @catch(ICEUserException* ex) + { + Ice::UnknownUserException uuex(__FILE__, __LINE__, fromNSString([ex description])); + if(release) + { + [ex release]; + } + throw uuex; + } + @catch(ICELocalException* ex) + { + if(release) + { + try + { + [ex rethrowCxx]; + } + catch(const std::exception&) + { + [ex release]; + throw; + } + } + else + { + [ex rethrowCxx]; + } + } + @catch(id ex) + { + if([ex conformsToProtocol:@protocol(NSObject)]) + { + IceObjC::Exception exo(ex); + if(release) + { + [ex release]; + } + throw exo; + } + else + { + throw IceObjC::Exception(nil); + } + } +} + +std::string +toObjCSliceId(const std::string& sliceId, NSDictionary* prefixTable) +{ + std::string objcType = sliceId; + + if(objcType.find("::Ice::") == 0) + { + return objcType.replace(0, 7, "ICE"); + } + + std::string::size_type pos = objcType.rfind("::"); + if(pos != std::string::npos) + { + NSString* moduleName = toNSString(objcType.substr(0, pos)); + NSString* prefix = [prefixTable objectForKey:moduleName]; + [moduleName release]; + if(prefix) + { + return objcType.replace(0, pos + 2, fromNSString(prefix)); + } + } + + while((pos = objcType.find("::")) != std::string::npos) + { + objcType = objcType.replace(pos, 2, ""); + } + return objcType; +} + +IceObjC::Exception::Exception(id<NSObject> ex) : _ex([ex retain]) +{ +} + +IceObjC::Exception::Exception(const IceObjC::Exception& ex) : _ex([ex._ex retain]) +{ +} + +IceObjC::Exception::~Exception() throw() +{ + [_ex release]; +} + +std::string +IceObjC::Exception::ice_name() const +{ + return "IceObjC::Exception"; +} + +void +IceObjC::Exception::ice_print(std::ostream& os) const +{ + IceUtil::Exception::ice_print(os); + if(_ex != nil) + { + os << ":\n" << fromNSString([_ex description]); + } +} + +IceObjC::Exception* +IceObjC::Exception::ice_clone() const +{ + return new Exception(*this); +} + +void +IceObjC::Exception::ice_throw() const +{ + throw *this; +} + +NSObject<NSCopying>* +toObjC(const Ice::EndpointPtr& endpoint) +{ + return [ICEEndpoint wrapperWithCxxObjectNoAutoRelease:endpoint.get()]; +} + +void +fromObjC(id object, Ice::EndpointPtr& endpoint) +{ + endpoint = object == [NSNull null] ? 0 : [object endpoint]; +} diff --git a/objc/src/Ice/VersionI.h b/objc/src/Ice/VersionI.h new file mode 100644 index 00000000000..01b13e416dc --- /dev/null +++ b/objc/src/Ice/VersionI.h @@ -0,0 +1,27 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Version.h> + +#include <IceCpp/Version.h> + +@interface ICEProtocolVersion (ICEInternal) ++(void) load; +-(ICEProtocolVersion*)initWithProtocolVersion:(const Ice::ProtocolVersion&)arg; +-(Ice::ProtocolVersion)protocolVersion; ++(ICEProtocolVersion*)protocolVersionWithProtocolVersion:(const Ice::ProtocolVersion&)arg; +@end + +@interface ICEEncodingVersion (ICEInternal) ++(void) load; +-(ICEEncodingVersion*)initWithEncodingVersion:(const Ice::EncodingVersion&)arg; +-(Ice::EncodingVersion)encodingVersion; ++(ICEEncodingVersion*)encodingVersionWithEncodingVersion:(const Ice::EncodingVersion&)arg; +@end + diff --git a/objc/src/Ice/VersionI.mm b/objc/src/Ice/VersionI.mm new file mode 100644 index 00000000000..762e82fb699 --- /dev/null +++ b/objc/src/Ice/VersionI.mm @@ -0,0 +1,127 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <VersionI.h> +#import <Util.h> + +ICEEncodingVersion* ICEEncoding_1_0; +ICEEncodingVersion* ICEEncoding_1_1; +ICEEncodingVersion* ICECurrentEncoding; + +@implementation ICEEncodingVersion (ICEInternal) + ++(void) load +{ + ICEEncoding_1_0 = [[ICEEncodingVersion alloc] init:1 minor:0]; + ICEEncoding_1_1 = [[ICEEncodingVersion alloc] init:1 minor:1]; + ICECurrentEncoding = [[ICEEncodingVersion alloc] init:IceInternal::encodingMajor minor:IceInternal::encodingMinor]; +} + +-(ICEEncodingVersion*) initWithEncodingVersion:(const Ice::EncodingVersion&)arg +{ + self = [super init]; + if(!self) + { + return nil; + } + major = arg.major; + minor = arg.minor; + return self; +} + +-(Ice::EncodingVersion) encodingVersion +{ + Ice::EncodingVersion v; + v.major = major; + v.minor = minor; + return v; +} + ++(ICEEncodingVersion*) encodingVersionWithEncodingVersion:(const Ice::EncodingVersion&)arg +{ + if(arg == Ice::Encoding_1_0) + { + return ICEEncoding_1_0; + } + else if(arg == Ice::Encoding_1_1) + { + return ICEEncoding_1_1; + } + else if(arg == Ice::currentEncoding) + { + return ICECurrentEncoding; + } + else + { + return [[[ICEEncodingVersion alloc] initWithEncodingVersion:arg] autorelease]; + } +} + +-(NSString*) description +{ + return [toNSString(Ice::encodingVersionToString([self encodingVersion])) autorelease]; +} +@end + + +ICEProtocolVersion* ICEProtocol_1_0; +ICEProtocolVersion* ICECurrentProtocol; +ICEEncodingVersion* ICECurrentProtocolEncoding; + +@implementation ICEProtocolVersion (ICEInternal) + ++(void) load +{ + ICEProtocol_1_0 = [[ICEProtocolVersion alloc] init:1 minor:0]; + ICECurrentProtocol = [[ICEProtocolVersion alloc] init:IceInternal::protocolMajor minor:IceInternal::protocolMinor]; + ICECurrentProtocolEncoding = [[ICEEncodingVersion alloc] init:IceInternal::protocolEncodingMajor + minor:IceInternal::protocolEncodingMinor]; +} + +-(ICEProtocolVersion*) initWithProtocolVersion:(const Ice::ProtocolVersion&)arg +{ + self = [super init]; + if(!self) + { + return nil; + } + major = arg.major; + minor = arg.minor; + return self; +} + +-(Ice::ProtocolVersion) protocolVersion +{ + Ice::ProtocolVersion v; + v.major = major; + v.minor = minor; + return v; +} + ++(ICEProtocolVersion*) protocolVersionWithProtocolVersion:(const Ice::ProtocolVersion&)arg +{ + if(arg == Ice::Protocol_1_0) + { + return ICEProtocol_1_0; + } + else if(arg == Ice::currentProtocol) + { + return ICECurrentProtocol; + } + else + { + return [[[ICEProtocolVersion alloc] initWithProtocolVersion:arg] autorelease]; + } +} + +-(NSString*) description +{ + return [toNSString(Ice::protocolVersionToString([self protocolVersion])) autorelease]; +} +@end diff --git a/objc/src/Ice/Wrapper.h b/objc/src/Ice/Wrapper.h new file mode 100644 index 00000000000..53d4d2b512c --- /dev/null +++ b/objc/src/Ice/Wrapper.h @@ -0,0 +1,32 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice/Config.h> + +namespace IceUtil +{ +class Shared; +} + +@interface ICEInternalWrapper : NSObject +{ + void* cxxObject_; +} +-(id) initWithCxxObject:(IceUtil::Shared*)arg; + +// +// Note: the returned object is NOT retained. It must be held +// some other way by the calling thread. +// ++(id) getWrapperWithCxxObjectNoAutoRelease:(IceUtil::Shared*)arg; + ++(id) wrapperWithCxxObjectNoAutoRelease:(IceUtil::Shared*)arg; ++(id) wrapperWithCxxObject:(IceUtil::Shared*)arg; +-(IceUtil::Shared*) cxxObject; +@end diff --git a/objc/src/Ice/Wrapper.mm b/objc/src/Ice/Wrapper.mm new file mode 100644 index 00000000000..7bdb91670d8 --- /dev/null +++ b/objc/src/Ice/Wrapper.mm @@ -0,0 +1,258 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <Wrapper.h> + +// +// Using NSMapTable is necessary for this code to work properly with GC. +// We could also use NSMapTable on MacOS without GC, however, +// it's preferable to use the same code for non-GC on MacOS and other platforms +// +// #if defined(ICE_OBJC_GC) || !TARGET_OS_IPHONE +// +#ifdef ICE_OBJC_GC + #define ICE_USE_MAP_TABLE 1 +#endif + +#ifdef ICE_USE_MAP_TABLE + #import <Foundation/NSMapTable.h> +#else + #include <map> +#endif + +#include <IceUtilCpp/Shared.h> +#include <Foundation/Foundation.h> + +#define CXXOBJECT ((IceUtil::Shared*)cxxObject_) + +#ifndef ICE_USE_MAP_TABLE +namespace +{ + +std::map<IceUtil::Shared*, ICEInternalWrapper*>* cachedObjects = 0; + +class Init +{ +public: + + Init() + { + cachedObjects = new std::map<IceUtil::Shared*, ICEInternalWrapper*>; + } + + ~Init() + { + delete cachedObjects; + } +}; + +Init init; +} +#endif + + +@implementation ICEInternalWrapper + +#ifdef ICE_USE_MAP_TABLE +// +// mapTable singleton +// ++(NSMapTable*) mapTable +{ + static NSMapTable* instance; + @synchronized(self) + { + if(instance == 0) + { + // + // Unfortunately the values we use are not very well documented, and small variations + // (like using the opaque pointer memory personality for keys) introduces strange bugs + // + instance = [NSMapTable + mapTableWithKeyOptions:NSPointerFunctionsOpaquePersonality + valueOptions:NSMapTableZeroingWeakMemory]; + + CFRetain(instance); // leak it! + } + } + return instance; +} +#endif + +-(id) initWithCxxObject:(IceUtil::Shared*)arg +{ + self = [super init]; + if(!self) + { + return nil; + } + cxxObject_ = arg; + CXXOBJECT->__incRef(); + +#ifdef ICE_USE_MAP_TABLE + // + // No synchronization because initWithCxxObject is always called with mapTable locked, see below + // + NSMapTable* mapTable = [ICEInternalWrapper mapTable]; + void* result = NSMapInsertIfAbsent(mapTable, arg, self); + // COMPILERFIX: NSMapTable bug where the entry sometime doesn't get properly + // added. Adding it a second time works. + if(NSMapGet(mapTable, arg) == 0) + { + result = NSMapInsertIfAbsent([ICEInternalWrapper mapTable], arg, self); + } + assert(result == 0); +#else + // + // No synchronization because initWithCxxObject is always called with the wrapper class object locked + // + assert(cachedObjects->find(CXXOBJECT) == cachedObjects->end()); + cachedObjects->insert(std::make_pair(CXXOBJECT, self)); +#endif + + return self; +} + +-(IceUtil::Shared*) cxxObject +{ + return CXXOBJECT; +} + +-(void) dealloc +{ + +#ifdef ICE_USE_MAP_TABLE + // + // No synchronization because dealloc is always called with + // mapTable locked, see below + // + NSMapRemove([ICEInternalWrapper mapTable], cxxObject_); +#else + // + // No synchronization because dealloc is always called with the wrapper class object locked + // + cachedObjects->erase(CXXOBJECT); +#endif + + CXXOBJECT->__decRef(); + cxxObject_ = 0; + [super dealloc]; +} + +#ifdef ICE_USE_MAP_TABLE +// +// No GC and therefore finalize without the MapTable! +// +-(void) finalize +{ + assert(cxxObject_ != 0); + CXXOBJECT->__decRef(); + cxxObject_ = 0; + [super finalize]; +} +#endif + ++(id) getWrapperWithCxxObjectNoAutoRelease:(IceUtil::Shared*)arg +{ + // + // Note: the returned object is NOT retained. It must be held + // some other way by the calling thread. + // + + if(arg == 0) + { + return nil; + } + +#ifdef ICE_USE_MAP_TABLE + NSMapTable* mapTable = [ICEInternalWrapper mapTable]; + @synchronized(mapTable) + { + id val = (id)NSMapGet(mapTable, arg); + return val; + } +#else + @synchronized([ICEInternalWrapper class]) + { + std::map<IceUtil::Shared*, ICEInternalWrapper*>::const_iterator p = cachedObjects->find(arg); + if(p != cachedObjects->end()) + { + return p->second; + } + } +#endif + return nil; +} + ++(id) wrapperWithCxxObjectNoAutoRelease:(IceUtil::Shared*)arg +{ + if(arg == 0) + { + return nil; + } + +#ifdef ICE_USE_MAP_TABLE + NSMapTable* mapTable = [ICEInternalWrapper mapTable]; + @synchronized(mapTable) + { + id val = (id)NSMapGet(mapTable, arg); + + if(val == nil) + { + return [[self alloc] initWithCxxObject:arg]; + } + else + { + return [val retain]; + } + } +#else + @synchronized([ICEInternalWrapper class]) + { + std::map<IceUtil::Shared*, ICEInternalWrapper*>::const_iterator p = cachedObjects->find(arg); + if(p != cachedObjects->end()) + { + return [p->second retain]; + } + else + { + return [[self alloc] initWithCxxObject:arg]; + } + } +#endif + return nil; // Keep the compiler happy. +} + ++(id) wrapperWithCxxObject:(IceUtil::Shared*)arg +{ + return [[self wrapperWithCxxObjectNoAutoRelease:arg] autorelease]; +} + + +-(id) retain +{ + NSIncrementExtraRefCount(self); + return self; +} + +-(oneway void) release +{ +#ifdef ICE_USE_MAP_TABLE + @synchronized([ICEInternalWrapper mapTable]) +#else + @synchronized([ICEInternalWrapper class]) +#endif + { + if(NSDecrementExtraRefCountWasZero(self)) + { + [self dealloc]; + } + } +} +@end diff --git a/objc/src/IceGrid/.gitignore b/objc/src/IceGrid/.gitignore new file mode 100644 index 00000000000..1d8a22c0997 --- /dev/null +++ b/objc/src/IceGrid/.gitignore @@ -0,0 +1,28 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +.depend +Admin.m +Descriptor.m +Discovery.m +Exception.m +FileParser.m +Locator.m +Observer.m +PluginFacade.m +Query.m +Registry.m +Session.m +UserAccountMapper.m +Admin.h +Descriptor.h +Discovery.h +Exception.h +FileParser.h +Locator.h +Observer.h +PluginFacade.h +Query.h +Registry.h +Session.h +UserAccountMapper.h diff --git a/objc/src/IceGrid/Makefile b/objc/src/IceGrid/Makefile new file mode 100644 index 00000000000..a314c048157 --- /dev/null +++ b/objc/src/IceGrid/Makefile @@ -0,0 +1,56 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = ../.. + +LIBFILENAME = $(call mklibfilename,IceGridObjC,$(VERSION)) +SONAME = $(call mksoname,IceGridObjC,$(SOVERSION)) +LIBNAME = $(call mklibname,IceGridObjC) + +TARGETS = $(call mklibtargets,$(libdir)/$(LIBFILENAME),$(libdir)/$(SONAME),$(libdir)/$(LIBNAME)) + +SLICE_OBJS = Admin.o \ + Descriptor.o \ + Discovery.o \ + Exception.o \ + FileParser.o \ + Locator.o \ + Observer.o \ + PluginFacade.o \ + Query.o \ + Registry.o \ + Session.o \ + UserAccountMapper.o + +OBJS = $(SLICE_OBJS) + +HDIR = $(headerdir)/objc/IceGrid +SDIR = $(slicedir)/IceGrid + +include $(top_srcdir)/config/Make.rules + +SLICE2OBJCFLAGS := --ice --include-dir objc/IceGrid $(SLICE2OBJCFLAGS) +LINKWITH := -lGlacier2ObjC $(LIBS) + +$(libdir)/$(LIBFILENAME): $(OBJS) + @mkdir -p $(dir $@) + rm -f $@ + $(call mkshlib,$@,$(SONAME),$(OBJS),$(LINKWITH)) + +$(libdir)/$(SONAME): $(libdir)/$(LIBFILENAME) + rm -f $@ + ln -s $(LIBFILENAME) $@ + +$(libdir)/$(LIBNAME): $(libdir)/$(SONAME) + @mkdir -p $(libdir) + rm -f $@ + ln -s $(SONAME) $@ + +install:: all + $(call installlib,$(DESTDIR)$(install_libdir),$(libdir),$(LIBFILENAME),$(SONAME),$(LIBNAME)) diff --git a/objc/src/IceStorm/.gitignore b/objc/src/IceStorm/.gitignore new file mode 100644 index 00000000000..166500719d4 --- /dev/null +++ b/objc/src/IceStorm/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +.depend +Metrics.m +IceStorm.m +Metrics.h +IceStorm.h diff --git a/objc/src/IceStorm/Makefile b/objc/src/IceStorm/Makefile new file mode 100644 index 00000000000..2e4d1abefb6 --- /dev/null +++ b/objc/src/IceStorm/Makefile @@ -0,0 +1,45 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = ../.. + +LIBFILENAME = $(call mklibfilename,IceStormObjC,$(VERSION)) +SONAME = $(call mksoname,IceStormObjC,$(SOVERSION)) +LIBNAME = $(call mklibname,IceStormObjC) + +TARGETS = $(call mklibtargets,$(libdir)/$(LIBFILENAME),$(libdir)/$(SONAME),$(libdir)/$(LIBNAME)) + +SLICE_OBJS = Metrics.o \ + IceStorm.o + +OBJS = $(SLICE_OBJS) + +HDIR = $(headerdir)/objc/IceStorm +SDIR = $(slicedir)/IceStorm + +include $(top_srcdir)/config/Make.rules + +SLICE2OBJCFLAGS := --ice --include-dir objc/IceStorm $(SLICE2OBJCFLAGS) + +$(libdir)/$(LIBFILENAME): $(OBJS) + @mkdir -p $(dir $@) + rm -f $@ + $(call mkshlib,$@,$(SONAME),$(OBJS),$(LIBS)) + +$(libdir)/$(SONAME): $(libdir)/$(LIBFILENAME) + rm -f $@ + ln -s $(LIBFILENAME) $@ + +$(libdir)/$(LIBNAME): $(libdir)/$(SONAME) + @mkdir -p $(libdir) + rm -f $@ + ln -s $(SONAME) $@ + +install:: all + $(call installlib,$(DESTDIR)$(install_libdir),$(libdir),$(LIBFILENAME),$(SONAME),$(LIBNAME)) diff --git a/objc/src/Makefile b/objc/src/Makefile new file mode 100644 index 00000000000..b0bc669c5af --- /dev/null +++ b/objc/src/Makefile @@ -0,0 +1,40 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +top_srcdir = .. + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = Ice Glacier2 IceStorm IceGrid + +.PHONY: $(EVERYTHING) $(SUBDIRS) + +# +# Dependencies for 'all' target when using -jx +# + +Glacier2 IceStorm IceGrid: Ice + +IceGrid: Glacier2 + +all:: $(SUBDIRS) + +$(SUBDIRS): + @echo "making all in $@" + @$(MAKE) all --directory=$@ + +$(EVERYTHING_EXCEPT_ALL):: + @for subdir in $(SUBDIRS); \ + do \ + if test -d $$subdir ; \ + then \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + fi; \ + done diff --git a/objc/test/Common/.gitignore b/objc/test/Common/.gitignore new file mode 100644 index 00000000000..3a412ca89c7 --- /dev/null +++ b/objc/test/Common/.gitignore @@ -0,0 +1,4 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +.depend diff --git a/objc/test/Common/Makefile b/objc/test/Common/Makefile new file mode 100644 index 00000000000..ae5bd29f922 --- /dev/null +++ b/objc/test/Common/Makefile @@ -0,0 +1,50 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +LIBNAME = $(call mklibname,TestCommon) + +TARGETS = ../../lib/$(LIBNAME) + +OBJS = TestCommon.o + +SRCS := $(OBJS:.o=.m) +DEPENDFLAGS = --obj-dir + +include $(top_srcdir)/config/Make.rules + +ifeq ($(STATICLIBS),yes) + mklibname = lib$(1).a +else + mklibname = lib$(1).dylib +endif + +OBJS := $(addprefix $(OBJDIR)/,$(OBJS)) + +CPPFLAGS := -I../include $(CPPFLAGS) + +ifeq ($(STATICLIBS),yes) + +../../lib/$(LIBNAME): $(OBJS) + rm -f $@ + $(call mklib,$@,$(OBJS)) + +else + +../../lib/$(LIBNAME): $(OBJS) + rm -f $@ + $(call mkshlib,$@,$(LIBNAME),$(OBJS),$(LIBS)) + +endif + +$(OBJDIR)/%.o: %.m + $(CC) -c $(CPPFLAGS) $(OBJCFLAGS) $(CFLAGS) $< -o $@ + + diff --git a/objc/test/Common/TestCommon.m b/objc/test/Common/TestCommon.m new file mode 100644 index 00000000000..69cd7e9c4ff --- /dev/null +++ b/objc/test/Common/TestCommon.m @@ -0,0 +1,251 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <TestCommon.h> + +#include <stdarg.h> +#include <stdlib.h> + +#import <objc/Ice.h> + +@implementation TestFailedException +-(id)init +{ + return [super initWithName:@"TestFailedException" reason:nil userInfo:nil]; +} +@end + +#if TARGET_OS_IPHONE + +#import <Foundation/NSString.h> +#import <Foundation/NSObject.h> +#import <Foundation/NSThread.h> + +#include <Ice/Ice.h> + +static id outputTarget; +static id testRun; +static SEL readySelector; +static SEL outputSelector; +static id<ICECommunicator> communicator = nil; +static BOOL ssl; + +static BOOL sliced; +static BOOL encoding10; + +#endif + +id<ICEProperties> +defaultServerProperties(int *argc, char** argv) +{ + id<ICEProperties> properties = [ICEUtil createProperties]; + +#if TARGET_OS_IPHONE + static NSString* defaults[] = + { + @"Ice.NullHandleAbort", @"1", + @"Ice.Warn.Connections", @"1", + @"Ice.ThreadPool.Server.Size", @"1", + @"Ice.ThreadPool.Server.SizeMax", @"3", + @"Ice.ThreadPool.Server.SizeWarn", @"0", + //@"Ice.PrintAdapterReady", @"1", + @"Ice.ServerIdleTime", @"30", + @"Ice.Default.Host", @"127.0.0.1", + @"Ice.Trace.Network", @"0", + @"Ice.Trace.Protocol", @"0" + }; + + static NSString* ssldefaults[] = + { + @"Ice.Default.Protocol", @"ssl", + @"Ice.Override.ConnectTimeout", @"10000", // COMPILERFIX: Workaround for SSL hang on iOS devices + @"IceSSL.CertAuthFile", @"cacert.der", + @"IceSSL.CheckCertName", @"0", + @"IceSSL.CertFile", @"s_rsa1024.pfx", + @"IceSSL.Password", @"password" + }; + + int i; + for(i = 0; i < sizeof(defaults)/sizeof(defaults[0]); i += 2) + { + [properties setProperty:defaults[i] value:defaults[i+1]]; + } + if(ssl) + { + for(i = 0; i < sizeof(ssldefaults)/sizeof(ssldefaults[0]); i += 2) + { + [properties setProperty:ssldefaults[i] value:ssldefaults[i+1]]; + } + } + + if(sliced) + { + [properties setProperty:@"Ice.Default.SlicedFormat" value:@"1"]; + } + else if(encoding10) + { + [properties setProperty:@"Ice.Default.EncodingVersion" value:@"1.0"]; + } +#endif + + NSArray* args = [properties parseIceCommandLineOptions:[ICEUtil argsToStringSeq:*argc argv:argv]]; + [ICEUtil stringSeqToArgs:args argc:argc argv:argv]; + + return properties; +} + +id<ICEProperties> +defaultClientProperties(int* argc, char** argv) +{ + id<ICEProperties> properties = [ICEUtil createProperties]; + +#if TARGET_OS_IPHONE + static NSString* defaults[] = + { + @"Ice.NullHandleAbort", @"1", + @"Ice.Warn.Connections", @"1", + @"Ice.Default.Host", @"127.0.0.1", + @"Ice.Trace.Network", @"0", + @"Ice.Trace.Protocol", @"0" + }; + + static NSString* ssldefaults[] = + { + @"Ice.Default.Protocol", @"ssl", + @"Ice.Override.ConnectTimeout", @"10000", // COMPILERFIX: Workaround for SSL hang on iOS devices + @"IceSSL.CheckCertName", @"0", + @"IceSSL.CertAuthFile", @"cacert.der", + @"IceSSL.CertFile", @"c_rsa1024.pfx", + @"IceSSL.Password", @"password", + @"IceSSL.TrustOnly.Client", @"25 9D 03 60 D5 6D 46 3C 32 EE FE 54 48 7A 76 68 FF 6A 87 1D" + }; + + int i; + for(i = 0; i < sizeof(defaults)/sizeof(defaults[0]); i += 2) + { + [properties setProperty:defaults[i] value:defaults[i+1]]; + } + + if(ssl) + { + for(i = 0; i < sizeof(ssldefaults)/sizeof(ssldefaults[0]); i += 2) + { + [properties setProperty:ssldefaults[i] value:ssldefaults[i+1]]; + } + } + if(sliced) + { + [properties setProperty:@"Ice.Default.SlicedFormat" value:@""]; + } + else if(encoding10) + { + [properties setProperty:@"Ice.Default.EncodingVersion" value:@"1.0"]; + } +#endif + + NSArray* args = [properties parseIceCommandLineOptions:[ICEUtil argsToStringSeq:*argc argv:argv]]; + [ICEUtil stringSeqToArgs:args argc:argc argv:argv]; + return properties; +} + +#if TARGET_OS_IPHONE + +void +TestCommonInit(id target, SEL output) +{ + outputTarget = target; + outputSelector = output; +} + +void +TestCommonTestInit(id r, SEL ready, BOOL s, BOOL sl, BOOL e10) +{ + testRun = r; + readySelector = ready; + ssl = s; + sliced = sl; + encoding10 = e10; +} + +void +serverReady(id<ICECommunicator> c) +{ +#if defined(__clang__) && !__has_feature(objc_arc) + [communicator release]; + communicator = [c retain]; +#else + communicator = c; +#endif + [testRun performSelectorOnMainThread:readySelector withObject:nil waitUntilDone:NO]; +} + +void +serverStop() +{ + [communicator shutdown]; +} + +void +tprintf(const char* fmt, ...) +{ + va_list va; + va_start(va, fmt); +#if defined(__clang__) && !__has_feature(objc_arc) + NSString* s = [[[NSString alloc] initWithFormat:[NSString stringWithCString:fmt encoding:NSUTF8StringEncoding] + arguments:va] autorelease]; +#else + NSString* s = [[NSString alloc] initWithFormat:[NSString stringWithCString:fmt encoding:NSUTF8StringEncoding] + arguments:va]; + +#endif + va_end(va); + [outputTarget performSelectorOnMainThread:outputSelector withObject:s waitUntilDone:NO]; +} + +void +testFailed(const char* expr, const char* file, unsigned int line) +{ + tprintf("failed!\n"); + tprintf("%s:%u: assertion `%s' failed\n", file, line, expr); +#if defined(__clang__) && !__has_feature(objc_arc) + @throw [[[TestFailedException alloc] init] autorelease]; +#else + @throw [[TestFailedException alloc] init]; +#endif +} + +#else + +#include <stdio.h> + +void +tprintf(const char* fmt, ...) +{ + va_list va; + va_start(va, fmt); + NSString* s = [[[NSString alloc] initWithFormat:[NSString stringWithCString:fmt encoding:NSUTF8StringEncoding] + arguments:va] autorelease]; + va_end(va); + fputs([s UTF8String], stdout); + fflush(stdout); +} + +void +serverReady(id<ICECommunicator> c) +{ +} + +void +testFailed(const char* expr, const char* file, unsigned int line) +{ + tprintf("failed!\n"); + tprintf("%s:%u: assertion `%s' failed\n", file, line, expr); + abort(); +} +#endif diff --git a/objc/test/Ice/Makefile b/objc/test/Ice/Makefile new file mode 100644 index 00000000000..a4a3f4f6c62 --- /dev/null +++ b/objc/test/Ice/Makefile @@ -0,0 +1,47 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = proxy \ + ami \ + operations \ + exceptions \ + inheritance \ + facets \ + objects \ + optional \ + interceptor \ + invoke \ + dispatcher \ + defaultServant \ + defaultValue \ + enums \ + faultTolerance \ + location \ + adapterDeactivation \ + slicing \ + binding \ + hold \ + retry \ + stream \ + timeout \ + hash \ + info \ + metrics \ + services + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done diff --git a/objc/test/Ice/adapterDeactivation/.gitignore b/objc/test/Ice/adapterDeactivation/.gitignore new file mode 100644 index 00000000000..4027eaac940 --- /dev/null +++ b/objc/test/Ice/adapterDeactivation/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +AdapterDeactivationTest.m +AdapterDeactivationTest.h diff --git a/objc/test/Ice/adapterDeactivation/AdapterDeactivationTest.ice b/objc/test/Ice/adapterDeactivation/AdapterDeactivationTest.ice new file mode 100644 index 00000000000..e7dee062747 --- /dev/null +++ b/objc/test/Ice/adapterDeactivation/AdapterDeactivationTest.ice @@ -0,0 +1,23 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestAdapterDeactivation"] +module Test +{ + +interface TestIntf +{ + void transient(); + + void deactivate(); +}; + +}; diff --git a/objc/test/Ice/adapterDeactivation/AllTests.m b/objc/test/Ice/adapterDeactivation/AllTests.m new file mode 100644 index 00000000000..31714ecd975 --- /dev/null +++ b/objc/test/Ice/adapterDeactivation/AllTests.m @@ -0,0 +1,70 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <AdapterDeactivationTest.h> + +id<TestAdapterDeactivationTestIntfPrx> +adapterDeactivationAllTests(id<ICECommunicator> communicator) +{ + tprintf("testing stringToProxy... "); + id<ICEObjectPrx> base = [communicator stringToProxy:@"test:default -p 12010"]; + test(base); + tprintf("ok\n"); + + tprintf("testing checked cast... "); + id<TestAdapterDeactivationTestIntfPrx> obj = [TestAdapterDeactivationTestIntfPrx checkedCast:base]; + test(obj); + test([obj isEqual:base]); + tprintf("ok\n"); + + { + tprintf("creating/destroying/recreating object adapter... "); + id<ICEObjectAdapter> adapter = + [communicator createObjectAdapterWithEndpoints:@"TransientTestAdapter" endpoints:@"default -p 9999"]; + @try + { + [communicator createObjectAdapterWithEndpoints:@"TransientTestAdapter" endpoints:@"default -p 9998"]; + test(NO); + } + @catch(ICEAlreadyRegisteredException*) + { + } + [adapter destroy]; + + // + // Use a different port than the first adapter to avoid an @"address already in use" error. + // + adapter = [communicator createObjectAdapterWithEndpoints:@"TransientTestAdapter" endpoints:@"default -p 9998"]; + [adapter destroy]; + tprintf("ok\n"); + } + + tprintf("creating/activating/deactivating object adapter in one operation... "); + [obj transient]; + tprintf("ok\n"); + + tprintf("deactivating object adapter in the server... "); + [obj deactivate]; + tprintf("ok\n"); + + tprintf("testing whether server is gone... "); + @try + { + [obj ice_ping]; + test(NO); + } + @catch(ICELocalException*) + { + tprintf("ok\n"); + } + + return obj; +} diff --git a/objc/test/Ice/adapterDeactivation/Client.m b/objc/test/Ice/adapterDeactivation/Client.m new file mode 100644 index 00000000000..862dd0ceb9d --- /dev/null +++ b/objc/test/Ice/adapterDeactivation/Client.m @@ -0,0 +1,76 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <AdapterDeactivationTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + id<TestAdapterDeactivationTestIntfPrx> adapterDeactivationAllTests(id<ICECommunicator>); + adapterDeactivationAllTests(communicator); + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main adapterDeactivationClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestAdapterDeactivation", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/adapterDeactivation/Makefile b/objc/test/Ice/adapterDeactivation/Makefile new file mode 100644 index 00000000000..aad957767db --- /dev/null +++ b/objc/test/Ice/adapterDeactivation/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = AdapterDeactivationTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/adapterDeactivation/Server.m b/objc/test/Ice/adapterDeactivation/Server.m new file mode 100644 index 00000000000..e22da9b9f29 --- /dev/null +++ b/objc/test/Ice/adapterDeactivation/Server.m @@ -0,0 +1,82 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <adapterDeactivation/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010:udp"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + [adapter add:[[[TestAdapterDeactivationI alloc] init] autorelease] identity:[communicator stringToIdentity:@"test"]]; +#else + [adapter add:[[TestAdapterDeactivationI alloc] init] identity:[communicator stringToIdentity:@"test"]]; +#endif + [adapter activate]; + + serverReady(communicator); + + [adapter waitForDeactivate]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main adapterDeactivationServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestAdapterDeactivation", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/adapterDeactivation/TestI.h b/objc/test/Ice/adapterDeactivation/TestI.h new file mode 100644 index 00000000000..d6427154cfb --- /dev/null +++ b/objc/test/Ice/adapterDeactivation/TestI.h @@ -0,0 +1,15 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <AdapterDeactivationTest.h> + +@interface TestAdapterDeactivationI : TestAdapterDeactivationTestIntf<TestAdapterDeactivationTestIntf> +-(void) transient:(ICECurrent*)current; +-(void) deactivate:(ICECurrent*)current; +@end diff --git a/objc/test/Ice/adapterDeactivation/TestI.m b/objc/test/Ice/adapterDeactivation/TestI.m new file mode 100644 index 00000000000..40b8ba8b849 --- /dev/null +++ b/objc/test/Ice/adapterDeactivation/TestI.m @@ -0,0 +1,31 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <adapterDeactivation/TestI.h> + +#import <Foundation/NSThread.h> + +@implementation TestAdapterDeactivationI + +-(void) transient:(ICECurrent*)current +{ + id<ICECommunicator> communicator = [current.adapter getCommunicator]; + id<ICEObjectAdapter> adapter = + [communicator createObjectAdapterWithEndpoints:@"TransientTestAdapter" endpoints:@"default -p 9999"]; + [adapter activate]; + [adapter destroy]; +} + +-(void) deactivate:(ICECurrent*)current +{ + [current.adapter deactivate]; + [NSThread sleepForTimeInterval:1]; +} +@end diff --git a/objc/test/Ice/adapterDeactivation/run.py b/objc/test/Ice/adapterDeactivation/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/adapterDeactivation/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/ami/.gitignore b/objc/test/Ice/ami/.gitignore new file mode 100644 index 00000000000..0c850ff8ce7 --- /dev/null +++ b/objc/test/Ice/ami/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +AMITest.m +AMITest.h diff --git a/objc/test/Ice/ami/AMITest.ice b/objc/test/Ice/ami/AMITest.ice new file mode 100644 index 00000000000..43feb67be75 --- /dev/null +++ b/objc/test/Ice/ami/AMITest.ice @@ -0,0 +1,41 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +#include <Ice/BuiltinSequences.ice> + +["objc:prefix:TestAMI"] +module Test +{ + +exception TestIntfException +{ +}; + +interface TestIntf +{ + void op(); + void opWithPayload(Ice::ByteSeq seq); + int opWithResult(); + void opWithUE() + throws TestIntfException; + void opBatch(); + int opBatchCount(); + bool waitForBatch(int count); + void shutdown(); +}; + +interface TestIntfController +{ + void holdAdapter(); + void resumeAdapter(); +}; + +}; diff --git a/objc/test/Ice/ami/AllTests.m b/objc/test/Ice/ami/AllTests.m new file mode 100644 index 00000000000..99c0ef5c944 --- /dev/null +++ b/objc/test/Ice/ami/AllTests.m @@ -0,0 +1,760 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <AMITest.h> + +#import <Foundation/Foundation.h> + +@interface TestAMICallback : NSObject +{ + BOOL called; + NSCondition* cond; +} +-(BOOL) check; +-(void) called; +@end + +@implementation TestAMICallback +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + cond = [[NSCondition alloc] init]; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [super dealloc]; +} +#endif + +-(BOOL) check +{ + [cond lock]; + while(!called) + { + if(![cond waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:50]]) + { + return NO; + } + } + called = NO; + [cond unlock]; + return YES; +} +-(void) called +{ + [cond lock]; + called = YES; + [cond signal]; + [cond unlock]; +} + ++(id) create +{ +#if defined(__clang__) && __has_feature(objc_arc) + return [[TestAMICallback alloc] init]; +#else + return [[[TestAMICallback alloc] init] autorelease]; +#endif +} + +@end + +void +amiAllTests(id<ICECommunicator> communicator) +{ + NSString* ref = @"test:default -p 12010"; + id<ICEObjectPrx> base = [communicator stringToProxy:(ref)]; + id<TestAMITestIntfPrx> p = [TestAMITestIntfPrx checkedCast:base]; + test(p); + + ref = @"testController:tcp -p 12011"; + base = [communicator stringToProxy:ref]; + TestAMITestIntfControllerPrx* testController = [TestAMITestIntfControllerPrx uncheckedCast:base]; + test(testController); + + tprintf("testing begin/end invocation... "); + { + ICEContext* ctx = [ICEContext dictionary]; + id<ICEAsyncResult> result; + + result = [p begin_ice_isA:[TestAMITestIntfPrx ice_staticId]]; + test([p end_ice_isA:result]); + result = [p begin_ice_isA:[TestAMITestIntfPrx ice_staticId] context:ctx]; + test([p end_ice_isA:result]); + + result = [p begin_ice_ping]; + [p end_ice_ping:result]; + result = [p begin_ice_ping:ctx]; + [p end_ice_ping:result]; + + result = [p begin_ice_id]; + test([[p end_ice_id:result] isEqualToString:[TestAMITestIntfPrx ice_staticId]]); + result = [p begin_ice_id:ctx]; + test([[p end_ice_id:result] isEqualToString:[TestAMITestIntfPrx ice_staticId]]); + + result = [p begin_ice_ids]; + test([[p end_ice_ids:result] count] == 2); + result = [p begin_ice_ids:ctx]; + test([[p end_ice_ids:result] count] == 2); + + result = [p begin_op]; + [p end_op:result]; + result = [p begin_op:ctx]; + [p end_op:result]; + + result = [p begin_opWithResult]; + test([p end_opWithResult:result] == 15); + result = [p begin_opWithResult:ctx]; + test([p end_opWithResult:result] == 15); + + result = [p begin_opWithUE]; + @try + { + [p end_opWithUE:result]; + test(NO); + } + @catch(TestAMITestIntfException*) + { + } + result = [p begin_opWithUE:ctx]; + @try + { + [p end_opWithUE:result]; + test(NO); + } + @catch(TestAMITestIntfException*) + { + } + } + tprintf("ok\n"); + + tprintf("testing response callback... "); + { + TestAMICallback* cb = [TestAMICallback create]; + ICEContext* ctx = [NSDictionary dictionary]; + void (^exCB)(ICEException*) = ^(ICEException* ex) + { + test(NO); + }; + + void (^isACB)(BOOL) = ^(BOOL ret) { test(ret); [cb called]; }; + [p begin_ice_isA:[TestAMITestIntfPrx ice_staticId] response:isACB exception:exCB]; + [cb check]; + [p begin_ice_isA:[TestAMITestIntfPrx ice_staticId] context:ctx response:isACB exception:exCB]; + [cb check]; + + void (^pingCB)() = ^ { [cb called]; }; + [p begin_ice_ping:pingCB exception:exCB]; + [cb check]; + [p begin_ice_ping:ctx response:pingCB exception:exCB]; + [cb check]; + + void (^idCB)(NSString* typeId) = ^(NSString* typeId) + { + test([typeId isEqualToString:[TestAMITestIntfPrx ice_staticId]]); + [cb called]; + }; + + [p begin_ice_id:idCB exception:exCB]; + [cb check]; + [p begin_ice_id:ctx response:idCB exception:exCB]; + [cb check]; + + void (^idsCB)(NSArray* types) = ^(NSArray* types) + { + test([types count] == 2); + [cb called]; + }; + + [p begin_ice_ids:idsCB exception:exCB]; + [cb check]; + [p begin_ice_ids:ctx response:idsCB exception:exCB]; + [cb check]; + + void (^opCB)() = ^ { [cb called]; }; + [p begin_op:opCB exception:exCB]; + [cb check]; + [p begin_op:ctx response:opCB exception:exCB]; + [cb check]; + [p begin_op:nil exception:exCB]; + [p begin_op:ctx response:nil exception:exCB]; + + void (^opWithResultCB)(ICEInt) = ^(ICEInt r) + { + test(r == 15); + [cb called]; + }; + [p begin_opWithResult:opWithResultCB exception:exCB]; + [cb check]; + [p begin_opWithResult:ctx response:opWithResultCB exception:exCB]; + [cb check]; + +#if defined(__clang__) && !__has_feature(objc_arc) + void (^opWithUE)() = [[ ^() { test(NO); } copy ] autorelease]; +#else + void (^opWithUE)() = [ ^() { test(NO); } copy ]; +#endif + void (^opWithUEEx)(ICEException*) = ^(ICEException* ex) + { + @try + { + @throw ex; + test(NO); + } + @catch(TestAMITestIntfException*) + { + [cb called]; + } + }; + [p begin_opWithUE:opWithUE exception:opWithUEEx]; + [cb check]; + [p begin_opWithUE:ctx response:opWithUE exception:opWithUEEx]; + [cb check]; + [p begin_opWithUE:nil exception:opWithUEEx]; + [cb check]; + [p begin_opWithUE:ctx response:nil exception:opWithUEEx]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("testing local exceptions... "); + { + TestAMITestIntfPrx* indirect = [TestAMITestIntfPrx uncheckedCast:[p ice_adapterId:@"dummy"]]; + id<ICEAsyncResult> r; + + r = [indirect begin_op]; + @try + { + [indirect end_op:r]; + test(NO); + } + @catch(ICENoEndpointException*) + { + } + + @try + { + r = [[p ice_oneway] begin_ice_id]; + test(NO); + } + @catch(NSException* ex) + { + test([ex name] == NSInvalidArgumentException); + } + @try + { + r = [[p ice_oneway] begin_opWithResult]; + test(NO); + } + @catch(NSException* ex) + { + test([ex name] == NSInvalidArgumentException); + } + + @try + { + r = [p begin_op:nil exception:nil]; + test(NO); + } + @catch(NSException* ex) + { + test([ex name] == NSInvalidArgumentException); + } + + // + // Check that CommunicatorDestroyedException is raised directly. + // + ICEInitializationData* initData = [ICEInitializationData initializationData]; + [initData setProperties:[[communicator getProperties] clone]]; + id<ICECommunicator> ic = [ICEUtil createCommunicator:initData]; + id<ICEObjectPrx> obj = [ic stringToProxy:[p ice_toString]]; + id<TestAMITestIntfPrx> p2 = [TestAMITestIntfPrx checkedCast:obj]; + + [ic destroy]; + + @try + { + [p2 begin_op]; + test(NO); + } + @catch(ICECommunicatorDestroyedException*) + { + // Expected. + } + } + tprintf("ok\n"); + + tprintf("testing exception callback... "); + { + id<TestAMITestIntfPrx> i = [TestAMITestIntfPrx uncheckedCast:[p ice_adapterId:@"dummy"]]; + TestAMICallback* cb = [TestAMICallback create]; + ICEContext* ctx = [NSDictionary dictionary]; + + void (^exCB)(ICEException*) = ^(ICEException* ex) { + test([ex isKindOfClass:[ICENoEndpointException class]]); + [cb called]; + }; + +#if defined(__clang__) && !__has_feature(objc_arc) + void (^isACB)(BOOL) = [[ ^(BOOL ret) { test(NO); } copy ] autorelease]; +#else + void (^isACB)(BOOL) = [ ^(BOOL ret) { test(NO); } copy ]; +#endif + [i begin_ice_isA:@"dummy" response:isACB exception:exCB]; + [cb check]; + [i begin_ice_isA:@"dummy" context:ctx response:isACB exception:exCB]; + [cb check]; + +#if defined(__clang__) && !__has_feature(objc_arc) + void (^pingCB)() = [[ ^ { test(NO); } copy ] autorelease]; +#else + void (^pingCB)() = [ ^ { test(NO); } copy ]; +#endif + [i begin_ice_ping:pingCB exception:exCB]; + [cb check]; + [i begin_ice_ping:ctx response:pingCB exception:exCB]; + [cb check]; + +#if defined(__clang__) && !__has_feature(objc_arc) + void (^idCB)(NSString*) = [[ ^(NSString* ret) { test(NO); } copy ] autorelease]; +#else + void (^idCB)(NSString*) = [ ^(NSString* ret) { test(NO); } copy ]; +#endif + [i begin_ice_id:idCB exception:exCB]; + [cb check]; + [i begin_ice_id:ctx response:idCB exception:exCB]; + [cb check]; + +#if defined(__clang__) && !__has_feature(objc_arc) + void (^idsCB)(NSArray*) = [[ ^(NSArray* ret) { test(NO); } copy ] autorelease]; +#else + void (^idsCB)(NSArray*) = [ ^(NSArray* ret) { test(NO); } copy ]; +#endif + [i begin_ice_ids:idsCB exception:exCB]; + [cb check]; + [i begin_ice_ids:ctx response:idsCB exception:exCB]; + [cb check]; + +#if defined(__clang__) && !__has_feature(objc_arc) + void (^opCB)() = [[ ^ { test(NO); } copy ] autorelease]; +#else + void (^opCB)() = [ ^ { test(NO); } copy ]; +#endif + [i begin_op:opCB exception:exCB]; + [cb check]; + [i begin_op:ctx response:opCB exception:exCB]; + [cb check]; + + @try + { + [p begin_opWithResult:nil exception:^(ICEException* ex) { test(NO); }]; + test(NO); + } + @catch(NSException* ex) + { + test([ex name] == NSInvalidArgumentException); + } + } + tprintf("ok\n"); + + tprintf("testing sent callback... "); + { + TestAMICallback* cb = [TestAMICallback create]; + ICEContext* ctx = [NSDictionary dictionary]; + void (^exCB)(ICEException*) = ^(ICEException* ex) { + test(NO); + }; + + void (^sentCB)(BOOL) = ^(BOOL ss) { [cb called]; }; + + [p begin_ice_isA:@"test" response:nil exception:exCB sent:sentCB]; + [cb check]; + [p begin_ice_isA:@"test" context:ctx response:nil exception:exCB sent:sentCB]; + [cb check]; + + [p begin_ice_ping:nil exception:exCB sent:sentCB]; + [cb check]; + [p begin_ice_ping:ctx response:nil exception:exCB sent:sentCB]; + [cb check]; + + [p begin_ice_id:nil exception:exCB sent:sentCB]; + [cb check]; + [p begin_ice_id:ctx response:nil exception:exCB sent:sentCB]; + [cb check]; + + [p begin_ice_ids:nil exception:exCB sent:sentCB]; + [cb check]; + [p begin_ice_ids:ctx response:nil exception:exCB sent:sentCB]; + [cb check]; + + [p begin_op:nil exception:exCB sent:sentCB]; + [cb check]; + [p begin_op:ctx response:nil exception:exCB sent:sentCB]; + [cb check]; + + ICEByte d[1024]; + ICEMutableByteSeq* seq = [ICEMutableByteSeq dataWithBytes:d length:sizeof(d)]; + [testController holdAdapter]; + NSMutableArray* cbs = [NSMutableArray array]; + + @autoreleasepool + { + @try + { + TestAMICallback* cb = [TestAMICallback create]; + while(true) + { + if(![[p begin_opWithPayload:seq response:nil exception:exCB sent: + ^(BOOL ss) { + [cb called]; + }] sentSynchronously]) + { + [cbs addObject:cb]; + break; + } + [cbs addObject:cb]; + cb = [TestAMICallback create]; + } + } + @catch(NSException* ex) + { + [testController resumeAdapter]; + @throw ex; + } + [testController resumeAdapter]; + for(TestAMICallback* cb in cbs) + { + [cb check]; + } + } + } + tprintf("ok\n"); + + tprintf("testing illegal arguments... "); + { + id<ICEAsyncResult> result; + + result = [p begin_op]; + [p end_op:result]; + @try + { + [p end_op:result]; + test(NO); + } + @catch(NSException* ex) + { + test([ex name] == NSInvalidArgumentException); + } + + result = [p begin_op]; + @try + { + [p end_opWithResult:result]; + test(NO); + } + @catch(NSException* ex) + { + test([ex name] == NSInvalidArgumentException); + } + + @try + { + [p end_op:nil]; + test(NO); + } + @catch(NSException* ex) + { + test([ex name] == NSInvalidArgumentException); + } + } + tprintf("ok\n"); + + tprintf("testing unexpected exceptions from callback... "); + { + id<TestAMITestIntfPrx> q = [TestAMITestIntfPrx uncheckedCast:[p ice_adapterId:@"dummy"]]; + TestAMICallback* cb = [TestAMICallback create]; + void (^thrower)() = ^(int i) + { + [cb called]; + switch(i) + { + case 0: + { + @throw [ICEObjectNotExistException objectNotExistException:__FILE__ line:__LINE__]; + } + case 1: + { + @throw [TestAMITestIntfException testIntfException]; + } + case 2: + { + @throw [NSException exceptionWithName:@"" reason:nil userInfo:nil]; + } + } + }; + + void (^exCB)(ICEException*) = ^(ICEException* ex) + { + test(NO); + }; + + int i; + for(i = 0; i < 3; ++i) + { + void (^throwResponse)() = ^{ thrower(i); }; + void (^throwEx)(ICEException*) = ^(ICEException* ex){ thrower(i); }; + void (^throwSent)(BOOL) = ^(BOOL b){ thrower(i); }; + + [p begin_ice_ping:throwResponse exception:exCB]; + [cb check]; + + [q begin_ice_ping:nil exception:throwEx]; + [cb check]; + + [p begin_ice_ping:nil exception:exCB sent:throwSent]; + [cb check]; + + [p begin_op:throwResponse exception:exCB]; + [cb check]; + + [q begin_op:nil exception:throwEx]; + [cb check]; + + [p begin_op:nil exception:exCB sent:throwSent]; + [cb check]; + } + } + tprintf("ok\n"); + + tprintf("testing batch requests with proxy... "); + { + { + test([p opBatchCount] == 0); + id<TestAMITestIntfPrx> b1 = [p ice_batchOneway]; + [b1 opBatch]; + [b1 opBatch]; + TestAMICallback* cb = [TestAMICallback create]; + id<ICEAsyncResult> r = [b1 begin_ice_flushBatchRequests:^(ICEException* ex) { test(NO); } + sent:^(BOOL sentSynchronously) { [cb called]; }]; + [cb check]; + test([r isSent]); + test([r isCompleted]); + test([p waitForBatch:2]); + } + + { + test([p opBatchCount] == 0); + id<TestAMITestIntfPrx> b1 = [p ice_batchOneway]; + [b1 opBatch]; + [[b1 ice_getConnection] close:false]; + TestAMICallback* cb = [TestAMICallback create]; + id<ICEAsyncResult> r = [b1 begin_ice_flushBatchRequests:^(ICEException* ex) { [cb called]; } + sent:^(BOOL sentSynchronously) { test(NO); }]; + [cb check]; + test(![r isSent]); + test([r isCompleted]); + test([p opBatchCount] == 0); + } + } + tprintf("ok\n"); + + tprintf("testing batch requests with connection... "); + { + { + test([p opBatchCount] == 0); + id<TestAMITestIntfPrx> b1 = [p ice_batchOneway]; + [b1 opBatch]; + [b1 opBatch]; + TestAMICallback* cb = [TestAMICallback create]; + id<ICEAsyncResult> r = [[b1 ice_getConnection] begin_flushBatchRequests:^(ICEException* ex) { test(NO); } + sent:^(BOOL sentSynchronously) { [cb called]; }]; + [cb check]; + test([r isSent]); + test([r isCompleted]); + test([p waitForBatch:2]); + } + + { + test([p opBatchCount] == 0); + TestAMITestIntfPrx* b1 = [p ice_batchOneway]; + [b1 opBatch]; + [[b1 ice_getConnection] close:false]; + TestAMICallback* cb = [TestAMICallback create]; + id<ICEAsyncResult> r = [[b1 ice_getConnection] begin_flushBatchRequests: + ^(ICEException* ex) { [cb called]; } + sent:^(BOOL sentSynchronously) { test(NO); }]; + [cb check]; + test(![r isSent]); + test([r isCompleted]); + test([p opBatchCount] == 0); + } + } + tprintf("ok\n"); + + tprintf("testing batch requests with communicator... "); + { + { + test([p opBatchCount] == 0); + id<TestAMITestIntfPrx> b1 = [p ice_batchOneway]; + [b1 opBatch]; + [b1 opBatch]; + TestAMICallback* cb = [TestAMICallback create]; + id<ICEAsyncResult> r = [communicator begin_flushBatchRequests:^(ICEException* ex) { test(NO); } + sent:^(BOOL sentSynchronously) { [cb called]; }]; + [cb check]; + test([r isSent]); + test([r isCompleted]); + test([p waitForBatch:2]); + } + + { + test([p opBatchCount] == 0); + TestAMITestIntfPrx* b1 = [p ice_batchOneway]; + [b1 opBatch]; + [[b1 ice_getConnection] close:false]; + TestAMICallback* cb = [TestAMICallback create]; + id<ICEAsyncResult> r = [communicator begin_flushBatchRequests:^(ICEException* ex) { test(NO); } + sent:^(BOOL sentSynchronously) { [cb called]; }]; + [cb check]; + test([r isSent]); + test([r isCompleted]); + test([p opBatchCount] == 0); + } + } + tprintf("ok\n"); + + tprintf("testing AsyncResult operations... "); + { + { + id<TestAMITestIntfPrx> indirect = [TestAMITestIntfPrx uncheckedCast:[p ice_adapterId:@"dummy"]]; + id<ICEAsyncResult> r = [indirect begin_op]; + @try + { + [r waitForCompleted]; + [r throwLocalException]; + } + @catch(ICENoEndpointException* ex) + { + } + + [testController holdAdapter]; + id<ICEAsyncResult> r1; + id<ICEAsyncResult> r2; + @try + { + r1 = [p begin_op]; + ICEByte d[1024]; + ICEMutableByteSeq* seq = [ICEMutableByteSeq dataWithBytes:d length:sizeof(d)]; + while([(r2 = [p begin_opWithPayload:seq]) sentSynchronously]); + + test(r1 == r1); + test(r1 != r2); + + test(([r1 sentSynchronously] && [r1 isSent] && ![r1 isCompleted]) || + (![r1 sentSynchronously] && ![r1 isCompleted])); + + test(![r2 sentSynchronously] && ![r2 isCompleted]); + } + @catch(NSException* ex) + { + [testController resumeAdapter]; + @throw ex; + } + [testController resumeAdapter]; + + [r1 waitForSent]; + test([r1 isSent]); + + [r2 waitForSent]; + test([r2 isSent]); + + [r1 waitForCompleted]; + test([r1 isCompleted]); + + [r2 waitForCompleted]; + test([r2 isCompleted]); + + test([[r1 getOperation] isEqualToString:@"op"]); + test([[r2 getOperation] isEqualToString:@"opWithPayload"]); + } + + { + id<ICEAsyncResult> r; + + // + // Twoway + // + r = [p begin_ice_ping]; + test([[r getOperation] isEqualToString:@"ice_ping"]); + test([r getConnection] == nil); // Expected + test([r getCommunicator] == communicator); + test([[r getProxy] isEqual:p]); + [p end_ice_ping:r]; + + id<TestAMITestIntfPrx> p2; + + // + // Oneway + // + p2 = [p ice_oneway]; + r = [p2 begin_ice_ping]; + test([[r getOperation] isEqualToString:@"ice_ping"]); + test(![r getConnection]); // Expected + test([r getCommunicator] == communicator); + test([[r getProxy] isEqual:p2]); + + // + // Batch request via proxy + // + p2 = [p ice_batchOneway]; + [p2 ice_ping]; + r = [p2 begin_ice_flushBatchRequests]; + test([r getConnection] == nil); // Expected + test([r getCommunicator] == communicator); + test([[r getProxy] isEqual:p2]); + [p2 end_ice_flushBatchRequests:r]; + + // + // Batch request via connection + // + id<ICEConnection> con = [p ice_getConnection]; + p2 = [p ice_batchOneway]; + [p2 ice_ping]; + r = [con begin_flushBatchRequests]; + test([[r getConnection] isEqual:con]); + test([r getCommunicator] == communicator); + test([r getProxy] == nil); // Expected + [con end_flushBatchRequests:r]; + + // + // Batch request via communicator + // + p2 = [p ice_batchOneway]; + [p2 ice_ping]; + r = [communicator begin_flushBatchRequests]; + test([r getConnection] == nil); // Expected + test([r getCommunicator] == communicator); + test([r getProxy] == nil); // Expected + [communicator end_flushBatchRequests:r]; + } + } + tprintf("ok\n"); + + [p shutdown]; +} diff --git a/objc/test/Ice/ami/Client.m b/objc/test/Ice/ami/Client.m new file mode 100644 index 00000000000..f3928e205a6 --- /dev/null +++ b/objc/test/Ice/ami/Client.m @@ -0,0 +1,93 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <AMITest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + void amiAllTests(id<ICECommunicator>); + amiAllTests(communicator); + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main amiClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); + // + // In this test, we need at least two threads in the + // client side thread pool for nested AMI. + // + [initData.properties setProperty:@"Ice.ThreadPool.Client.Size" value:@"2"]; + [initData.properties setProperty:@"Ice.ThreadPool.Client.SizeWarn" value:@"0"]; + [initData.properties setProperty:@"Ice.Warn.AMICallback" value:@"0"]; + + // + // We must set MessageSizeMax to an explicit values, because + // we run tests to check whether Ice.MemoryLimitException is + // raised as expected. + // + [initData.properties setProperty:@"Ice.MessageSizeMax" value:@"100"]; + +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestAMI", @"::Test", + nil]; +#endif + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/ami/Makefile b/objc/test/Ice/ami/Makefile new file mode 100644 index 00000000000..47b7ecc1506 --- /dev/null +++ b/objc/test/Ice/ami/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = AMITest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/ami/Server.m b/objc/test/Ice/ami/Server.m new file mode 100644 index 00000000000..1ac7c651ea9 --- /dev/null +++ b/objc/test/Ice/ami/Server.m @@ -0,0 +1,103 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <ami/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAMIAdapter.Endpoints" value:@"default -p 12010:udp"]; + [[communicator getProperties] setProperty:@"ControllerAdapter.Endpoints" value:@"tcp -p 12011"]; + [[communicator getProperties] setProperty:@"ControllerAdapter.ThreadPool.Size" value:@"1"]; + + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAMIAdapter"]; + id<ICEObjectAdapter> adapter2 = [communicator createObjectAdapter:@"ControllerAdapter"]; + +#if defined(__clang__) && !__has_feature(objc_arc) + TestAMITestIntfControllerI* testController + = [[[TestAMITestIntfControllerI alloc] initWithAdapter:adapter] autorelease]; + + [adapter add:[[[TestAMITestIntfI alloc] init] autorelease] identity:[communicator stringToIdentity:@"test"]]; +#else + TestAMITestIntfControllerI* testController + = [[TestAMITestIntfControllerI alloc] initWithAdapter:adapter]; + + [adapter add:[[TestAMITestIntfI alloc] init] identity:[communicator stringToIdentity:@"test"]]; +#endif + [adapter activate]; + + [adapter2 add:testController identity:[communicator stringToIdentity:@"testController"]]; + [adapter2 activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main amiServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); + + // + // Its possible to have batch oneway requests dispatched after + // the adapter is deactivated due to thread scheduling so we + // supress this warning. + // + [initData.properties setProperty:@"Ice.Warn.Dispatch" value:@"0"]; +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestAMI", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/ami/TestI.h b/objc/test/Ice/ami/TestI.h new file mode 100644 index 00000000000..3535f73f0c8 --- /dev/null +++ b/objc/test/Ice/ami/TestI.h @@ -0,0 +1,29 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <AMITest.h> +#import <Foundation/Foundation.h> + +// +// Servant implementation +// +@interface TestAMITestIntfI : TestAMITestIntf<TestAMITestIntf> +{ + int _batchCount; + NSCondition* _cond; +} +@end + +@interface TestAMITestIntfControllerI : TestAMITestIntfController<TestAMITestIntfController> +{ + id<ICEObjectAdapter> _adapter; +} +-(id) initWithAdapter:(id<ICEObjectAdapter>)adapter; +@end + diff --git a/objc/test/Ice/ami/TestI.m b/objc/test/Ice/ami/TestI.m new file mode 100644 index 00000000000..0357daeef42 --- /dev/null +++ b/objc/test/Ice/ami/TestI.m @@ -0,0 +1,114 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> + +#import <ami/TestI.h> +#import <TestCommon.h> + +@implementation TestAMITestIntfI +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + _cond = [[NSCondition alloc] init]; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [_cond release]; + [super dealloc]; +} +#endif + +-(void) op:(ICECurrent*)current +{ +} +-(void) opWithPayload:(ICEMutableByteSeq*)data current:(ICECurrent*)current +{ +} +-(int) opWithResult:(ICECurrent*)current +{ + return 15; +} +-(void) opWithUE:(ICECurrent*)current +{ + @throw [TestAMITestIntfException testIntfException]; +} + +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} +-(void) opBatch:(ICECurrent *)current +{ + [_cond lock]; + ++_batchCount; + [_cond signal]; + [_cond unlock]; +} +-(ICEInt) opBatchCount:(ICECurrent *)current +{ + [_cond lock]; + @try + { + return _batchCount; + } + @finally + { + [_cond unlock]; + } + return 0; +} +-(BOOL) waitForBatch:(ICEInt)count current:(ICECurrent *)current +{ + [_cond lock]; + @try + { + while(_batchCount < count) + { + [_cond waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:500]]; + } + BOOL result = count == _batchCount; + _batchCount = 0; + return result; + } + @finally + { + [_cond unlock]; + } + return NO; +} +@end + +@implementation TestAMITestIntfControllerI +-(id) initWithAdapter:(id<ICEObjectAdapter>)adapter +{ + self = [super init]; + if(!self) + { + return nil; + } + _adapter = adapter; + return self; +} +-(void) holdAdapter:(ICECurrent*)current +{ + [_adapter hold]; +} +-(void) resumeAdapter:(ICECurrent*)current +{ + [_adapter activate]; +} +@end diff --git a/objc/test/Ice/ami/run.py b/objc/test/Ice/ami/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/ami/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/binding/.gitignore b/objc/test/Ice/binding/.gitignore new file mode 100644 index 00000000000..111134fb8e1 --- /dev/null +++ b/objc/test/Ice/binding/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +BindingTest.m +BindingTest.h diff --git a/objc/test/Ice/binding/AllTests.m b/objc/test/Ice/binding/AllTests.m new file mode 100644 index 00000000000..6fe816d3262 --- /dev/null +++ b/objc/test/Ice/binding/AllTests.m @@ -0,0 +1,886 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <BindingTest.h> + +#import <Foundation/Foundation.h> + +@interface GetAdapterNameCB : NSObject +{ + NSCondition* cond_; + NSString* name_; +} +-(id) init; +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc; +#endif +-(void) response:(NSString*)name; +-(void) exception:(ICEException*)ex; +-(NSString*) getResult; +@end + +@implementation GetAdapterNameCB +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + cond_ = [[NSCondition alloc] init]; + name_ = nil; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond_ release]; + [name_ release]; + [super dealloc]; +} +#endif + +-(void) response:(NSString*)name +{ + [cond_ lock]; +#if defined(__clang__) && !__has_feature(objc_arc) + name_ = [name retain]; +#else + name_ = name; +#endif + [cond_ signal]; + [cond_ unlock]; +} +-(void) exception:(ICEException*)ex +{ + tprintf("unexpected exception: %@", ex); + test(NO); +} +-(NSString*) getResult +{ + [cond_ lock]; + @try + { + while(name_ == nil) + { + [cond_ wait]; + } +#if defined(__clang__) && !__has_feature(objc_arc) + return [[name_ retain] autorelease]; +#else + return name_; +#endif + } + @finally + { + [cond_ unlock]; + } + return nil; +} +@end + +NSString* +getAdapterNameWithAMI(id<TestBindingTestIntfPrx> test) +{ +#if defined(__clang__) && !__has_feature(objc_arc) + GetAdapterNameCB* cb = [[[GetAdapterNameCB alloc] init] autorelease]; +#else + GetAdapterNameCB* cb = [[GetAdapterNameCB alloc] init]; +#endif + [test begin_getAdapterName:^(NSMutableString* name) { [cb response:name]; } + exception:^(ICEException* ex) { [cb exception:ex]; }]; + return [cb getResult]; +} + +NSArray* +getEndpoints(id<TestBindingTestIntfPrx> proxy) +{ + NSMutableArray* edpts = [NSMutableArray array]; + bool escape = NO; + int beg = 0; + int length = 0; + NSString* s = [proxy ice_toString]; + int index; + for(index = 0; index < [s length]; ++index) + { + unichar c = [s characterAtIndex:index]; + if(c == '"') + { + escape = !escape; + } + + if(!escape && c == ':') + { + NSRange range = { beg, length }; + [edpts addObject:[s substringWithRange:range]]; + beg = beg + length + 1; + length = 0; + } + else + { + ++length; + } + } + if(length > 0) + { + NSRange range = { beg, length }; + [edpts addObject:[s substringWithRange:range]]; + } + [edpts removeObjectAtIndex:0]; + return edpts; +} + +id<TestBindingTestIntfPrx> +createTestIntfPrx(NSArray* adapters) +{ + NSMutableArray* endpoints = [NSMutableArray arrayWithCapacity:[adapters count]]; + id<TestBindingTestIntfPrx> test = nil; + for(id<TestBindingRemoteObjectAdapterPrx> a in adapters) + { + test = [a getTestIntf]; + [endpoints addObjectsFromArray:getEndpoints(test)]; + } + NSString* proxy = [[test ice_getCommunicator] identityToString:[test ice_getIdentity]]; + for(NSString* e in endpoints) + { + proxy = [proxy stringByAppendingString:@":"]; + proxy = [proxy stringByAppendingString:e]; + } + return [TestBindingTestIntfPrx uncheckedCast:[[test ice_getCommunicator] stringToProxy:proxy]]; +} + +void +deactivate(id<TestBindingRemoteCommunicatorPrx> com, NSArray* adapters) +{ + for(id<TestBindingRemoteObjectAdapterPrx> a in adapters) + { + [com deactivateObjectAdapter:a]; + } +} + +void +random_shuffle(NSMutableArray* array) +{ + NSUInteger count = [array count]; + while(count--) + { + [array exchangeObjectAtIndex:count withObjectAtIndex:(random() % (count + 1))]; + } +} + +void +bindingAllTests(id<ICECommunicator> communicator) +{ + NSString* ref = @"communicator:default -p 12010"; + id<TestBindingRemoteCommunicatorPrx> com = [TestBindingRemoteCommunicatorPrx uncheckedCast:[ + communicator stringToProxy:ref]]; + + tprintf("testing binding with single endpoint... "); + { + id<TestBindingRemoteObjectAdapterPrx> adapter = [com createObjectAdapter:@"Adapter" endpoints:@"default"]; + + id<TestBindingTestIntfPrx> test1 = [adapter getTestIntf]; + id<TestBindingTestIntfPrx> test2 = [adapter getTestIntf]; + test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]); + + [test1 ice_ping]; + [test2 ice_ping]; + + [com deactivateObjectAdapter:adapter]; + + id<TestBindingTestIntfPrx> test3 = [TestBindingTestIntfPrx uncheckedCast:test1]; + test([[test3 ice_getConnection] isEqual:[test1 ice_getConnection]]); + test([[test3 ice_getConnection] isEqual:[test2 ice_getConnection]]); + + @try + { + [test3 ice_ping]; + test(NO); + } + @catch(ICEConnectionRefusedException*) + { + } + } + tprintf("ok\n"); + + tprintf("testing binding with multiple endpoints... "); + { + NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3]; + [adapters addObject:[com createObjectAdapter:@"Adapter11" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter12" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter13" endpoints:@"default"]]; + + // + // Ensure that when a connection is opened it's reused for new + // proxies and that all endpoints are eventually tried. + // + NSMutableSet* names = [NSMutableSet setWithCapacity:3]; + [names addObject:@"Adapter11"]; + [names addObject:@"Adapter12"]; + [names addObject:@"Adapter13"]; + while([names count] != 0) + { + NSMutableArray* adpts = [adapters mutableCopy]; +#if defined(__clang__) && !__has_feature(objc_arc) + [adpts autorelease]; +#endif + id<TestBindingTestIntfPrx> test1 = createTestIntfPrx(adpts); + random_shuffle(adpts); + id<TestBindingTestIntfPrx> test2 = createTestIntfPrx(adpts); + random_shuffle(adpts); + id<TestBindingTestIntfPrx> test3 = createTestIntfPrx(adpts); + + test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]); + test([[test2 ice_getConnection] isEqual:[test3 ice_getConnection]]); + + [names removeObject:[test1 getAdapterName]]; + [[test1 ice_getConnection] close:NO]; + } + + // + // Ensure that the proxy correctly caches the connection (we + // always send the request over the same connection.) + // + { + for(id<TestBindingRemoteObjectAdapterPrx> a in adapters) + { + [[a getTestIntf] ice_ping]; + } + + id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters); + NSString* name = [test getAdapterName]; + const int nRetry = 10; + int i; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:name]; i++); + test(i == nRetry); + + for(id<TestBindingRemoteObjectAdapterPrx> a in adapters) + { + [[[a getTestIntf] ice_getConnection] close:NO]; + } + } + + // + // Deactivate an adapter and ensure that we can still + // establish the connection to the remaining adapters. + // + [com deactivateObjectAdapter:[adapters objectAtIndex:0]]; + [names addObject:@"Adapter12"]; + [names addObject:@"Adapter13"]; + while([names count] != 0) + { + NSMutableArray* adpts = [adapters mutableCopy]; +#if defined(__clang__) && !__has_feature(objc_arc) + [adpts autorelease]; +#endif + id<TestBindingTestIntfPrx> test1 = createTestIntfPrx(adpts); + random_shuffle(adpts); + id<TestBindingTestIntfPrx> test2 = createTestIntfPrx(adpts); + random_shuffle(adpts); + id<TestBindingTestIntfPrx> test3 = createTestIntfPrx(adpts); + + test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]); + test([[test2 ice_getConnection] isEqual:[test3 ice_getConnection]]); + + [names removeObject:[test1 getAdapterName]]; + [[test1 ice_getConnection] close:NO]; + } + + // + // Deactivate an adapter and ensure that we can still + // establish the connection to the remaining adapter. + // + [com deactivateObjectAdapter:[adapters objectAtIndex:2]]; + id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters); + test([[test getAdapterName] isEqualToString:@"Adapter12"]); + + deactivate(com, adapters); + } + tprintf("ok\n"); + + tprintf("testing binding with multiple endpoints and AMI... "); + { + NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3]; + [adapters addObject:[com createObjectAdapter:@"AdapterAMI11" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"AdapterAMI12" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"AdapterAMI13" endpoints:@"default"]]; + + // + // Ensure that when a connection is opened it's reused for new + // proxies and that all endpoints are eventually tried. + // + NSMutableSet* names = [NSMutableSet setWithCapacity:3]; + [names addObject:@"AdapterAMI11"]; + [names addObject:@"AdapterAMI12"]; + [names addObject:@"AdapterAMI13"]; + while([names count] != 0) + { + NSMutableArray* adpts = [adapters mutableCopy]; +#if defined(__clang__) && !__has_feature(objc_arc) + [adpts autorelease]; +#endif + + id<TestBindingTestIntfPrx> test1 = createTestIntfPrx(adpts); + random_shuffle(adpts); + id<TestBindingTestIntfPrx> test2 = createTestIntfPrx(adpts); + random_shuffle(adpts); + id<TestBindingTestIntfPrx> test3 = createTestIntfPrx(adpts); + + test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]); + test([[test2 ice_getConnection] isEqual:[test3 ice_getConnection]]); + + [names removeObject:getAdapterNameWithAMI(test1)]; + [[test1 ice_getConnection] close:NO]; + } + + // + // Ensure that the proxy correctly caches the connection (we + // always send the request over the same connection.) + // + { + for(id<TestBindingRemoteObjectAdapterPrx> a in adapters) + { + [[a getTestIntf] ice_ping]; + } + + id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters); + NSString* name = getAdapterNameWithAMI(test); + const int nRetry = 10; + int i; + for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:name]; i++); + test(i == nRetry); + + for(id<TestBindingRemoteObjectAdapterPrx> a in adapters) + { + [[[a getTestIntf] ice_getConnection] close:NO]; + } + } + + // + // Deactivate an adapter and ensure that we can still + // establish the connection to the remaining adapters. + // + [com deactivateObjectAdapter:[adapters objectAtIndex:0]]; + [names addObject:@"AdapterAMI12"]; + [names addObject:@"AdapterAMI13"]; + while([names count] != 0) + { + NSMutableArray* adpts = [adapters mutableCopy]; +#if defined(__clang__) && !__has_feature(objc_arc) + [adpts autorelease]; +#endif + + id<TestBindingTestIntfPrx> test1 = createTestIntfPrx(adpts); + random_shuffle(adpts); + id<TestBindingTestIntfPrx> test2 = createTestIntfPrx(adpts); + random_shuffle(adpts); + id<TestBindingTestIntfPrx> test3 = createTestIntfPrx(adpts); + + test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]); + test([[test2 ice_getConnection] isEqual:[test3 ice_getConnection]]); + + [names removeObject:[test1 getAdapterName]]; + [[test1 ice_getConnection] close:NO]; + } + + // + // Deactivate an adapter and ensure that we can still + // establish the connection to the remaining adapter. + // + [com deactivateObjectAdapter:[adapters objectAtIndex:2]]; + id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters); + test([[test getAdapterName] isEqualToString:@"AdapterAMI12"]); + + deactivate(com, adapters); + } + tprintf("ok\n"); + + tprintf("testing random endpoint selection... "); + { + NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3]; + [adapters addObject:[com createObjectAdapter:@"Adapter21" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter22" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter23" endpoints:@"default"]]; + + id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters); + test([test ice_getEndpointSelection] == ICERandom); + + NSMutableSet* names = [NSMutableSet setWithCapacity:3]; + [names addObject:@"Adapter21"]; + [names addObject:@"Adapter22"]; + [names addObject:@"Adapter23"]; + while([names count] != 0) + { + [names removeObject:[test getAdapterName]]; + [[test ice_getConnection] close:NO]; + } + + test = [TestBindingTestIntfPrx uncheckedCast:[test ice_endpointSelection:ICERandom]]; + test([test ice_getEndpointSelection] == ICERandom); + + [names addObject:@"Adapter21"]; + [names addObject:@"Adapter22"]; + [names addObject:@"Adapter23"]; + while([names count] != 0) + { + [names removeObject:[test getAdapterName]]; + [[test ice_getConnection] close:NO]; + } + + deactivate(com, adapters); + } + tprintf("ok\n"); + + tprintf("testing ordered endpoint selection... "); + { + NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3]; + [adapters addObject:[com createObjectAdapter:@"Adapter31" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter32" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter33" endpoints:@"default"]]; + + id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters); + test = [TestBindingTestIntfPrx uncheckedCast:[test ice_endpointSelection:ICEOrdered]]; + test([test ice_getEndpointSelection] == ICEOrdered); + const int nRetry = 5; + int i; + + // + // Ensure that endpoints are tried in order by deactiving the adapters + // one after the other. + // + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter31"]; i++); +#if TARGET_OS_IPHONE > 0 + if(i != nRetry) + { + [[test ice_getConnection] close:NO]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter31"]; i++); + } +#endif + test(i == nRetry); + [com deactivateObjectAdapter:[adapters objectAtIndex:0]]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter32"]; i++); +#if TARGET_OS_IPHONE > 0 + if(i != nRetry) + { + [[test ice_getConnection] close:NO]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter32"]; i++); + } +#endif + test(i == nRetry); + [com deactivateObjectAdapter:[adapters objectAtIndex:1]]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter33"]; i++); +#if TARGET_OS_IPHONE > 0 + if(i != nRetry) + { + [[test ice_getConnection] close:NO]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter33"]; i++); + } +#endif + test(i == nRetry); + [com deactivateObjectAdapter:[adapters objectAtIndex:2]]; + + @try + { + [test getAdapterName]; + } + @catch(ICEConnectionRefusedException*) + { + } + + NSArray* endpoints = getEndpoints(test); + + adapters = [NSMutableArray arrayWithCapacity:3]; + + // + // Now, re-activate the adapters with the same endpoints in the opposite + // order. + // + [adapters addObject:[com createObjectAdapter:@"Adapter36" endpoints:[endpoints objectAtIndex:2]]]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter36"]; i++); +#if TARGET_OS_IPHONE > 0 + if(i != nRetry) + { + [[test ice_getConnection] close:NO]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter36"]; i++); + } +#endif + test(i == nRetry); + [[test ice_getConnection] close:NO]; + [adapters addObject:[com createObjectAdapter:@"Adapter35" endpoints:[endpoints objectAtIndex:1]]]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter35"]; i++); +#if TARGET_OS_IPHONE > 0 + if(i != nRetry) + { + [[test ice_getConnection] close:NO]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter35"]; i++); + } +#endif + test(i == nRetry); + [[test ice_getConnection] close:NO]; + [adapters addObject:[com createObjectAdapter:@"Adapter34" endpoints:[endpoints objectAtIndex:0]]]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter34"]; i++); +#if TARGET_OS_IPHONE > 0 + if(i != nRetry) + { + [[test ice_getConnection] close:NO]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter34"]; i++); + } +#endif + test(i == nRetry); + deactivate(com, adapters); + } + tprintf("ok\n"); + + tprintf("testing per request binding with single endpoint... "); + { + id<TestBindingRemoteObjectAdapterPrx> adapter = [com createObjectAdapter:@"Adapter41" endpoints:@"default"]; + + id<TestBindingTestIntfPrx> test1 = [TestBindingTestIntfPrx uncheckedCast:[[adapter getTestIntf] ice_connectionCached:NO]]; + id<TestBindingTestIntfPrx> test2 = [TestBindingTestIntfPrx uncheckedCast:[[adapter getTestIntf] ice_connectionCached:NO]]; + test(![test1 ice_isConnectionCached]); + test(![test2 ice_isConnectionCached]); + test([[test1 ice_getConnection] isEqual:[test2 ice_getConnection]]); + + [test1 ice_ping]; + + [com deactivateObjectAdapter:adapter]; + + id<TestBindingTestIntfPrx> test3 = [TestBindingTestIntfPrx uncheckedCast:test1]; + @try + { + test([[test3 ice_getConnection] isEqual:[test1 ice_getConnection]]); + test(NO); + } + @catch(ICEConnectionRefusedException*) + { + } + } + tprintf("ok\n"); + + tprintf("testing per request binding with multiple endpoints... "); + { + NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3]; + [adapters addObject:[com createObjectAdapter:@"Adapter51" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter52" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter53" endpoints:@"default"]]; + + id<TestBindingTestIntfPrx> test = [createTestIntfPrx(adapters) ice_connectionCached:NO]; + test(![test ice_isConnectionCached]); + + NSMutableSet* names = [NSMutableSet setWithCapacity:3]; + [names addObject:@"Adapter51"]; + [names addObject:@"Adapter52"]; + [names addObject:@"Adapter53"]; + while([names count] != 0) + { + [names removeObject:[test getAdapterName]]; + } + + [com deactivateObjectAdapter:[adapters objectAtIndex:0]]; + + [names addObject:@"Adapter52"]; + [names addObject:@"Adapter53"]; + while([names count] != 0) + { + [names removeObject:[test getAdapterName]]; + } + + [com deactivateObjectAdapter:[adapters objectAtIndex:2]]; + + + test([[test getAdapterName] isEqualToString:@"Adapter52"]); + + deactivate(com, adapters); + } + tprintf("ok\n"); + + tprintf("testing per request binding with multiple endpoints and AMI... "); + { + NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3]; + [adapters addObject:[com createObjectAdapter:@"AdapterAMI51" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"AdapterAMI52" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"AdapterAMI53" endpoints:@"default"]]; + + id<TestBindingTestIntfPrx> test = [createTestIntfPrx(adapters) ice_connectionCached:NO]; + test(![test ice_isConnectionCached]); + + NSMutableSet* names = [NSMutableSet setWithCapacity:3]; + [names addObject:@"AdapterAMI51"]; + [names addObject:@"AdapterAMI52"]; + [names addObject:@"AdapterAMI53"]; + while([names count] != 0) + { + [names removeObject:getAdapterNameWithAMI(test)]; + } + + [com deactivateObjectAdapter:[adapters objectAtIndex:0]]; + + [names addObject:@"AdapterAMI52"]; + [names addObject:@"AdapterAMI53"]; + while([names count] != 0) + { + [names removeObject:getAdapterNameWithAMI(test)]; + } + + [com deactivateObjectAdapter:[adapters objectAtIndex:2]]; + + test([[test getAdapterName] isEqualToString:@"AdapterAMI52"]); + + deactivate(com, adapters); + } + tprintf("ok\n"); + + tprintf("testing per request binding and ordered endpoint selection... "); + { + NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3]; + [adapters addObject:[com createObjectAdapter:@"Adapter61" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter62" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter63" endpoints:@"default"]]; + + id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters); + test = [TestBindingTestIntfPrx uncheckedCast:[test ice_endpointSelection:ICEOrdered]]; + test([test ice_getEndpointSelection] == ICEOrdered); + test = [TestBindingTestIntfPrx uncheckedCast:[test ice_connectionCached:NO]]; + test(![test ice_isConnectionCached]); + const int nRetry = 5; + int i; + + // + // Ensure that endpoints are tried in order by deactiving the adapters + // one after the other. + // + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter61"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + [com deactivateObjectAdapter:[adapters objectAtIndex:0]]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter62"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + [com deactivateObjectAdapter:[adapters objectAtIndex:1]]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter63"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + [com deactivateObjectAdapter:[adapters objectAtIndex:2]]; + + @try + { + [test getAdapterName]; + } + @catch(ICEConnectionRefusedException*) + { + } + + NSArray* endpoints = getEndpoints(test); + + adapters = [NSMutableArray arrayWithCapacity:3]; + + // + // Now, re-activate the adapters with the same endpoints in the opposite + // order. + // + [adapters addObject:[com createObjectAdapter:@"Adapter66" endpoints:[endpoints objectAtIndex:2]]]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter66"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + [adapters addObject:[com createObjectAdapter:@"Adapter65" endpoints:[endpoints objectAtIndex:1]]]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter65"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + [adapters addObject:[com createObjectAdapter:@"Adapter64" endpoints:[endpoints objectAtIndex:0]]]; + for(i = 0; i < nRetry && [[test getAdapterName] isEqualToString:@"Adapter64"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + + deactivate(com, adapters); + } + tprintf("ok\n"); + + tprintf("testing per request binding and ordered endpoint selection and AMI... "); + { + NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3]; + [adapters addObject:[com createObjectAdapter:@"AdapterAMI61" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"AdapterAMI62" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"AdapterAMI63" endpoints:@"default"]]; + + id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters); + test = [TestBindingTestIntfPrx uncheckedCast:[test ice_endpointSelection:ICEOrdered]]; + test([test ice_getEndpointSelection] == ICEOrdered); + test = [TestBindingTestIntfPrx uncheckedCast:[test ice_connectionCached:NO]]; + test(![test ice_isConnectionCached]); + const int nRetry = 5; + int i; + + // + // Ensure that endpoints are tried in order by deactiving the adapters + // one after the other. + // + for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI61"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + [com deactivateObjectAdapter:[adapters objectAtIndex:0]]; + for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI62"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + [com deactivateObjectAdapter:[adapters objectAtIndex:1]]; + for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI63"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + [com deactivateObjectAdapter:[adapters objectAtIndex:2]]; + + @try + { + [test getAdapterName]; + } + @catch(ICEConnectionRefusedException*) + { + } + + NSArray* endpoints = getEndpoints(test); + + adapters = [NSMutableArray arrayWithCapacity:3]; + + // + // Now, re-activate the adapters with the same endpoints in the opposite + // order. + // + [adapters addObject:[com createObjectAdapter:@"AdapterAMI66" endpoints:[endpoints objectAtIndex:2]]]; + for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI66"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + [adapters addObject:[com createObjectAdapter:@"AdapterAMI65" endpoints:[endpoints objectAtIndex:1]]]; + for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI65"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + [adapters addObject:[com createObjectAdapter:@"AdapterAMI64" endpoints:[endpoints objectAtIndex:0]]]; + for(i = 0; i < nRetry && [getAdapterNameWithAMI(test) isEqualToString:@"AdapterAMI64"]; i++); +#if TARGET_OS_IPHONE > 0 + test(i >= nRetry - 1); // WORKAROUND: for connection establishment hang. +#else + test(i == nRetry); +#endif + + deactivate(com, adapters); + } + tprintf("ok\n"); + + tprintf("testing endpoint mode filtering... "); + { + NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3]; + [adapters addObject:[com createObjectAdapter:@"Adapter71" endpoints:@"default"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter72" endpoints:@"udp"]]; + + id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters); + test([[test getAdapterName] isEqualToString:@"Adapter71"]); + + id<TestBindingTestIntfPrx> testUDP = [TestBindingTestIntfPrx uncheckedCast:[test ice_datagram]]; + test([test ice_getConnection] != [testUDP ice_getConnection]); + @try + { + [testUDP getAdapterName]; + } + @catch(ICETwowayOnlyException*) + { + } + } + tprintf("ok\n"); + + if([[[communicator getProperties] getProperty:@"Ice.Default.Protocol"] isEqual:@"ssl"]) + { + tprintf("testing unsecure vs. secure endpoints... "); + { + NSMutableArray* adapters = [NSMutableArray arrayWithCapacity:3]; + [adapters addObject:[com createObjectAdapter:@"Adapter81" endpoints:@"ssl"]]; + [adapters addObject:[com createObjectAdapter:@"Adapter82" endpoints:@"tcp"]]; + + id<TestBindingTestIntfPrx> test = createTestIntfPrx(adapters); + int i; + for(i = 0; i < 5; i++) + { + test([[test getAdapterName] isEqualToString:@"Adapter82"]); + [[test ice_getConnection] close:NO]; + } + + id<TestBindingTestIntfPrx> testSecure = [TestBindingTestIntfPrx uncheckedCast:[test ice_secure:YES]]; + test([testSecure ice_isSecure]); + testSecure = [TestBindingTestIntfPrx uncheckedCast:[test ice_secure:NO]]; + test(![testSecure ice_isSecure]); + testSecure = [TestBindingTestIntfPrx uncheckedCast:[test ice_secure:YES]]; + test([testSecure ice_isSecure]); + test([test ice_getConnection] != [testSecure ice_getConnection]); + + [com deactivateObjectAdapter:[adapters objectAtIndex:1]]; + + for(i = 0; i < 5; i++) + { + test([[test getAdapterName] isEqualToString:@"Adapter81"]); + [[test ice_getConnection] close:NO]; + } + + [com createObjectAdapter:@"Adapter83" endpoints:[getEndpoints(test) objectAtIndex:1]]; // Reactive tcp OA. + + for(i = 0; i < 5; i++) + { + test([[test getAdapterName] isEqualToString:@"Adapter83"]); + [[test ice_getConnection] close:NO]; + } + + [com deactivateObjectAdapter:[adapters objectAtIndex:0]]; + @try + { + [testSecure ice_ping]; + test(NO); + } + @catch(ICEConnectionRefusedException*) + { + } + + deactivate(com, adapters); + } + tprintf("ok\n"); + } + + [com shutdown]; +} + diff --git a/objc/test/Ice/binding/BindingTest.ice b/objc/test/Ice/binding/BindingTest.ice new file mode 100644 index 00000000000..867b62f3e1b --- /dev/null +++ b/objc/test/Ice/binding/BindingTest.ice @@ -0,0 +1,37 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestBinding"] +module Test +{ + +interface TestIntf +{ + string getAdapterName(); +}; + +interface RemoteObjectAdapter +{ + TestIntf* getTestIntf(); + + void deactivate(); +}; + +interface RemoteCommunicator +{ + RemoteObjectAdapter* createObjectAdapter(string name, string endpoints); + + void deactivateObjectAdapter(RemoteObjectAdapter* adapter); + + void shutdown(); +}; + +}; diff --git a/objc/test/Ice/binding/Client.m b/objc/test/Ice/binding/Client.m new file mode 100644 index 00000000000..34315765336 --- /dev/null +++ b/objc/test/Ice/binding/Client.m @@ -0,0 +1,75 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <BindingTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + void bindingAllTests(id<ICECommunicator>); + bindingAllTests(communicator); + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main bindingClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestBinding", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/binding/Makefile b/objc/test/Ice/binding/Makefile new file mode 100644 index 00000000000..faaade67717 --- /dev/null +++ b/objc/test/Ice/binding/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = BindingTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/binding/Server.m b/objc/test/Ice/binding/Server.m new file mode 100644 index 00000000000..bfcdec84bf0 --- /dev/null +++ b/objc/test/Ice/binding/Server.m @@ -0,0 +1,86 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <binding/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010:udp"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; + ICEIdentity* ident = [communicator stringToIdentity:@"communicator"]; +#if defined(__clang__) && !__has_feature(objc_arc) + [adapter add:[[[RemoteCommunicatorI alloc] init] autorelease] identity:ident]; +#else + [adapter add:[[RemoteCommunicatorI alloc] init] identity:ident]; +#endif + [adapter activate]; + + // Disable ready print for further adapters. + [[communicator getProperties] setProperty:@"Ice.PrintAdapterReady" value:@"0"]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main bindingServer +#endif + +int +main(int argc, char* argv[]) +{ + @autoreleasepool + { + int status; + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestBinding", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; + } +} diff --git a/objc/test/Ice/binding/TestI.h b/objc/test/Ice/binding/TestI.h new file mode 100644 index 00000000000..142d231ade1 --- /dev/null +++ b/objc/test/Ice/binding/TestI.h @@ -0,0 +1,35 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <BindingTest.h> + +@interface RemoteCommunicatorI : TestBindingRemoteCommunicator<TestBindingRemoteCommunicator> +{ + int nextPort_; +} +-(id<TestBindingRemoteObjectAdapterPrx>) createObjectAdapter:(NSMutableString *)name + endpoints:(NSMutableString *)endpoints current:(ICECurrent *)current; +-(void) deactivateObjectAdapter:(id<TestBindingRemoteObjectAdapterPrx>)adapter current:(ICECurrent *)current; +-(void) shutdown:(ICECurrent *)current; +@end + +@interface RemoteObjectAdapterI : TestBindingRemoteObjectAdapter<TestBindingRemoteObjectAdapter> +{ + id<ICEObjectAdapter> adapter_; + id<TestBindingTestIntfPrx> testIntf_; +} +-(id)initWithAdapter:(id<ICEObjectAdapter>)adapter; +-(id<TestBindingTestIntfPrx>) getTestIntf:(ICECurrent *)current; +-(void) deactivate:(ICECurrent *)current; +@end + +@interface TestBindingI : TestBindingTestIntf<TestBindingTestIntf> +-(NSString *) getAdapterName:(ICECurrent *)current; +@end + diff --git a/objc/test/Ice/binding/TestI.m b/objc/test/Ice/binding/TestI.m new file mode 100644 index 00000000000..d7f4cb112ba --- /dev/null +++ b/objc/test/Ice/binding/TestI.m @@ -0,0 +1,105 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <binding/TestI.h> + +@implementation RemoteCommunicatorI +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + nextPort_ = 10001; + return self; +} + + +-(id<TestBindingRemoteObjectAdapterPrx>) createObjectAdapter:(NSMutableString*)name endpoints:(NSMutableString*)endpts + current:(ICECurrent*)current +{ + id<ICECommunicator> com = [current.adapter getCommunicator]; + [[com getProperties] setProperty:[name stringByAppendingString:@".ThreadPool.Size"] value:@"1"]; + id<ICEObjectAdapter> adapter = [com createObjectAdapterWithEndpoints:name endpoints:endpts]; +#if defined(__clang__) && !__has_feature(objc_arc) + RemoteObjectAdapterI* remote = [[[RemoteObjectAdapterI alloc] initWithAdapter:adapter] autorelease]; +#else + RemoteObjectAdapterI* remote = [[RemoteObjectAdapterI alloc] initWithAdapter:adapter]; +#endif + return [TestBindingRemoteObjectAdapterPrx uncheckedCast:[current.adapter addWithUUID:remote]]; +} + +-(void) deactivateObjectAdapter:(id<TestBindingRemoteObjectAdapterPrx>)adapter current:(ICECurrent*)current +{ + [adapter deactivate]; // Collocated call +} + +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} +@end + +@implementation RemoteObjectAdapterI +-(id) initWithAdapter:(id<ICEObjectAdapter>)adapter +{ + self = [super init]; + if(!self) + { + return nil; + } +#if defined(__clang__) && !__has_feature(objc_arc) + adapter_ = [adapter retain]; + testIntf_ = [TestBindingTestIntfPrx uncheckedCast:[adapter_ add:[[[TestBindingI alloc] init] autorelease] + identity:[[adapter_ getCommunicator] stringToIdentity:@"test"]]]; + [testIntf_ retain]; +#else + adapter_ = adapter; + testIntf_ = [TestBindingTestIntfPrx uncheckedCast:[ + adapter_ add:[[TestBindingI alloc] init] + identity:[[adapter_ getCommunicator] stringToIdentity:@"test"]]]; +#endif + [adapter_ activate]; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [testIntf_ release]; + [adapter_ release]; + [super dealloc]; +} +#endif + +-(id<TestBindingTestIntfPrx>) getTestIntf:(ICECurrent*)current +{ + return testIntf_; +} + +-(void) deactivate:(ICECurrent*)current +{ + @try + { + [adapter_ destroy]; + } + @catch(ICEObjectAdapterDeactivatedException*) + { + } +} +@end + +@implementation TestBindingI +-(NSString*) getAdapterName:(ICECurrent*)current +{ + return [current.adapter getName]; +} +@end diff --git a/objc/test/Ice/binding/run.py b/objc/test/Ice/binding/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/binding/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/defaultServant/.gitignore b/objc/test/Ice/defaultServant/.gitignore new file mode 100644 index 00000000000..f330ebd1012 --- /dev/null +++ b/objc/test/Ice/defaultServant/.gitignore @@ -0,0 +1,7 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +.depend +DefaultServantTest.m +DefaultServantTest.h diff --git a/objc/test/Ice/defaultServant/Client.m b/objc/test/Ice/defaultServant/Client.m new file mode 100644 index 00000000000..fb48ecc4ac0 --- /dev/null +++ b/objc/test/Ice/defaultServant/Client.m @@ -0,0 +1,204 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <DefaultServantTest.h> +#import <defaultServant/MyObjectI.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + // + // Create OA + // + id<ICEObjectAdapter> oa = [communicator createObjectAdapterWithEndpoints:@"MyOA" endpoints:@"tcp -h localhost"]; + [oa activate]; + ICEObject* servant = [[TestDefaultServantMyObjectI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [servant autorelease]; +#endif + // + // Register default servant with category "foo" + // + [oa addDefaultServant:servant category:@"foo"]; + + // + // Start test + // + tprintf("testing single category... "); + ICEObject* r = [oa findDefaultServant:@"foo"]; + test(r == servant); + + r = [oa findDefaultServant:@"bar"]; + test(r == nil); + + ICEIdentity* identity = [ICEIdentity identity:@"" category:@"foo"]; + NSArray* stringArray = [NSArray arrayWithObjects:@"foo", @"bar", @"x", @"y", @"abcdefg", nil]; + + for(NSString* name in stringArray) + { + [identity setName:name]; + id<TestDefaultServantMyObjectPrx> prx = [TestDefaultServantMyObjectPrx uncheckedCast:[oa createProxy:identity]]; + [prx ice_ping]; + test([[prx getName] isEqualToString:name]); + } + + [identity setName:@"ObjectNotExist"]; + id<TestDefaultServantMyObjectPrx> prx = [TestDefaultServantMyObjectPrx uncheckedCast:[oa createProxy:identity]]; + @try + { + [prx ice_ping]; + //test(NO); + } + @catch(ICEObjectNotExistException*) + { + // expected + } + @try + { + [prx getName]; + test(NO); + } + @catch(ICEObjectNotExistException*) + { + // expected + } + + [identity setName:@"FacetNotExist"]; + prx = [TestDefaultServantMyObjectPrx uncheckedCast:[oa createProxy:identity]]; + + @try + { + [prx ice_ping]; + test(NO); + } + @catch(ICEFacetNotExistException*) + { + // expected + } + + @try + { + [prx getName]; + test(NO); + } + @catch(ICEFacetNotExistException*) + { + // expected + } + + [identity setCategory:@"bar"]; + for(NSString* name in stringArray) + { + [identity setName:name]; + id<TestDefaultServantMyObjectPrx> prx = [TestDefaultServantMyObjectPrx uncheckedCast:[oa createProxy:identity]]; + + @try + { + [prx ice_ping]; + test(NO); + } + @catch(ICEObjectNotExistException*) + { + } + + @try + { + [prx getName]; + test(NO); + } + @catch(ICEObjectNotExistException*) + { + } + } + tprintf("ok\n"); + tprintf("testing default category... "); + + [oa addDefaultServant:servant category:@""]; + + r = [oa findDefaultServant:@"bar"]; + test(r == nil); + + r = [oa findDefaultServant:@""]; + test(r == servant); + + for(NSString* name in stringArray) + { + [identity setName:name]; + id<TestDefaultServantMyObjectPrx> prx = [TestDefaultServantMyObjectPrx uncheckedCast:[oa createProxy:identity]]; + [prx ice_ping]; + test([[prx getName] isEqualToString:name]); + } + tprintf("ok\n"); + return 0; +} + +#if TARGET_OS_IPHONE +# define main defaultServantClient + +int +defaultServantServer(int argc, char* argv[]) +{ + serverReady(nil); + return 0; +} +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestDefaultServant", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} + diff --git a/objc/test/Ice/defaultServant/DefaultServantTest.ice b/objc/test/Ice/defaultServant/DefaultServantTest.ice new file mode 100644 index 00000000000..cba349190f8 --- /dev/null +++ b/objc/test/Ice/defaultServant/DefaultServantTest.ice @@ -0,0 +1,21 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestDefaultServant"] +module Test +{ + +interface MyObject +{ + string getName(); +}; + +}; diff --git a/objc/test/Ice/defaultServant/Makefile b/objc/test/Ice/defaultServant/Makefile new file mode 100644 index 00000000000..c050bf6f0f0 --- /dev/null +++ b/objc/test/Ice/defaultServant/Makefile @@ -0,0 +1,29 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client + +TARGETS = $(CLIENT) + +SLICE_OBJS = DefaultServantTest.o + +COBJS = Client.o \ + MyObjectI.o + +OBJS = $(COBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/defaultServant/MyObjectI.h b/objc/test/Ice/defaultServant/MyObjectI.h new file mode 100644 index 00000000000..22c7d09e5db --- /dev/null +++ b/objc/test/Ice/defaultServant/MyObjectI.h @@ -0,0 +1,13 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <DefaultServantTest.h> + +@interface TestDefaultServantMyObjectI : TestDefaultServantMyObject<TestDefaultServantMyObject> +@end diff --git a/objc/test/Ice/defaultServant/MyObjectI.m b/objc/test/Ice/defaultServant/MyObjectI.m new file mode 100644 index 00000000000..fc726d2452f --- /dev/null +++ b/objc/test/Ice/defaultServant/MyObjectI.m @@ -0,0 +1,46 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <defaultServant/MyObjectI.h> + +@implementation TestDefaultServantMyObjectI + +-(void) ice_ping:(ICECurrent*)current +{ + NSString* name = current.id_.name; + + if([name isEqualToString:@"ObjectNotExist"]) + { + @throw [ICEObjectNotExistException objectNotExistException:__FILE__ line:__LINE__]; + } + + if([name isEqualToString:@"FacetNotExist"]) + { + @throw [ICEFacetNotExistException facetNotExistException:__FILE__ line:__LINE__]; + } +} + +-(NSString*) getName:(ICECurrent*)current +{ + NSString* name = current.id_.name; + + if([name isEqualToString:@"ObjectNotExist"]) + { + @throw [ICEObjectNotExistException objectNotExistException:__FILE__ line:__LINE__]; + } + + if([name isEqualToString:@"FacetNotExist"]) + { + @throw [ICEFacetNotExistException facetNotExistException:__FILE__ line:__LINE__]; + } + + return name; +} +@end diff --git a/objc/test/Ice/defaultServant/run.py b/objc/test/Ice/defaultServant/run.py new file mode 100755 index 00000000000..eed9bface4f --- /dev/null +++ b/objc/test/Ice/defaultServant/run.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +client = os.path.join(os.getcwd(), "client") + +TestUtil.simpleTest(client) diff --git a/objc/test/Ice/defaultValue/.gitignore b/objc/test/Ice/defaultValue/.gitignore new file mode 100644 index 00000000000..e4c2ca683a3 --- /dev/null +++ b/objc/test/Ice/defaultValue/.gitignore @@ -0,0 +1,7 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +.depend +DefaultValueTest.m +DefaultValueTest.h diff --git a/objc/test/Ice/defaultValue/AllTests.m b/objc/test/Ice/defaultValue/AllTests.m new file mode 100644 index 00000000000..8f389d93624 --- /dev/null +++ b/objc/test/Ice/defaultValue/AllTests.m @@ -0,0 +1,110 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <DefaultValueTest.h> + +#import <Foundation/Foundation.h> + +void +defaultValueAllTests() +{ + tprintf("testing default values... "); + + { + TestDefaultValueStruct1* v = [TestDefaultValueStruct1 struct1]; + test(!v.boolFalse); + test(v.boolTrue); + test(v.b == 254); + test(v.s == 16000); + test(v.i == 3); + test(v.l == 4); + test(v.f == 5.0); + test(v.d == 6.0); + test([v.str isEqualToString:@"foo bar"]); + test(v.c == TestDefaultValuered); + test([v.noDefault length] == 0); + } + + { + TestDefaultValueStruct2* v = [TestDefaultValueStruct2 struct2]; + test(!v.boolFalse); + test(v.boolTrue); + test(v.b == 1); + test(v.s == 2); + test(v.i == 3); + test(v.l == 4); + test(v.f == 5.0); + test(v.d == 6.0); + test([v.str isEqualToString:@"foo bar"]); + test(v.c == TestDefaultValueblue); + test([v.noDefault length] == 0); + } + + { + TestDefaultValueBase* v = [TestDefaultValueBase base]; + test(!v.boolFalse); + test(v.boolTrue); + test(v.b == 1); + test(v.s == 2); + test(v.i == 3); + test(v.l == 4); + test(v.f == 5.0); + test(v.d == 6.0); + test([v.str isEqualToString:@"foo bar"]); + test([v.noDefault length] == 0); + } + + { + TestDefaultValueDerived* v = [TestDefaultValueDerived derived]; + test(!v.boolFalse); + test(v.boolTrue); + test(v.b == 1); + test(v.s == 2); + test(v.i == 3); + test(v.l == 4); + test(v.f == 5.0); + test(v.d == 6.0); + test([v.str isEqualToString:@"foo bar"]); + test([v.noDefault length] == 0); + test(v.c == TestDefaultValuegreen); + } + + { + TestDefaultValueBaseEx* v = [TestDefaultValueBaseEx baseEx]; + test(!v.boolFalse); + test(v.boolTrue); + test(v.b == 1); + test(v.s == 2); + test(v.i == 3); + test(v.l == 4); + test(v.f == 5.0); + test(v.d == 6.0); + test([v.str isEqualToString:@"foo bar"]); + test([v.noDefault length] == 0); + } + + { + TestDefaultValueDerivedEx* v = [TestDefaultValueDerivedEx derivedEx]; + test(!v.boolFalse); + test(v.boolTrue); + test(v.b == 1); + test(v.s == 2); + test(v.i == 3); + test(v.l == 4); + test(v.f == 5.0); + test(v.d == 6.0); + test([v.str isEqualToString:@"foo bar"]); + test([v.noDefault length] == 0); + test(v.c == TestDefaultValuegreen); + } + + tprintf("ok\n"); +} diff --git a/objc/test/Ice/defaultValue/Client.m b/objc/test/Ice/defaultValue/Client.m new file mode 100644 index 00000000000..94fa41cf8c9 --- /dev/null +++ b/objc/test/Ice/defaultValue/Client.m @@ -0,0 +1,53 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <DefaultValueTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run() +{ + void defaultValueAllTests(); + defaultValueAllTests(); + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main defaultValueClient +#endif + +int +main(int argc, char* argv[]) +{ + @autoreleasepool + { + int status; + @try + { + status = run(); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; + } +} diff --git a/objc/test/Ice/defaultValue/DefaultValueTest.ice b/objc/test/Ice/defaultValue/DefaultValueTest.ice new file mode 100644 index 00000000000..93e2eee3fd8 --- /dev/null +++ b/objc/test/Ice/defaultValue/DefaultValueTest.ice @@ -0,0 +1,87 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestDefaultValue"] +module Test +{ + +enum Color { red, green, blue }; + +struct Struct1 +{ + bool boolFalse = false; + bool boolTrue = true; + byte b = 254; + short s = 16000; + int i = 3; + long l = 4; + float f = 5.0; + double d = 6.0; + string str = "foo bar"; + Color c = red; + string noDefault; +}; + +["cpp:class"] +struct Struct2 +{ + bool boolFalse = false; + bool boolTrue = true; + byte b = 1; + short s = 2; + int i = 3; + long l = 4; + float f = 5.0; + double d = 6.0; + string str = "foo bar"; + Color c = blue; + string noDefault; +}; + +class Base +{ + bool boolFalse = false; + bool boolTrue = true; + byte b = 1; + short s = 2; + int i = 3; + long l = 4; + float f = 5.0; + double d = 6.0; + string str = "foo bar"; + string noDefault; +}; + +class Derived extends Base +{ + Color c = green; +}; + +exception BaseEx +{ + bool boolFalse = false; + bool boolTrue = true; + byte b = 1; + short s = 2; + int i = 3; + long l = 4; + float f = 5.0; + double d = 6.0; + string str = "foo bar"; + string noDefault; +}; + +exception DerivedEx extends BaseEx +{ + Color c = green; +}; + +}; diff --git a/objc/test/Ice/defaultValue/Makefile b/objc/test/Ice/defaultValue/Makefile new file mode 100644 index 00000000000..a116331df5a --- /dev/null +++ b/objc/test/Ice/defaultValue/Makefile @@ -0,0 +1,29 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client + +TARGETS = $(CLIENT) + +SLICE_OBJS = DefaultValueTest.o + +COBJS = Client.o \ + AllTests.o + +OBJS = $(COBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/defaultValue/run.py b/objc/test/Ice/defaultValue/run.py new file mode 100755 index 00000000000..ac32c445572 --- /dev/null +++ b/objc/test/Ice/defaultValue/run.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +client = os.path.join(os.getcwd(), "client") +TestUtil.simpleTest(client) + diff --git a/objc/test/Ice/dispatcher/.gitignore b/objc/test/Ice/dispatcher/.gitignore new file mode 100644 index 00000000000..b814b2f0fbb --- /dev/null +++ b/objc/test/Ice/dispatcher/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +DispatcherTest.m +DispatcherTest.h diff --git a/objc/test/Ice/dispatcher/AllTests.m b/objc/test/Ice/dispatcher/AllTests.m new file mode 100644 index 00000000000..cb93d5b2ea0 --- /dev/null +++ b/objc/test/Ice/dispatcher/AllTests.m @@ -0,0 +1,156 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <DispatcherTest.h> + +#import <Foundation/Foundation.h> + +NSThread* dispatcherThread = nil; + +static BOOL isDispatcherThread() +{ + if(dispatcherThread == nil) + { + dispatcherThread = [NSThread currentThread]; + test(dispatcherThread); + } + return dispatcherThread == [NSThread currentThread]; +} + +@interface TestDispatcherCallback : NSObject +{ + BOOL called; + NSCondition* cond; +} +-(void) check; +-(void) called; +@end + +@implementation TestDispatcherCallback +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + cond = [[NSCondition alloc] init]; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [super dealloc]; +} +#endif + +-(void) check +{ + [cond lock]; + while(!called) + { + [cond wait]; + } + called = NO; + [cond unlock]; +} +-(void) called +{ + [cond lock]; + called = YES; + [cond signal]; + [cond unlock]; +} +-(void) response +{ + test(isDispatcherThread()); + [self called]; +} + +-(void) exception:(ICEException*)ex +{ + test([ex isKindOfClass:[ICENoEndpointException class]]); + test(isDispatcherThread()); + [self called]; +} + +-(void) payload +{ + test(isDispatcherThread()); +} + +-(void) ignoreEx:(ICEException*)ex +{ + test([ex isKindOfClass:[ICECommunicatorDestroyedException class]]); +} + +-(void) sent:(BOOL)sentSynchronously +{ + test(sentSynchronously || isDispatcherThread()); +} + +@end + +id<TestDispatcherTestIntfPrx> +dispatcherAllTests(id<ICECommunicator> communicator) +{ + NSString* sref = @"test:default -p 12010"; + id<ICEObjectPrx> obj = [communicator stringToProxy:sref]; + test(obj); + + id<TestDispatcherTestIntfPrx> p = [TestDispatcherTestIntfPrx uncheckedCast:obj]; + + sref = @"testController:tcp -p 12011"; + obj = [communicator stringToProxy:sref]; + test(obj); + + id<TestDispatcherTestIntfControllerPrx> testController = [TestDispatcherTestIntfControllerPrx uncheckedCast:obj]; + + tprintf("testing dispatcher... "); + { + [p op]; + + TestDispatcherCallback* cb = [[TestDispatcherCallback alloc] init]; + [p begin_op:^ { [cb response]; } exception:^(ICEException* ex) { [cb exception:ex]; }]; + [cb check]; + + TestDispatcherTestIntfPrx* i = [p ice_adapterId:@"dummy"]; + [i begin_op:^ { [cb response]; } exception:^(ICEException* ex) { [cb exception:ex]; }]; + [cb check]; + + [testController holdAdapter]; + + ICEByte d[1024]; + ICEMutableByteSeq* seq = [ICEMutableByteSeq dataWithBytes:d length:sizeof(d)]; + + id<ICEAsyncResult> result; + @autoreleasepool + { + id response = ^{ [cb payload]; }; + id exception = ^(ICEException* ex) { [cb ignoreEx:ex]; }; + id sent = ^(BOOL ss) { [cb sent:ss]; }; + + while([(result = [p begin_opWithPayload:seq response:response + exception:exception + sent:sent]) sentSynchronously]); + [testController resumeAdapter]; + [result waitForCompleted]; + } +#if defined(__clang__) && !__has_feature(objc_arc) + [cb release]; +#endif + } + tprintf("ok\n"); + + return p; +} diff --git a/objc/test/Ice/dispatcher/Client.m b/objc/test/Ice/dispatcher/Client.m new file mode 100644 index 00000000000..5f1776bc34e --- /dev/null +++ b/objc/test/Ice/dispatcher/Client.m @@ -0,0 +1,81 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <DispatcherTest.h> +#include <dispatch/dispatch.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + TestDispatcherTestIntfPrx* dispatcherAllTests(id<ICECommunicator>); + TestDispatcherTestIntfPrx* dispatcher = dispatcherAllTests(communicator); + [dispatcher shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main dispatcherClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); + initData.dispatcher = ^(id<ICEDispatcherCall> call, id<ICEConnection> con) { + dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ { [call run]; }); + }; +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestDispatcher", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/dispatcher/DispatcherTest.ice b/objc/test/Ice/dispatcher/DispatcherTest.ice new file mode 100644 index 00000000000..7631a9a3061 --- /dev/null +++ b/objc/test/Ice/dispatcher/DispatcherTest.ice @@ -0,0 +1,31 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Ice/BuiltinSequences.ice> + +["objc:prefix:TestDispatcher"] +module Test +{ + +interface TestIntf +{ + void op(); + void opWithPayload(Ice::ByteSeq seq); + void shutdown(); +}; + +interface TestIntfController +{ + void holdAdapter(); + void resumeAdapter(); +}; + +}; diff --git a/objc/test/Ice/dispatcher/Makefile b/objc/test/Ice/dispatcher/Makefile new file mode 100644 index 00000000000..2697492c928 --- /dev/null +++ b/objc/test/Ice/dispatcher/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = DispatcherTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/dispatcher/Server.m b/objc/test/Ice/dispatcher/Server.m new file mode 100644 index 00000000000..24e7d58be9d --- /dev/null +++ b/objc/test/Ice/dispatcher/Server.m @@ -0,0 +1,96 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <dispatcher/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010:udp"]; + [[communicator getProperties] setProperty:@"ControllerAdapter.Endpoints" value:@"tcp -p 12011"]; + [[communicator getProperties] setProperty:@"ControllerAdapter.ThreadPool.Size" value:@"1"]; + + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; + id<ICEObjectAdapter> adapter2 = [communicator createObjectAdapter:@"ControllerAdapter"]; + +#if defined(__clang__) && !__has_feature(objc_arc) + TestDispatcherTestIntfControllerI* testController + = [[[TestDispatcherTestIntfControllerI alloc] initWithAdapter:adapter] autorelease]; + + ICEObject* object = [[[TestDispatcherTestIntfI alloc] init] autorelease]; +#else + TestDispatcherTestIntfControllerI* testController + = [[TestDispatcherTestIntfControllerI alloc] initWithAdapter:adapter]; + + ICEObject* object = [[TestDispatcherTestIntfI alloc] init]; +#endif + [adapter add:object identity:[communicator stringToIdentity:@"test"]]; + [adapter activate]; + + [adapter2 add:testController identity:[communicator stringToIdentity:@"testController"]]; + [adapter2 activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main dispatcherServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestDispatcher", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/dispatcher/TestI.h b/objc/test/Ice/dispatcher/TestI.h new file mode 100644 index 00000000000..c417c27415e --- /dev/null +++ b/objc/test/Ice/dispatcher/TestI.h @@ -0,0 +1,25 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <DispatcherTest.h> + +@interface TestDispatcherTestIntfI : TestDispatcherTestIntf +-(void) op:(ICECurrent *)current; +-(void) opWithPayload:(ICEMutableByteSeq*)seq current:(ICECurrent *)current; +-(void) shutdown:(ICECurrent *)current; +@end + +@interface TestDispatcherTestIntfControllerI : TestDispatcherTestIntfController +{ + id<ICEObjectAdapter> _adapter; +} +-(id) initWithAdapter:(id<ICEObjectAdapter>)adapter; +-(void) holdAdapter:(ICECurrent*)current; +-(void) resumeAdapter:(ICECurrent*)current; +@end diff --git a/objc/test/Ice/dispatcher/TestI.m b/objc/test/Ice/dispatcher/TestI.m new file mode 100644 index 00000000000..6b5e3a0503a --- /dev/null +++ b/objc/test/Ice/dispatcher/TestI.m @@ -0,0 +1,45 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <dispatcher/TestI.h> + +@implementation TestDispatcherTestIntfI +-(void) op:(ICECurrent*)current +{ +} +-(void) opWithPayload:(ICEMutableByteSeq*)data current:(ICECurrent*)current +{ +} +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} +@end + +@implementation TestDispatcherTestIntfControllerI +-(id) initWithAdapter:(id<ICEObjectAdapter>)adapter +{ + self = [super init]; + if(!self) + { + return nil; + } + _adapter = adapter; + return self; +} +-(void) holdAdapter:(ICECurrent*)current +{ + [_adapter hold]; +} +-(void) resumeAdapter:(ICECurrent*)current +{ + [_adapter activate]; +} +@end diff --git a/objc/test/Ice/dispatcher/run.py b/objc/test/Ice/dispatcher/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/dispatcher/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/enums/.gitignore b/objc/test/Ice/enums/.gitignore new file mode 100644 index 00000000000..657ea9d677b --- /dev/null +++ b/objc/test/Ice/enums/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +EnumTest.m +EnumTest.h diff --git a/objc/test/Ice/enums/AllTests.m b/objc/test/Ice/enums/AllTests.m new file mode 100644 index 00000000000..5b89a67f79c --- /dev/null +++ b/objc/test/Ice/enums/AllTests.m @@ -0,0 +1,388 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <EnumTest.h> + + +TestEnumTestIntfPrx* +enumAllTests(id<ICECommunicator> communicator) +{ + + ICEObjectPrx* obj = [communicator stringToProxy:@"test:default -p 12010"]; + test(obj); + TestEnumTestIntfPrx* proxy = [TestEnumTestIntfPrx checkedCast:obj]; + test(proxy); + + tprintf("testing enum values... "); + + test((int)(TestEnumbenum1) == 0); + test((int)(TestEnumbenum2) == 1); + test((int)(TestEnumbenum3) == TestEnumByteConst1); + test((int)(TestEnumbenum4) == TestEnumByteConst1 + 1); + test((int)(TestEnumbenum5) == TestEnumShortConst1); + test((int)(TestEnumbenum6) == TestEnumShortConst1 + 1); + test((int)(TestEnumbenum7) == TestEnumIntConst1); + test((int)(TestEnumbenum8) == TestEnumIntConst1 + 1); + test((int)(TestEnumbenum9) == TestEnumLongConst1); + test((int)(TestEnumbenum10) == TestEnumLongConst1 + 1); + test((int)(TestEnumbenum11) == TestEnumByteConst2); + + test((int)(TestEnumsenum1) == 3); + test((int)(TestEnumsenum2) == 4); + test((int)(TestEnumsenum3) == TestEnumByteConst1); + test((int)(TestEnumsenum4) == TestEnumByteConst1 + 1); + test((int)(TestEnumsenum5) == TestEnumShortConst1); + test((int)(TestEnumsenum6) == TestEnumShortConst1 + 1); + test((int)(TestEnumsenum7) == TestEnumIntConst1); + test((int)(TestEnumsenum8) == TestEnumIntConst1 + 1); + test((int)(TestEnumsenum9) == TestEnumLongConst1); + test((int)(TestEnumsenum10) == TestEnumLongConst1 + 1); + test((int)(TestEnumsenum11) == TestEnumShortConst2); + + test((int)(TestEnumienum1) == 0); + test((int)(TestEnumienum2) == 1); + test((int)(TestEnumienum3) == TestEnumByteConst1); + test((int)(TestEnumienum4) == TestEnumByteConst1 + 1); + test((int)(TestEnumienum5) == TestEnumShortConst1); + test((int)(TestEnumienum6) == TestEnumShortConst1 + 1); + test((int)(TestEnumienum7) == TestEnumIntConst1); + test((int)(TestEnumienum8) == TestEnumIntConst1 + 1); + test((int)(TestEnumienum9) == TestEnumLongConst1); + test((int)(TestEnumienum10) == TestEnumLongConst1 + 1); + test((int)(TestEnumienum11) == TestEnumIntConst2); + test((int)(TestEnumienum12) == TestEnumLongConst2); + + test((int)(TestEnumred) == 0); + test((int)(TestEnumgreen) == 1); + test((int)(TestEnumblue) == 2); + + tprintf("ok\n"); + + tprintf("testing enum operations... "); + + TestEnumByteEnum byteEnum; + test([proxy opByte:TestEnumbenum1 b2:&byteEnum] == TestEnumbenum1); + test(byteEnum == TestEnumbenum1); + test([proxy opByte:TestEnumbenum11 b2:&byteEnum] == TestEnumbenum11); + test(byteEnum == TestEnumbenum11); + + TestEnumShortEnum shortEnum; + test([proxy opShort:TestEnumsenum1 s2:&shortEnum] == TestEnumsenum1); + test(shortEnum == TestEnumsenum1); + test([proxy opShort:TestEnumsenum11 s2:&shortEnum] == TestEnumsenum11); + test(shortEnum == TestEnumsenum11); + + TestEnumIntEnum intEnum; + test([proxy opInt:TestEnumienum1 i2:&intEnum] == TestEnumienum1); + test(intEnum == TestEnumienum1); + test([proxy opInt:TestEnumienum11 i2:&intEnum] == TestEnumienum11); + test(intEnum == TestEnumienum11); + test([proxy opInt:TestEnumienum12 i2:&intEnum] == TestEnumienum12); + test(intEnum == TestEnumienum12); + + TestEnumSimpleEnum s; + test([proxy opSimple:TestEnumgreen s2:&s] == TestEnumgreen); + test(s == TestEnumgreen); + tprintf("ok\n"); + + tprintf("testing enum sequences operations... "); + + { + TestEnumByteEnum values[] = {TestEnumbenum1, TestEnumbenum2, TestEnumbenum3, TestEnumbenum4, TestEnumbenum5, + TestEnumbenum6, TestEnumbenum7, TestEnumbenum8, TestEnumbenum9, TestEnumbenum10, + TestEnumbenum11}; + + int enumSize = sizeof(TestEnumByteEnum); + int length = sizeof(values); + int elements = length/enumSize; + + TestEnumMutableByteEnumSeq* enumSeq1 = [NSMutableData dataWithBytes:values length:length]; + TestEnumMutableByteEnumSeq* enumSeq2 = [NSMutableData dataWithLength:length]; + TestEnumByteEnumSeq* enumSeq3 = [proxy opByteSeq:enumSeq1 b2:&enumSeq2]; + + ICEByte* p1 = (ICEByte *)[enumSeq1 bytes]; + ICEByte* p2 = (ICEByte *)[enumSeq2 bytes]; + ICEByte* p3 = (ICEByte *)[enumSeq3 bytes]; + + for(int i = 0; i < elements; ++i) + { + test(*p1 == *p2); + test(*p1 == *p3); + p1++; + p2++; + p3++; + } + } + + { + + TestEnumShortEnum values[] = {TestEnumsenum1, TestEnumsenum2, TestEnumsenum3, TestEnumsenum4, TestEnumsenum5, + TestEnumsenum6, TestEnumsenum7, TestEnumsenum8, TestEnumsenum9, TestEnumsenum10, + TestEnumsenum11}; + + int enumSize = sizeof(TestEnumShortEnum); + int length = sizeof(values); + int elements = length/enumSize; + + TestEnumMutableShortEnumSeq* enumSeq1 = [NSMutableData dataWithBytes:values length:length]; + TestEnumMutableShortEnumSeq* enumSeq2 = [NSMutableData dataWithLength:length]; + TestEnumShortEnumSeq* enumSeq3 = [proxy opShortSeq:enumSeq1 s2:&enumSeq2]; + + ICEByte* p1 = (ICEByte *)[enumSeq1 bytes]; + ICEByte* p2 = (ICEByte *)[enumSeq2 bytes]; + ICEByte* p3 = (ICEByte *)[enumSeq3 bytes]; + + for(int i = 0; i < elements; ++i) + { + test(*p1 == *p2); + test(*p1 == *p3); + p1++; + p2++; + p3++; + } + } + + { + + TestEnumIntEnum values[] = {TestEnumienum1, TestEnumienum2, TestEnumienum3, TestEnumienum4, TestEnumienum5, + TestEnumienum6, TestEnumienum7, TestEnumienum8, TestEnumienum9, TestEnumienum10, + TestEnumienum11}; + + int enumSize = sizeof(TestEnumShortEnum); + int length = sizeof(values); + int elements = length/enumSize; + + TestEnumMutableShortEnumSeq* enumSeq1 = [NSMutableData dataWithBytes:values length:length]; + TestEnumMutableShortEnumSeq* enumSeq2 = [NSMutableData dataWithLength:length]; + TestEnumShortEnumSeq* enumSeq3 = [proxy opIntSeq:enumSeq1 i2:&enumSeq2]; + + ICEByte* p1 = (ICEByte *)[enumSeq1 bytes]; + ICEByte* p2 = (ICEByte *)[enumSeq2 bytes]; + ICEByte* p3 = (ICEByte *)[enumSeq3 bytes]; + + for(int i = 0; i < elements; ++i) + { + test(*p1 == *p2); + test(*p1 == *p3); + p1++; + p2++; + p3++; + } + } + + { + + TestEnumSimpleEnum values[] = {TestEnumred, TestEnumgreen, TestEnumblue}; + + int enumSize = sizeof(TestEnumShortEnum); + int length = sizeof(values); + int elements = length/enumSize; + + TestEnumMutableShortEnumSeq* enumSeq1 = [NSMutableData dataWithBytes:values length:length]; + TestEnumMutableShortEnumSeq* enumSeq2 = [NSMutableData dataWithLength:length]; + TestEnumShortEnumSeq* enumSeq3 = [proxy opSimpleSeq:enumSeq1 s2:&enumSeq2]; + + ICEByte* p1 = (ICEByte *)[enumSeq1 bytes]; + ICEByte* p2 = (ICEByte *)[enumSeq2 bytes]; + ICEByte* p3 = (ICEByte *)[enumSeq3 bytes]; + + for(int i = 0; i < elements; ++i) + { + test(*p1 == *p2); + test(*p1 == *p3); + p1++; + p2++; + p3++; + } + } + + tprintf("ok\n"); + + tprintf("testing enum exceptions... "); + + @try + { + [proxy opByte:(TestEnumByteEnum)-1 b2:&byteEnum]; // Negative enumerators are not supported + test(NO); + } + @catch(ICEMarshalException*) + { + } + + @try + { + [proxy opByte:(TestEnumByteEnum)127 b2:&byteEnum]; // Invalid enumerator + test(NO); + } + @catch(ICEMarshalException*) + { + } + + @try + { + [proxy opShort:(TestEnumShortEnum)-1 s2:&shortEnum]; // Negative enumerators are not supported + test(NO); + } + @catch(const ICEMarshalException*) + { + } + + @try + { + [proxy opShort:(TestEnumShortEnum)0 s2:&shortEnum]; // Invalid enumerator + test(NO); + } + @catch(ICEMarshalException*) + { + } + + @try + { + [proxy opShort:(TestEnumShortEnum)32767 s2:&shortEnum]; // Invalid enumerator + test(NO); + } + @catch(ICEMarshalException*) + { + } + + @try + { + [proxy opInt:(TestEnumIntEnum)-1 i2:&intEnum]; // Negative enumerators are not supported + test(NO); + } + @catch(ICEMarshalException*) + { + } + + { + TestEnumByteEnum values[] = {TestEnumbenum1, TestEnumbenum2, TestEnumbenum3, TestEnumbenum4, TestEnumbenum5, + TestEnumbenum6, (TestEnumByteEnum)-1, TestEnumbenum8, TestEnumbenum9, TestEnumbenum10, + TestEnumbenum11}; // Negative enumerators are not supported + + int length = sizeof(values); + + TestEnumMutableByteEnumSeq* enumSeq1 = [NSMutableData dataWithBytes:values length:length]; + TestEnumMutableByteEnumSeq* enumSeq2 = [NSMutableData dataWithLength:length]; + @try + { + [proxy opByteSeq:enumSeq1 b2:&enumSeq2]; + test(NO); + } + @catch(ICEMarshalException*) + { + } + } + + { + TestEnumByteEnum values[] = {TestEnumbenum1, TestEnumbenum2, TestEnumbenum3, TestEnumbenum4, TestEnumbenum5, + TestEnumbenum6, (TestEnumByteEnum)127, TestEnumbenum8, TestEnumbenum9, TestEnumbenum10, + TestEnumbenum11}; // Invalid enumerator + + int length = sizeof(values); + + TestEnumMutableByteEnumSeq* enumSeq1 = [NSMutableData dataWithBytes:values length:length]; + TestEnumMutableByteEnumSeq* enumSeq2 = [NSMutableData dataWithLength:length]; + @try + { + [proxy opByteSeq:enumSeq1 b2:&enumSeq2]; + test(NO); + } + @catch(ICEMarshalException*) + { + } + } + + { + + TestEnumShortEnum values[] = {TestEnumsenum1, TestEnumsenum2, TestEnumsenum3, TestEnumsenum4, TestEnumsenum5, + (TestEnumShortEnum)-1, TestEnumsenum7, TestEnumsenum8, TestEnumsenum9, TestEnumsenum10, + TestEnumsenum11}; // Negative enumerators are not supported + + int length = sizeof(values); + + TestEnumMutableShortEnumSeq* enumSeq1 = [NSMutableData dataWithBytes:values length:length]; + TestEnumMutableShortEnumSeq* enumSeq2 = [NSMutableData dataWithLength:length]; + @try + { + [proxy opShortSeq:enumSeq1 s2:&enumSeq2]; + test(NO); + } + @catch(ICEMarshalException*) + { + } + } + + { + + TestEnumShortEnum values[] = {TestEnumsenum1, TestEnumsenum2, TestEnumsenum3, TestEnumsenum4, TestEnumsenum5, + (TestEnumShortEnum)0, TestEnumsenum7, TestEnumsenum8, TestEnumsenum9, TestEnumsenum10, + TestEnumsenum11}; // Invalid enumerator + + int length = sizeof(values); + + TestEnumMutableShortEnumSeq* enumSeq1 = [NSMutableData dataWithBytes:values length:length]; + TestEnumMutableShortEnumSeq* enumSeq2 = [NSMutableData dataWithLength:length]; + @try + { + [proxy opShortSeq:enumSeq1 s2:&enumSeq2]; + test(NO); + } + @catch(ICEMarshalException*) + { + } + } + + { + + TestEnumShortEnum values[] = {TestEnumsenum1, TestEnumsenum2, TestEnumsenum3, TestEnumsenum4, TestEnumsenum5, + (TestEnumShortEnum)32767, TestEnumsenum7, TestEnumsenum8, TestEnumsenum9, TestEnumsenum10, + TestEnumsenum11}; // Invalid enumerator + + int length = sizeof(values); + + TestEnumMutableShortEnumSeq* enumSeq1 = [NSMutableData dataWithBytes:values length:length]; + TestEnumMutableShortEnumSeq* enumSeq2 = [NSMutableData dataWithLength:length]; + @try + { + [proxy opShortSeq:enumSeq1 s2:&enumSeq2]; + test(NO); + } + @catch(ICEMarshalException*) + { + } + } + + { + + TestEnumIntEnum values[] = {TestEnumienum1, TestEnumienum2, TestEnumienum3, TestEnumienum4, TestEnumienum5, + (TestEnumIntEnum)-1, TestEnumienum7, TestEnumienum8, TestEnumienum9, TestEnumienum10, + TestEnumienum11}; // Negative enumerators are not supported + + int length = sizeof(values); + + TestEnumMutableShortEnumSeq* enumSeq1 = [NSMutableData dataWithBytes:values length:length]; + TestEnumMutableShortEnumSeq* enumSeq2 = [NSMutableData dataWithLength:length]; + @try + { + [proxy opIntSeq:enumSeq1 i2:&enumSeq2]; + test(NO); + } + @catch(ICEMarshalException*) + { + } + } + + + + tprintf("ok\n"); + + return proxy; +} diff --git a/objc/test/Ice/enums/Client.m b/objc/test/Ice/enums/Client.m new file mode 100644 index 00000000000..3e9b09fa86d --- /dev/null +++ b/objc/test/Ice/enums/Client.m @@ -0,0 +1,79 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <EnumTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + TestEnumTestIntfPrx* enumAllTests(id<ICECommunicator>); + TestEnumTestIntfPrx* test = enumAllTests(communicator); + + [test shutdown]; + + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main enumClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestEnum", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/enums/EnumTest.ice b/objc/test/Ice/enums/EnumTest.ice new file mode 100644 index 00000000000..762bc7d89d4 --- /dev/null +++ b/objc/test/Ice/enums/EnumTest.ice @@ -0,0 +1,98 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestEnum"] +module Test +{ + +const byte ByteConst1 = 10; +const short ShortConst1 = 20; +const int IntConst1 = 30; +const long LongConst1 = 40; + +const byte ByteConst2 = 126; +const short ShortConst2 = 32766; +const int IntConst2 = 2147483647; +const long LongConst2 = 2147483646; + +enum ByteEnum +{ + benum1, + benum2, + benum3 = ByteConst1, + benum4, + benum5 = ShortConst1, + benum6, + benum7 = IntConst1, + benum8, + benum9 = LongConst1, + benum10, + benum11 = ByteConst2 +}; +sequence<ByteEnum> ByteEnumSeq; + +enum ShortEnum +{ + senum1 = 3, + senum2, + senum3 = ByteConst1, + senum4, + senum5 = ShortConst1, + senum6, + senum7 = IntConst1, + senum8, + senum9 = LongConst1, + senum10, + senum11 = ShortConst2 +}; +sequence<ShortEnum> ShortEnumSeq; + +enum IntEnum +{ + ienum1, + ienum2, + ienum3 = ByteConst1, + ienum4, + ienum5 = ShortConst1, + ienum6, + ienum7 = IntConst1, + ienum8, + ienum9 = LongConst1, + ienum10, + ienum11 = IntConst2, + ienum12 = LongConst2 +}; +sequence<IntEnum> IntEnumSeq; + +enum SimpleEnum +{ + red, + green, + blue +}; +sequence<SimpleEnum> SimpleEnumSeq; + +interface TestIntf +{ + ByteEnum opByte(ByteEnum b1, out ByteEnum b2); + ShortEnum opShort(ShortEnum s1, out ShortEnum s2); + IntEnum opInt(IntEnum i1, out IntEnum i2); + SimpleEnum opSimple(SimpleEnum s1, out SimpleEnum s2); + + ByteEnumSeq opByteSeq(ByteEnumSeq b1, out ByteEnumSeq b2); + ShortEnumSeq opShortSeq(ShortEnumSeq s1, out ShortEnumSeq s2); + IntEnumSeq opIntSeq(IntEnumSeq i1, out IntEnumSeq i2); + SimpleEnumSeq opSimpleSeq(SimpleEnumSeq s1, out SimpleEnumSeq s2); + + void shutdown(); +}; + +}; diff --git a/objc/test/Ice/enums/Makefile b/objc/test/Ice/enums/Makefile new file mode 100644 index 00000000000..93f4caae0cf --- /dev/null +++ b/objc/test/Ice/enums/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = EnumTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/enums/Server.m b/objc/test/Ice/enums/Server.m new file mode 100644 index 00000000000..877202be6a8 --- /dev/null +++ b/objc/test/Ice/enums/Server.m @@ -0,0 +1,83 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <enums/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010:udp"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + [adapter add:[[[TestEnumTestIntfI alloc] init] autorelease] + identity:[communicator stringToIdentity:@"test"]]; +#else + [adapter add:[[TestEnumTestIntfI alloc] init] identity:[communicator stringToIdentity:@"test"]]; +#endif + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main enumServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestEnum", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/enums/TestI.h b/objc/test/Ice/enums/TestI.h new file mode 100644 index 00000000000..4283e41babd --- /dev/null +++ b/objc/test/Ice/enums/TestI.h @@ -0,0 +1,15 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <EnumTest.h> + +@interface TestEnumTestIntfI : TestEnumTestIntf<TestEnumTestIntf> +{ +} +@end diff --git a/objc/test/Ice/enums/TestI.m b/objc/test/Ice/enums/TestI.m new file mode 100644 index 00000000000..6b4daf75e61 --- /dev/null +++ b/objc/test/Ice/enums/TestI.m @@ -0,0 +1,69 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <enums/TestI.h> +#import <TestCommon.h> + +@implementation TestEnumTestIntfI + +-(void) shutdown:(ICECurrent*)current +{ + [[[current adapter] getCommunicator] shutdown]; +} + +-(TestEnumByteEnum) opByte:(TestEnumByteEnum)b1 b2:(TestEnumByteEnum*)b2 current:(ICECurrent*)current +{ + *b2 = b1; + return b1; +} + +-(TestEnumShortEnum) opShort:(TestEnumShortEnum)s1 s2:(TestEnumShortEnum*)s2 current:(ICECurrent*)current +{ + *s2 = s1; + return s1; +} + +-(TestEnumIntEnum) opInt:(TestEnumIntEnum)i1 i2:(TestEnumIntEnum*)i2 current:(ICECurrent*)current +{ + *i2 = i1; + return i1; +} + +-(TestEnumSimpleEnum) opSimple:(TestEnumSimpleEnum)s1 s2:(TestEnumSimpleEnum*)s2 current:(ICECurrent*)current +{ + *s2 = s1; + return s1; +} + +-(TestEnumByteEnumSeq*) opByteSeq:(TestEnumByteEnumSeq*)b1 b2:(TestEnumByteEnumSeq**)b2 current:(ICECurrent*)current +{ + *b2 = b1; + return b1; +} + +-(TestEnumShortEnumSeq*) opShortSeq:(TestEnumShortEnumSeq*)s1 s2:(TestEnumShortEnumSeq**)s2 current:(ICECurrent*)current +{ + *s2 = s1; + return s1; +} + +-(TestEnumIntEnumSeq*) opIntSeq:(TestEnumIntEnumSeq*)i1 i2:(TestEnumIntEnumSeq**)i2 current:(ICECurrent*)current +{ + *i2 = i1; + return i1; +} + +-(TestEnumSimpleEnumSeq*) opSimpleSeq:(TestEnumSimpleEnumSeq*)s1 s2:(TestEnumSimpleEnumSeq**)s2 current:(ICECurrent*)current +{ + *s2 = s1; + return s1; +} + +@end diff --git a/objc/test/Ice/enums/run.py b/objc/test/Ice/enums/run.py new file mode 100755 index 00000000000..efa77639a65 --- /dev/null +++ b/objc/test/Ice/enums/run.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +print("Running test with 1.0 encoding.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", + additionalServerOptions="--Ice.Default.EncodingVersion=1.0") + +print("Running test with 1.1 encoding.") +TestUtil.clientServerTest() diff --git a/objc/test/Ice/exceptions/.gitignore b/objc/test/Ice/exceptions/.gitignore new file mode 100644 index 00000000000..540725b83c2 --- /dev/null +++ b/objc/test/Ice/exceptions/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +ExceptionsTest.m +ExceptionsTest.h diff --git a/objc/test/Ice/exceptions/AllTests.m b/objc/test/Ice/exceptions/AllTests.m new file mode 100644 index 00000000000..8a57ccd7f90 --- /dev/null +++ b/objc/test/Ice/exceptions/AllTests.m @@ -0,0 +1,501 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <ExceptionsTest.h> + +@interface ExceptionsEmptyI : TestExceptionsEmpty<TestExceptionsEmpty> +@end + +@implementation ExceptionsEmptyI +@end + +id<TestExceptionsThrowerPrx> +exceptionsAllTests(id<ICECommunicator> communicator, BOOL collocated) +{ + tprintf("testing object adapter registration exceptions... "); + { + id<ICEObjectAdapter> first; + @try + { + first = [communicator createObjectAdapter:@"TestAdapter0"]; + test(false); + } + @catch(ICEInitializationException *ex) + { + // Expeccted + } + + [[communicator getProperties] setProperty:@"TestAdapter0.Endpoints" value:@"default"]; + first = [communicator createObjectAdapter:@"TestAdapter0"]; + @try + { + [communicator createObjectAdapter:@"TestAdapter0"]; + test(false); + } + @catch(ICEAlreadyRegisteredException *ex) + { + // Expected + } + + @try + { + } + @catch(ICEAlreadyRegisteredException *ex) + { + // Expected + } + + // + // Properties must remain unaffected if an exception occurs. + // + test([[[communicator getProperties] getProperty:@"TestAdapter0.Endpoints"] isEqualToString:@"default"]); + [first deactivate]; + } + tprintf("ok\n"); + + tprintf("testing servant registration exceptions... "); + { + [[communicator getProperties] setProperty:@"TestAdapter1.Endpoints" value:@"default"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter1"]; +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* obj = [[[ExceptionsEmptyI alloc] init] autorelease]; +#else + ICEObject* obj = [[ExceptionsEmptyI alloc] init]; +#endif + [adapter add:obj identity:[communicator stringToIdentity:@"x"]]; + @try + { + [adapter add:obj identity:[communicator stringToIdentity:@"x"]]; + test(false); + } + @catch(ICEAlreadyRegisteredException *ex) + { + } + + [adapter remove:[communicator stringToIdentity:@"x"]]; + @try + { + [adapter remove:[communicator stringToIdentity:@"x"]]; + test(false); + } + @catch(ICENotRegisteredException *ex) + { + } + + [adapter deactivate]; + } + tprintf("ok\n"); + + tprintf("testing stringToProxy... "); + NSString *ref = @"thrower:default -p 12010"; + id<ICEObjectPrx> base = [communicator stringToProxy:ref]; + test(base); + tprintf("ok\n"); + + tprintf("testing checked cast... "); + id<TestExceptionsThrowerPrx> thrower = [TestExceptionsThrowerPrx checkedCast:base]; + test(thrower); + test([thrower isEqual:base]); + tprintf("ok\n"); + + tprintf("catching exact types... "); + + @try + { + [thrower throwAasA:1]; + test(false); + } + @catch(TestExceptionsA *ex) + { + test(ex.aMem == 1); + } + @catch(NSException *ex) + { + test(false); + } + + @try + { + [thrower throwAorDasAorD:1]; + test(false); + } + @catch(TestExceptionsA *ex) + { + test(ex.aMem == 1); + } + @catch(NSException *ex) + { + test(false); + } + + @try + { + [thrower throwAorDasAorD:-1]; + test(false); + } + @catch(TestExceptionsD *ex) + { + test(ex.dMem == -1); + } + @catch(NSException* ex) + { + test(false); + } + + @try + { + [thrower throwBasB:1 b:2]; + test(false); + } + @catch(TestExceptionsB *ex) + { + test(ex.aMem == 1); + test(ex.bMem == 2); + } + @catch(NSException *ex) + { + test(false); + } + + @try + { + [thrower throwCasC:1 b:2 c:3]; + test(false); + } + @catch(TestExceptionsC *ex) + { + test(ex.aMem == 1); + test(ex.bMem == 2); + test(ex.cMem == 3); + } + @catch(NSException *ex) + { + test(false); + } + + @try + { + [thrower throwModA:1 a2:2]; + test(false); + } + @catch(TestExceptionsModA *ex) + { + test(ex.aMem == 1); + test(ex.a2Mem == 2); + } + @catch(ICEOperationNotExistException *ex) + { + // + // This operation is not supported in Java. + // + } + @catch(NSException *ex) + { + test(false); + } + + tprintf("ok\n"); + + tprintf("catching base types... "); + + @try + { + [thrower throwBasB:1 b:2]; + test(false); + } + @catch(TestExceptionsA *ex) + { + test(ex.aMem == 1); + } + @catch(NSException *ex) + { + test(false); + } + + @try + { + [thrower throwCasC:1 b:2 c:3]; + test(false); + } + @catch(TestExceptionsB *ex) + { + test(ex.aMem == 1); + test(ex.bMem == 2); + } + @catch(NSException *ex) + { + test(false); + } + + @try + { + [thrower throwModA:1 a2:2]; + test(false); + } + @catch(TestExceptionsA *ex) + { + test(ex.aMem == 1); + } + @catch(ICEOperationNotExistException *ex) + { + // + // This operation is not supported in Java. + // + } + @catch(NSException *ex) + { + test(false); + } + + tprintf("ok\n"); + + tprintf("catching derived types... "); + + @try + { + [thrower throwBasA:1 b:2]; + test(false); + } + @catch(TestExceptionsB *ex) + { + test(ex.aMem == 1); + test(ex.bMem == 2); + } + @catch(NSException *ex) + { + test(false); + } + + @try + { + [thrower throwCasA:1 b:2 c:3]; + test(false); + } + @catch(TestExceptionsC *ex) + { + test(ex.aMem == 1); + test(ex.bMem == 2); + test(ex.cMem == 3); + } + @catch(NSException *ex) + { + test(false); + } + + @try + { + [thrower throwCasB:1 b:2 c:3]; + test(false); + } + @catch(TestExceptionsC *ex) + { + test(ex.aMem == 1); + test(ex.bMem == 2); + test(ex.cMem == 3); + } + @catch(NSException *ex) + { + test(false); + } + + tprintf("ok\n"); + + if([thrower supportsUndeclaredExceptions]) + { + tprintf("catching unknown user exception... "); + + @try + { + [thrower throwUndeclaredA:1]; + test(false); + } + @catch(ICEUnknownUserException *ex) + { + } + @catch(NSException *ex) + { + test(false); + } + + @try + { + [thrower throwUndeclaredB:1 b:2]; + test(false); + } + @catch(ICEUnknownUserException *ex) + { + } + @catch(NSException *ex) + { + test(false); + } + + @try + { + [thrower throwUndeclaredC:1 b:2 c:3]; + test(false); + } + @catch(ICEUnknownUserException *ex) + { + } + @catch(NSException *ex) + { + test(false); + } + + tprintf("ok\n"); + } + + { + tprintf("testing memory limit marshal exception..."); + @try + { + ICEByteSeq *bs = [NSMutableData dataWithLength:0]; + [thrower throwMemoryLimitException:bs]; + test(false); + } + @catch(ICEMemoryLimitException *ex) + { + } + @catch(NSException *ex) + { + test(false); + } + + @try + { + [thrower throwMemoryLimitException:[NSMutableData dataWithLength:20 * 1024]]; // 20KB + test(false); + } + @catch(ICEConnectionLostException *ex) + { + } + @catch(NSException *ex) + { + test(false); + } + tprintf("ok\n"); + } + + tprintf("catching object not exist exception... "); + + ICEIdentity *id_ = [communicator stringToIdentity:@"does not exist"]; + @try + { + id<TestExceptionsThrowerPrx> thrower2 = [TestExceptionsThrowerPrx uncheckedCast:[thrower ice_identity:id_]]; + [thrower2 throwAasA:1]; +// //[thrower2 ice_ping]; + test(false); + } + @catch(ICEObjectNotExistException *ex) + { + test([ex.id_ isEqual:id_]); + } + @catch(NSException *ex) + { + test(false); + } + + tprintf("ok\n"); + + tprintf("catching facet not exist exception... "); + + @try + { + id<TestExceptionsThrowerPrx> thrower2 = [TestExceptionsThrowerPrx uncheckedCast:thrower facet:@"no such facet"]; + @try + { + [thrower2 ice_ping]; + test(false); + } + @catch(ICEFacetNotExistException *ex) + { + test([ex.facet isEqualToString:@"no such facet"]); + } + } + @catch(NSException *ex) + { + test(false); + } + + tprintf("ok\n"); + + tprintf("catching operation not exist exception... "); + + @try + { + id<TestExceptionsWrongOperationPrx> thrower2 = [TestExceptionsWrongOperationPrx uncheckedCast:thrower]; + [thrower2 noSuchOperation]; + test(false); + } + @catch(ICEOperationNotExistException *ex) + { + test([ex.operation isEqualToString:@"noSuchOperation"]); + } + @catch(NSException *ex) + { + test(false); + } + + tprintf("ok\n"); + + tprintf("catching unknown local exception... "); + + @try + { + [thrower throwLocalException]; + test(false); + } + @catch(ICEUnknownLocalException *ex) + { + } + @catch(NSException *ex) + { + test(false); + } + @try + { + [thrower throwLocalExceptionIdempotent]; + test(false); + } + @catch(ICEUnknownLocalException*) + { + } + @catch(ICEOperationNotExistException*) + { + } + @catch(NSException* ex) + { + test(false); + } + + + tprintf("ok\n"); + + tprintf("catching unknown non-Ice exception... "); + + @try + { + [thrower throwNonIceException]; + test(false); + } + @catch(ICEUnknownException *) + { + } + @catch(NSException *) + { + test(false); + } + + tprintf("ok\n"); + + return thrower; +} diff --git a/objc/test/Ice/exceptions/Client.m b/objc/test/Ice/exceptions/Client.m new file mode 100644 index 00000000000..c988600b617 --- /dev/null +++ b/objc/test/Ice/exceptions/Client.m @@ -0,0 +1,79 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <ExceptionsTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + TestExceptionsThrowerPrx* exceptionsAllTests(id<ICECommunicator>, BOOL); + TestExceptionsThrowerPrx* thrower = exceptionsAllTests(communicator, NO); + [thrower shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main exceptionsClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); + [initData.properties setProperty:@"Ice.MessageSizeMax" value:@"10"]; // 10KB max + [initData.properties setProperty:@"Ice.Warn.Connections" value:@"0"]; +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestExceptions", @"::Test", + @"TestExceptionsMod", @"::Test::Mod", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/exceptions/ExceptionsTest.ice b/objc/test/Ice/exceptions/ExceptionsTest.ice new file mode 100644 index 00000000000..6d3c247076f --- /dev/null +++ b/objc/test/Ice/exceptions/ExceptionsTest.ice @@ -0,0 +1,88 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Ice/BuiltinSequences.ice> + +["objc:prefix:TestExceptions"] +module Test +{ + +interface Empty +{ +}; + +interface Thrower; + +exception A +{ + int aMem; +}; + +exception B extends A +{ + int bMem; +}; + +exception C extends B +{ + int cMem; +}; + +exception D +{ + int dMem; +}; + +["objc:prefix:TestExceptionsMod"] +module Mod +{ + exception A extends ::Test::A + { + int a2Mem; + }; +}; + + +interface Thrower +{ + void shutdown(); + bool supportsUndeclaredExceptions(); + bool supportsAssertException(); + + void throwAasA(int a) throws A; + void throwAorDasAorD(int a) throws A, D; + void throwBasA(int a, int b) throws A; + void throwCasA(int a, int b, int c) throws A; + void throwBasB(int a, int b) throws B; + void throwCasB(int a, int b, int c) throws B; + void throwCasC(int a, int b, int c) throws C; + + void throwModA(int a, int a2) throws Mod::A; + + void throwUndeclaredA(int a); + void throwUndeclaredB(int a, int b); + void throwUndeclaredC(int a, int b, int c); + void throwLocalException(); + void throwNonIceException(); + void throwAssertException(); + Ice::ByteSeq throwMemoryLimitException(Ice::ByteSeq seq); + idempotent void throwLocalExceptionIdempotent(); + + void throwAfterResponse(); + void throwAfterException() throws A; +}; + +interface WrongOperation +{ + void noSuchOperation(); +}; + +}; diff --git a/objc/test/Ice/exceptions/Makefile b/objc/test/Ice/exceptions/Makefile new file mode 100644 index 00000000000..ad1f1c56002 --- /dev/null +++ b/objc/test/Ice/exceptions/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = ExceptionsTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/exceptions/Server.m b/objc/test/Ice/exceptions/Server.m new file mode 100644 index 00000000000..9d5f81998b2 --- /dev/null +++ b/objc/test/Ice/exceptions/Server.m @@ -0,0 +1,90 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <exceptions/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"Ice.Warn.Dispatch" value:@"0"]; + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010:udp"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* object = [[[ThrowerI alloc] init] autorelease]; +#else + ICEObject* object = [[ThrowerI alloc] init]; +#endif + [adapter add:object identity:[communicator stringToIdentity:@"thrower"]]; + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main exceptionsServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); + [initData.properties setProperty:@"Ice.MessageSizeMax" value:@"10"]; // 10KB max + [initData.properties setProperty:@"Ice.Warn.Dispatch" value:@"0"]; + [initData.properties setProperty:@"Ice.Warn.Connections" value:@"0"]; + +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestExceptions", @"::Test", + @"TestExceptionsMod", @"::Test::Mod", + nil]; +#endif + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/exceptions/TestI.h b/objc/test/Ice/exceptions/TestI.h new file mode 100644 index 00000000000..8046ca912e6 --- /dev/null +++ b/objc/test/Ice/exceptions/TestI.h @@ -0,0 +1,16 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <ExceptionsTest.h> + +@interface ThrowerI : TestExceptionsThrower<TestExceptionsThrower> +{ +} + +@end diff --git a/objc/test/Ice/exceptions/TestI.m b/objc/test/Ice/exceptions/TestI.m new file mode 100644 index 00000000000..77620336a74 --- /dev/null +++ b/objc/test/Ice/exceptions/TestI.m @@ -0,0 +1,153 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> + +#import <exceptions/TestI.h> +#import <TestCommon.h> +#import <Foundation/NSException.h> + +@interface FooException : NSException +@end + +@implementation FooException +-(id)init +{ + self = [super initWithName:@"FooException" reason:@"no reason" userInfo:nil]; + if(!self) + { + return nil; + } + return self; +} +@end + +@implementation ThrowerI + +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} + +-(BOOL) supportsUndeclaredExceptions:(ICECurrent*)current +{ + return YES; +} + +-(BOOL) supportsAssertException:(ICECurrent*)current +{ + return NO; +} + +-(void) throwAasA:(ICEInt)a current:(ICECurrent*)current +{ + @throw [TestExceptionsA a:a]; +} + +-(void) throwAorDasAorD:(ICEInt)a current:(ICECurrent*)current +{ + if(a > 0) + { + @throw [TestExceptionsA a:a]; + } + else + { + @throw [TestExceptionsD d:a]; + } +} + +-(void) throwBasA:(ICEInt)a b:(ICEInt)b current:(ICECurrent*)current +{ + [self throwBasB:a b:b current:current]; +} + +-(void) throwCasA:(ICEInt)a b:(ICEInt)b c:(ICEInt) c current:(ICECurrent*)current +{ + [self throwCasC:a b:b c:c current:current]; +} + +-(void) throwBasB:(ICEInt)a b:(ICEInt)b current:(ICECurrent*)current +{ + @throw [TestExceptionsB b:a bMem:b]; +} + +-(void) throwCasB:(ICEInt)a b:(ICEInt)b c:(ICEInt)c current:(ICECurrent*)current +{ + [self throwCasC:a b:b c:c current:current]; +} + +-(void) throwCasC:(ICEInt)a b:(ICEInt)b c:(ICEInt)c current:(ICECurrent*)current +{ + @throw [TestExceptionsC c:a bMem:b cMem:c]; +} + +-(void) throwModA:(ICEInt)a a2:(ICEInt)a2 current:(ICECurrent*)current +{ + @throw [TestExceptionsModA a:a a2Mem:a2]; +} + +-(void) throwUndeclaredA:(ICEInt)a current:(ICECurrent*)current +{ + @throw [TestExceptionsA a:a]; +} + +-(void) throwUndeclaredB:(ICEInt)a b:(ICEInt)b current:(ICECurrent*)current +{ + @throw [TestExceptionsB b:a bMem:b]; +} + +-(void) throwUndeclaredC:(ICEInt)a b:(ICEInt)b c:(ICEInt)c current:(ICECurrent*)current +{ + @throw [TestExceptionsC c:a bMem:b cMem:c]; +} + +-(void) throwLocalException:(ICECurrent*)current +{ + @throw [ICETimeoutException timeoutException:__FILE__ line:__LINE__]; +} + +-(ICEByteSeq*) throwMemoryLimitException:(ICEMutableByteSeq*)bs current:(ICECurrent*)current +{ + int limit = 20 * 1024; + ICEMutableByteSeq *r = [NSMutableData dataWithLength:limit]; + ICEByte *p = (ICEByte *)[r bytes]; + while(--limit > 0) + { + *p++ = limit % 0x80; + } + return r; +} + +-(void) throwNonIceException:(ICECurrent*)current +{ +#if defined(__clang__) && !__has_feature(objc_arc) + @throw [[[FooException alloc] init] autorelease]; +#else + @throw [[FooException alloc] init]; +#endif +} + +-(void) throwAssertException:(ICECurrent*)current +{ + // Not supported. +} + +-(void) throwLocalExceptionIdempotent:(ICECurrent*)current +{ + @throw [ICETimeoutException timeoutException:__FILE__ line:__LINE__]; +} +-(void) throwAfterResponse:(ICECurrent*)current +{ + // Only relevant for AMD +} +-(void) throwAfterException:(ICECurrent*)current +{ + // Only relevant for AMD +} +@end diff --git a/objc/test/Ice/exceptions/run.py b/objc/test/Ice/exceptions/run.py new file mode 100755 index 00000000000..37acea1668c --- /dev/null +++ b/objc/test/Ice/exceptions/run.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +print("Running test with compact (default) format.") +TestUtil.clientServerTest() + +print("Running test with sliced format.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.SlicedFormat", + additionalServerOptions="--Ice.Default.SlicedFormat") + +print("Running test with 1.0 encoding.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", + additionalServerOptions="--Ice.Default.EncodingVersion=1.0") diff --git a/objc/test/Ice/facets/.gitignore b/objc/test/Ice/facets/.gitignore new file mode 100644 index 00000000000..9d788e0b4c2 --- /dev/null +++ b/objc/test/Ice/facets/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +FacetsTest.m +FacetsTest.h diff --git a/objc/test/Ice/facets/AllTests.m b/objc/test/Ice/facets/AllTests.m new file mode 100644 index 00000000000..00c496ee62e --- /dev/null +++ b/objc/test/Ice/facets/AllTests.m @@ -0,0 +1,196 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <FacetsTest.h> + + +@interface FacetsEmptyI : TestFacetsEmpty +@end + +@implementation FacetsEmptyI +@end + +id<TestFacetsGPrx> +facetsAllTests(id<ICECommunicator> communicator) +{ +// tprintf("testing Ice.Admin.Facets property... "); +// test([[[communicator getProperties] getPropertyAsList:@"Ice.Admin.Facets"] length] > 0); +// [[communicator getProperties] setProperty:@"Ice.Admin.Facets" value:@"foobar"]; +// ICEStringSeq facetFilter = [[communicator getProperties] getPropertyAsList:@"Ice.Admin.Facets"]; +// test([[facetFilter count] == 1 && [facetFilter objectAtIndex:0] isEqualToString:@"foobar"]); +// [[communicator getProperties] setProperty:@"Ice.Admin.Facets" value:@"foo'bar"]; +// facetFilter = [[communicator getProperties] getPropertyAsList:@"Ice.Admin.Facets"]; +// test([[facetFilter count] == 1 && [facetFilter objectAtIndex:0] isEqualToString:@"foo'bar"]); +// [[communicator getProperties] setProperty:@"Ice.Admin.Facets" value:@"'foo bar' toto 'titi'"]; +// facetFilter = [[communicator getProperties] getPropertyAsList:@"Ice.Admin.Facets"]; +// test([[facetFilter count] == 3 && [facetFilter objectAtIndex:0] isEqualToString:@"foo bar" && [facetFilter objectAtIndex:1]:isEqualToString:@"toto" && [facetFilter objectAtIndex:2]:isEqualToString:@"titi"]); +// [[communicator getProperties] setProperty:@"Ice.Admin.Facets" value:@"'foo bar\\' toto' 'titi'"]; +// facetFilter = [[communicator getProperties] getPropertyAsList:@"Ice.Admin.Facets"]; +// test([[facetFilter count] == 2 && [facetFilter objectAtIndex:0] isEqualToString:@"foo bar' toto" && [facetFilter objectAtIndex:1]:isEqualToString:@"titi"]); +// // [[communicator getProperties] setProperty:@"Ice.Admin.Facets" value:@"'foo bar' 'toto titi"]; +// // facetFilter = [[communicator getProperties] getPropertyAsList:@"Ice.Admin.Facets"]; +// // test([facetFilter count] == 0); +// [[communicator getProperties] setProperty:@"Ice.Admin.Facets" value:@""]; +// tprintf("ok\n"); + + tprintf("testing facet registration exceptions... "); + [[communicator getProperties] setProperty:@"FacetExceptionTestAdapter.Endpoints" value:@"default"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"FacetExceptionTestAdapter"]; + ICEObject* obj = [[FacetsEmptyI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [obj autorelease]; +#endif + [adapter add:obj identity:[communicator stringToIdentity:@"d"]]; + [adapter addFacet:obj identity:[communicator stringToIdentity:@"d"] facet:@"facetABCD"]; + @try + { + [adapter addFacet:obj identity:[communicator stringToIdentity:@"d"] facet:@"facetABCD"]; + test(NO); + } + @catch(ICEAlreadyRegisteredException*) + { + } + [adapter removeFacet:[communicator stringToIdentity:@"d"] facet:@"facetABCD"]; + @try + { + [adapter removeFacet:[communicator stringToIdentity:@"d"] facet:@"facetABCD"]; + test(NO); + } + @catch(ICENotRegisteredException*) + { + } + tprintf("ok\n"); + + tprintf("testing removeAllFacets... "); + ICEObject* obj1 = [[FacetsEmptyI alloc] init]; + ICEObject* obj2 = [[FacetsEmptyI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [obj1 autorelease]; + [obj2 autorelease]; +#endif + + [adapter addFacet:obj1 identity:[communicator stringToIdentity:@"id1"] facet:@"f1"]; + [adapter addFacet:obj2 identity:[communicator stringToIdentity:@"id1"] facet:@"f2"]; + + ICEObject* obj3 = [[FacetsEmptyI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [obj3 autorelease]; +#endif + + [adapter addFacet:obj1 identity:[communicator stringToIdentity:@"id2"] facet:@"f1"]; + [adapter addFacet:obj2 identity:[communicator stringToIdentity:@"id2"] facet:@"f2"]; + [adapter addFacet:obj3 identity:[communicator stringToIdentity:@"id2"] facet:@""]; + NSDictionary* fm = [adapter removeAllFacets:[communicator stringToIdentity:@"id1"]]; + test([fm count] == 2); + test([fm objectForKey:@"f1"] == obj1); + test([fm objectForKey:@"f2"] == obj2); + @try + { + [adapter removeAllFacets:[communicator stringToIdentity:@"id1"]]; + test(NO); + } + @catch(ICENotRegisteredException*) + { + } + fm = [adapter removeAllFacets:[communicator stringToIdentity:@"id2"]]; + test([fm count] == 3); + test([fm objectForKey:@"f1"] == obj1); + test([fm objectForKey:@"f2"] == obj2); + test([fm objectForKey:@""] == obj3); + tprintf("ok\n"); + + [adapter deactivate]; + + tprintf("testing stringToProxy... "); + NSString* ref = @"d:default -p 12010"; + id<ICEObjectPrx> db = [communicator stringToProxy:ref]; + test(db); + tprintf("ok\n"); + + tprintf("testing unchecked cast... "); + id<ICEObjectPrx> prx = [ICEObjectPrx uncheckedCast:db]; + test([[prx ice_getFacet] length] == 0); + prx = [ICEObjectPrx uncheckedCast:db facet:@"facetABCD"]; + test([[prx ice_getFacet] isEqualToString:@"facetABCD"]); + id<ICEObjectPrx> prx2 = [ICEObjectPrx uncheckedCast:prx]; + test([[prx2 ice_getFacet] isEqualToString:@"facetABCD"]); + id<ICEObjectPrx> prx3 = [ICEObjectPrx uncheckedCast:prx facet:@""]; + test([[prx3 ice_getFacet] length] == 0); + id<TestFacetsDPrx> d = [TestFacetsDPrx uncheckedCast:db]; + test([[d ice_getFacet] length] == 0); + id<TestFacetsDPrx> df = [TestFacetsDPrx uncheckedCast:db facet:@"facetABCD"]; + test([[df ice_getFacet] isEqualToString:@"facetABCD"]); + id<TestFacetsDPrx> df2 = [TestFacetsDPrx uncheckedCast:df]; + test([[df2 ice_getFacet] isEqualToString:@"facetABCD"]); + id<TestFacetsDPrx> df3 = [TestFacetsDPrx uncheckedCast:df facet:@""]; + test([[df3 ice_getFacet] length] == 0); + tprintf("ok\n"); + + tprintf("testing checked cast... "); + prx = [ICEObjectPrx checkedCast:db]; + test([[prx ice_getFacet] length] == 0); + prx = [ICEObjectPrx checkedCast:db facet:@"facetABCD"]; + test([[prx ice_getFacet] isEqualToString:@"facetABCD"]); + prx2 = [ICEObjectPrx checkedCast:prx]; + test([[prx2 ice_getFacet] isEqualToString:@"facetABCD"]); + prx3 = [ICEObjectPrx checkedCast:prx facet:@""]; + test([[prx3 ice_getFacet] length] == 0); + d = [TestFacetsDPrx checkedCast:db]; + test([[d ice_getFacet] length] == 0); + df = [TestFacetsDPrx checkedCast:db facet:@"facetABCD"]; + test([[df ice_getFacet] isEqualToString:@"facetABCD"]); + df2 = [TestFacetsDPrx checkedCast:df]; + test([[df2 ice_getFacet] isEqualToString:@"facetABCD"]); + df3 = [TestFacetsDPrx checkedCast:df facet:@""]; + test([[df3 ice_getFacet] length] == 0); + tprintf("ok\n"); + + tprintf("testing non-facets A, B, C, and D... "); + d = [TestFacetsDPrx checkedCast:db]; + test(d); + test([d isEqual:db]); + test([[d callA] isEqualToString:@"A"]); + test([[d callB] isEqualToString:@"B"]); + test([[d callC] isEqualToString:@"C"]); + test([[d callD] isEqualToString:@"D"]); + tprintf("ok\n"); + + tprintf("testing facets A, B, C, and D... "); + df = [TestFacetsDPrx checkedCast:d facet:@"facetABCD"]; + test(df); + test([[df callA] isEqualToString:@"A"]); + test([[df callB] isEqualToString:@"B"]); + test([[df callC] isEqualToString:@"C"]); + test([[df callD] isEqualToString:@"D"]); + tprintf("ok\n"); + + tprintf("testing facets E and F... "); + id<TestFacetsFPrx> ff = [TestFacetsFPrx checkedCast:d facet:@"facetEF"]; + test(ff); + test([[ff callE] isEqualToString:@"E"]); + test([[ff callF] isEqualToString:@"F"]); + tprintf("ok\n"); + + tprintf("testing facet G... "); + id<TestFacetsGPrx> gf = [TestFacetsGPrx checkedCast:ff facet:@"facetGH"]; + test(gf); + test([[gf callG] isEqualToString:@"G"]); + tprintf("ok\n"); + + tprintf("testing whether casting preserves the facet... "); + id<TestFacetsHPrx> hf = [TestFacetsHPrx checkedCast:gf]; + test(hf); + test([[hf callG] isEqualToString:@"G"]); + test([[hf callH] isEqualToString:@"H"]); + tprintf("ok\n"); + + return gf; +} diff --git a/objc/test/Ice/facets/Client.m b/objc/test/Ice/facets/Client.m new file mode 100644 index 00000000000..13a704cb259 --- /dev/null +++ b/objc/test/Ice/facets/Client.m @@ -0,0 +1,77 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <FacetsTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + id<TestFacetsGPrx> facetsAllTests(id<ICECommunicator>); + id<TestFacetsGPrx> g = facetsAllTests(communicator); + [g shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main facetsClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestFacets", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/facets/FacetsTest.ice b/objc/test/Ice/facets/FacetsTest.ice new file mode 100644 index 00000000000..435e9343cdb --- /dev/null +++ b/objc/test/Ice/facets/FacetsTest.ice @@ -0,0 +1,61 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestFacets"] +module Test +{ + +interface Empty +{ +}; + +interface A +{ + string callA(); +}; + +interface B extends A +{ + string callB(); +}; + +interface C extends A +{ + string callC(); +}; + +interface D extends B, C +{ + string callD(); +}; + +interface E +{ + string callE(); +}; + +interface F extends E +{ + string callF(); +}; + +interface G +{ + void shutdown(); + string callG(); +}; + +interface H extends G +{ + string callH(); +}; + +}; diff --git a/objc/test/Ice/facets/Makefile b/objc/test/Ice/facets/Makefile new file mode 100644 index 00000000000..5b6bd5534ec --- /dev/null +++ b/objc/test/Ice/facets/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = FacetsTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/facets/Server.m b/objc/test/Ice/facets/Server.m new file mode 100644 index 00000000000..1efa7568116 --- /dev/null +++ b/objc/test/Ice/facets/Server.m @@ -0,0 +1,91 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <facets/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* d = [[[TestFacetsDI alloc] init] autorelease]; + ICEObject* f = [[[TestFacetsFI alloc] init] autorelease]; + ICEObject* h = [[[TestFacetsHI alloc] init] autorelease]; +#else + ICEObject* d = [[TestFacetsDI alloc] init]; + ICEObject* f = [[TestFacetsFI alloc] init]; + ICEObject* h = [[TestFacetsHI alloc] init]; +#endif + [adapter add:d identity:[communicator stringToIdentity:@"d"]]; + [adapter addFacet:d identity:[communicator stringToIdentity:@"d"] facet:@"facetABCD"]; + [adapter addFacet:f identity:[communicator stringToIdentity:@"d"] facet:@"facetEF"]; + [adapter addFacet:h identity:[communicator stringToIdentity:@"d"] facet:@"facetGH"]; + + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main facetsServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestFacets", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/facets/TestI.h b/objc/test/Ice/facets/TestI.h new file mode 100644 index 00000000000..c56837bbd42 --- /dev/null +++ b/objc/test/Ice/facets/TestI.h @@ -0,0 +1,40 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <FacetsTest.h> + +@interface TestFacetsAI : TestFacetsA<TestFacetsA> +@end + +@interface TestFacetsBI : TestFacetsB<TestFacetsB> +@end + +@interface TestFacetsCI : TestFacetsC<TestFacetsC> +@end + +@interface TestFacetsDI : TestFacetsD<TestFacetsD> +@end + +@interface TestFacetsEI : TestFacetsE<TestFacetsE> +@end + +@interface TestFacetsFI : TestFacetsF<TestFacetsF> +@end + +@interface TestFacetsGI : TestFacetsG<TestFacetsG> +{ + id<ICECommunicator> communicator_; +} +-(void) shutdown:(ICECurrent*)current; +-(NSString*) callG:(ICECurrent*)current; +@end + +@interface TestFacetsHI : TestFacetsH<TestFacetsH> +-(NSString*) callH:(ICECurrent*)current; +@end diff --git a/objc/test/Ice/facets/TestI.m b/objc/test/Ice/facets/TestI.m new file mode 100644 index 00000000000..b032e7d39a0 --- /dev/null +++ b/objc/test/Ice/facets/TestI.m @@ -0,0 +1,103 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <facets/TestI.h> + +@implementation TestFacetsAI +-(NSString*) callA:(ICECurrent*)current +{ + return @"A"; +} +@end + +@implementation TestFacetsBI +-(NSString*) callA:(ICECurrent*)current +{ + return @"A"; +} +-(NSString*) callB:(ICECurrent*)current +{ + return @"B"; +} +@end + +@implementation TestFacetsCI +-(NSString*) callA:(ICECurrent*)current +{ + return @"A"; +} +-(NSString*) callC:(ICECurrent*)current +{ + return @"C"; +} +@end + +@implementation TestFacetsDI +-(NSString*) callA:(ICECurrent*)current +{ + return @"A"; +} +-(NSString*) callB:(ICECurrent*)current +{ + return @"B"; +} +-(NSString*) callC:(ICECurrent*)current +{ + return @"C"; +} +-(NSString*) callD:(ICECurrent*)current +{ + return @"D"; +} +@end + +@implementation TestFacetsEI +-(NSString*) callE:(ICECurrent*)current +{ + return @"E"; +} +@end + +@implementation TestFacetsFI +-(NSString*) callE:(ICECurrent*)current +{ + return @"E"; +} +-(NSString*) callF:(ICECurrent*)current +{ + return @"F"; +} +@end + +@implementation TestFacetsGI +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} +-(NSString*) callG:(ICECurrent*)current +{ + return @"G"; +} +@end + +@implementation TestFacetsHI +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} +-(NSString*) callG:(ICECurrent*)current +{ + return @"G"; +} +-(NSString*) callH:(ICECurrent*)current +{ + return @"H"; +} +@end diff --git a/objc/test/Ice/facets/run.py b/objc/test/Ice/facets/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/facets/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/faultTolerance/.gitignore b/objc/test/Ice/faultTolerance/.gitignore new file mode 100644 index 00000000000..aa38efcc5dc --- /dev/null +++ b/objc/test/Ice/faultTolerance/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +Test.m +Test.h diff --git a/objc/test/Ice/faultTolerance/AllTests.m b/objc/test/Ice/faultTolerance/AllTests.m new file mode 100644 index 00000000000..0251e6b97e5 --- /dev/null +++ b/objc/test/Ice/faultTolerance/AllTests.m @@ -0,0 +1,292 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <faultTolerance/Test.h> + +#import <Foundation/Foundation.h> + +@interface Callback : NSObject +{ + BOOL called; + NSCondition* cond; + ICEInt pid; +} +-(void) check; +-(void) called; +-(ICEInt) pid; +@end + +@implementation Callback +-(id) init +{ + if(![super init]) + { + return nil; + } + cond = [[NSCondition alloc] init]; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [super dealloc]; +} +#endif + +-(void) check +{ + [cond lock]; + while(!called) + { + [cond wait]; + } + called = NO; + [cond unlock]; +} +-(void) called +{ + [cond lock]; + called = YES; + [cond signal]; + [cond unlock]; +} +-(void) pidResponse:(ICEInt)p +{ + pid = p; + [self called]; +} + +-(void) pidException:(ICEException*)ex +{ + test(NO); +} +-(ICEInt) pid +{ + return pid; +} +-(void) shutdownResponse +{ + [self called]; +} + +-(void) shutdownException:(ICEException*)ex +{ + test(NO); +} +-(void) abortResponse +{ + test(NO); +} +-(void) abortException:(ICEException*)ex +{ + @try + { + @throw ex; + } + @catch(ICEConnectionLostException*) + { + } + @catch(ICEConnectFailedException*) + { + } + @catch(ICEException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + [self called]; +} +-(void) idempotentAbortResponse +{ + test(NO); +} +-(void) idempotentAbortException:(ICEException*)ex +{ + @try + { + @throw ex; + } + @catch(ICEConnectionLostException*) + { + } + @catch(ICEConnectFailedException*) + { + } + @catch(ICEException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + [self called]; +} +@end + +void +allTests(id<ICECommunicator> communicator, NSArray* ports) +{ + tprintf("testing stringToProxy... "); + NSString* ref = @"test"; + for(NSString* p in ports) + { + ref = [ref stringByAppendingString:@":default -p "]; + ref = [ref stringByAppendingString:p]; + } + id<ICEObjectPrx> base = [communicator stringToProxy:ref]; + test(base); + tprintf("ok\n"); + + tprintf("testing checked cast... "); + id<TestTestIntfPrx> obj = [TestTestIntfPrx checkedCast:base]; + test(obj); + test([obj isEqual:base]); + tprintf("ok\n"); + + int oldPid = 0; + BOOL ami = NO; + unsigned int i, j; + for(i = 1, j = 0; i <= [ports count]; ++i, ++j) + { + if(j > 3) + { + j = 0; + ami = !ami; + } + + if(!ami) + { + tprintf("testing server %d... ", i); + int pid = [obj pid]; + test(pid != oldPid); + tprintf("ok\n"); + oldPid = pid; + } + else + { + tprintf("testing server %d with AMI... ", i); + Callback* cb = [[Callback alloc] init]; + [obj begin_pid:^(ICEInt pid) { [cb pidResponse:pid]; } + exception:^(ICEException* ex) { [cb pidException:ex]; } ]; + [cb check]; + int pid = [cb pid]; + test(pid != oldPid); + oldPid = pid; +#if defined(__clang__) && !__has_feature(objc_arc) + [cb release]; +#endif + tprintf("ok\n"); + } + + if(j == 0) + { + if(!ami) + { + tprintf("shutting down server %d... ", i); + [obj shutdown]; + tprintf("ok\n"); + } + else + { + tprintf("shutting down server %d with AMI... ", i); + Callback* cb = [[Callback alloc] init]; + [obj begin_shutdown:^{ [cb shutdownResponse]; } + exception:^(ICEException* ex) { [cb shutdownException:ex]; }]; + [cb check]; +#if defined(__clang__) && !__has_feature(objc_arc) + [cb release]; +#endif + tprintf("ok\n"); + } + } + else if(j == 1 || i + 1 > [ports count]) + { + if(!ami) + { + tprintf("aborting server %d... ", i); + @try + { + [obj abort]; + test(NO); + } + @catch(ICEConnectionLostException*) + { + tprintf("ok\n"); + } + @catch(ICEConnectFailedException*) + { + tprintf("ok\n"); + } + } + else + { + tprintf("aborting server %d with AMI... ", i); + Callback* cb = [[Callback alloc] init]; + [obj begin_abort:^{ [cb abortResponse]; } exception:^(ICEException* ex) { [cb abortException:ex]; }]; + [cb check]; +#if defined(__clang__) && !__has_feature(objc_arc) + [cb release]; +#endif + tprintf("ok\n"); + } + } + else if(j == 2 || j == 3) + { + if(!ami) + { + tprintf("aborting server %d and #%d with idempotent call... ", i, i + 1); + @try + { + [obj idempotentAbort]; + test(NO); + } + @catch(ICEConnectionLostException*) + { + tprintf("ok\n"); + } + @catch(ICEConnectFailedException*) + { + tprintf("ok\n"); + } + } + else + { + tprintf("aborting server %d and #%d with idempotent AMI call... ", i, i + 1); + Callback* cb = [[Callback alloc] init]; + [obj begin_idempotentAbort:^{ [cb idempotentAbortResponse]; } + exception:^(ICEException* ex) { [cb idempotentAbortException:ex]; }]; + [cb check]; +#if defined(__clang__) && !__has_feature(objc_arc) + [cb release]; +#endif + tprintf("ok\n"); + } + + ++i; + } + else + { + test(NO); + } + } + + tprintf("testing whether all servers are gone... "); + @try + { + [obj ice_ping]; + test(NO); + } + @catch(ICELocalException*) + { + tprintf("ok\n"); + } +} + diff --git a/objc/test/Ice/faultTolerance/Client.m b/objc/test/Ice/faultTolerance/Client.m new file mode 100644 index 00000000000..314e7fa6b80 --- /dev/null +++ b/objc/test/Ice/faultTolerance/Client.m @@ -0,0 +1,106 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <faultTolerance/Test.h> +#import <stdio.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +void +usage(const char* n) +{ + printf("Usage: %s port\n", n); +} + +int +run(int argc, char* argv[], id<ICECommunicator> communicator) +{ + NSMutableArray* ports = [NSMutableArray array]; + int i; + for(i = 1; i < argc; ++i) + { + if(argv[i][0] == '-') + { + fprintf(stderr, "%s: unknown option `%s'", argv[0], argv[i]); + usage(argv[0]); + return EXIT_FAILURE; + } + + [ports addObject:[NSString stringWithUTF8String:argv[i]]]; + } + + if([ports count] == 0) + { + fprintf(stderr, "%s: no ports specified", argv[0]); + usage(argv[0]); + return EXIT_FAILURE; + } + + @try + { + void allTests(id<ICECommunicator>, NSArray*); + allTests(communicator, ports); + } + @catch(ICEException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + + return EXIT_SUCCESS; +} + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); + + // + // This test aborts servers, so we don't want warnings. + // + [initData.properties setProperty:@"Ice.Warn.Connections" value:@"0"]; + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + + status = run(argc, argv, communicator); + } + @catch(ICEException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/faultTolerance/Makefile b/objc/test/Ice/faultTolerance/Makefile new file mode 100644 index 00000000000..80e19841796 --- /dev/null +++ b/objc/test/Ice/faultTolerance/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = Test.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/faultTolerance/Server.m b/objc/test/Ice/faultTolerance/Server.m new file mode 100644 index 00000000000..998279cb5e0 --- /dev/null +++ b/objc/test/Ice/faultTolerance/Server.m @@ -0,0 +1,115 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <faultTolerance/TestI.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +#import <stdio.h> + +static void +usage(const char* n) +{ + printf("Usage: %s port\n", n); +} + +static int +run(int argc, char** argv, id<ICECommunicator> communicator) +{ + int port = 0; + int i; + for(i = 1; i < argc; ++i) + { + if(argv[i][0] == '-') + { + fprintf(stderr, "%s: unknown option `%s'", argv[0], argv[i]); + usage(argv[0]); + return EXIT_FAILURE; + } + + if(port > 0) + { + fprintf(stderr, "%s: only one port can be specified", argv[0]); + usage(argv[0]); + return EXIT_FAILURE; + } + + port = atoi(argv[i]); + } + + if(port <= 0) + { + fprintf(stderr, "%s: no port specified", argv[0]); + usage(argv[0]); + return EXIT_FAILURE; + } + + NSString* endpts = [NSString stringWithFormat:@"default -p %d:udp", port]; + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:endpts]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; + +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* object = [[[TestI alloc] init] autorelease]; +#else + ICEObject* object = [[TestI alloc] init]; +#endif + [adapter add:object identity:[communicator stringToIdentity:@"test"]]; + [adapter activate]; + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + // + // In this test, we need a longer server idle time, otherwise + // our test servers may time out before they are used in the + // test. + // + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = [ICEUtil createProperties:&argc argv:argv]; + [initData.properties setProperty:@"Ice.ServerIdleTime" value:@"120"]; // Two minutes. + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(argc, argv, communicator); + } + @catch(ICEException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + NSLog(@"%@", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/faultTolerance/Test.ice b/objc/test/Ice/faultTolerance/Test.ice new file mode 100644 index 00000000000..8b1e15a963e --- /dev/null +++ b/objc/test/Ice/faultTolerance/Test.ice @@ -0,0 +1,23 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Test +{ + +interface TestIntf +{ + void shutdown(); + void abort(); + idempotent void idempotentAbort(); + idempotent int pid(); +}; + +}; diff --git a/objc/test/Ice/faultTolerance/TestI.h b/objc/test/Ice/faultTolerance/TestI.h new file mode 100644 index 00000000000..0f9d2672c50 --- /dev/null +++ b/objc/test/Ice/faultTolerance/TestI.h @@ -0,0 +1,14 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <faultTolerance/Test.h> + +@interface TestI : TestTestIntf<TestTestIntf> +@end + diff --git a/objc/test/Ice/faultTolerance/TestI.m b/objc/test/Ice/faultTolerance/TestI.m new file mode 100644 index 00000000000..12ce4ea3cf5 --- /dev/null +++ b/objc/test/Ice/faultTolerance/TestI.m @@ -0,0 +1,36 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <faultTolerance/TestI.h> + +#include <unistd.h> + +@implementation TestI +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} + +-(void) abort:(ICECurrent*)current +{ + exit(0); +} + +-(void) idempotentAbort:(ICECurrent*)current +{ + exit(0); +} + +-(ICEInt) pid:(ICECurrent*)current +{ + return getpid(); +} +@end + diff --git a/objc/test/Ice/faultTolerance/run.py b/objc/test/Ice/faultTolerance/run.py new file mode 100755 index 00000000000..01a58d2a3d0 --- /dev/null +++ b/objc/test/Ice/faultTolerance/run.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +server = os.path.join(os.getcwd(), "server") +client = os.path.join(os.getcwd(), "client") + +num = 12 +base = 13340 + +serverProc = [] +for i in range(0, num): + print "starting server #%d..." % (i + 1), + serverProc.append(TestUtil.startServer(server, "%d" % (base + i))) + print "ok" + +ports = "" +for i in range(0, num): + ports = "%s %d" % (ports, base + i) + +print "starting client...", +clientProc = TestUtil.startClient(client, ports + " " + "--Ice.Trace.Network=0", startReader = False) +print "ok" +clientProc.startReader() + +clientProc.waitTestSuccess() +for p in serverProc: + p.waitTestSuccess() diff --git a/objc/test/Ice/hash/.gitignore b/objc/test/Ice/hash/.gitignore new file mode 100644 index 00000000000..be837f9fdf3 --- /dev/null +++ b/objc/test/Ice/hash/.gitignore @@ -0,0 +1,7 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +.depend +HashTest.m +HashTest.h diff --git a/objc/test/Ice/hash/AllTests.m b/objc/test/Ice/hash/AllTests.m new file mode 100644 index 00000000000..f63e9d56759 --- /dev/null +++ b/objc/test/Ice/hash/AllTests.m @@ -0,0 +1,163 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <HashTest.h> + +#import <Foundation/Foundation.h> + +void +hashAllTests() +{ + int maxCollisions = 10; + int maxIterations = 10000; + + { + tprintf("testing proxy hash algorithm collisions... "); + int collisions = 0; + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = [ICEUtil createProperties]; + id<ICECommunicator> communicator = [ICEUtil createCommunicator:initData]; + NSMutableDictionary* seenObject = [[NSMutableDictionary alloc] init]; + for(int i = 0; collisions < maxCollisions && i < maxIterations; ++i) + { + NSString* s = [NSString stringWithFormat:@"%i:tcp -p %i -t 10%i:udp -p %i -h %i", + i, arc4random() % 65536, arc4random() % 1000000, + arc4random() % 65536, arc4random() % 100]; + ICEObjectPrx* obj = [communicator stringToProxy:s]; + + NSNumber* hash = [NSNumber numberWithUnsignedInteger:[obj hash]]; + + if([seenObject objectForKey:hash]) + { + if([obj isEqual:[seenObject objectForKey:hash]]) + { + continue; + } + ++collisions; + } + else + { + [seenObject setObject:obj forKey:hash]; + } + // + // Test the same object produce always the same hash. + // + test([obj hash] == [obj hash]); + test(collisions < maxCollisions); + } + [seenObject removeAllObjects]; + [communicator destroy]; +#if defined(__clang__) && !__has_feature(objc_arc) + [seenObject release]; +#endif + tprintf("ok\n"); + } + + tprintf("testing struct hash algorithm collisions... "); + { + int collisions = 0; + NSMutableDictionary* seenObject = [[NSMutableDictionary alloc] init]; + for(int i = 0; collisions < maxCollisions && i < maxIterations; ++i) + { + TestHashPoint* obj = [TestHashPoint point:(arc4random() % 1000) + y:(arc4random() % 1000)]; + NSNumber* hash = [NSNumber numberWithUnsignedInteger:[obj hash]]; + if([seenObject objectForKey:hash]) + { + if([obj isEqual:[seenObject objectForKey:hash]]) + { + continue; + } + ++collisions; + } + else + { + [seenObject setObject:obj forKey:hash]; + } + // + // Test the same object produce always the same hash. + // + test([obj hash] == [obj hash]); + test(collisions < maxCollisions); + } + [seenObject removeAllObjects]; +#if defined(__clang__) && !__has_feature(objc_arc) + [seenObject release]; +#endif + } + { + int collisions = 0; + NSMutableDictionary* seenObject = [[NSMutableDictionary alloc] init]; + for(int i = 0; collisions < maxCollisions && i < maxIterations; ++i) + { + TestHashPointF* obj = [TestHashPointF pointF:(arc4random() % 1000)/3 + y:(arc4random() % 1000)/5 + z:(arc4random() % 1000)/7]; + + NSNumber* hash = [NSNumber numberWithUnsignedInteger:[obj hash]]; + if([seenObject objectForKey:hash]) + { + if([obj isEqual:[seenObject objectForKey:hash]]) + { + continue; + } + ++collisions; + } + else + { + [seenObject setObject:obj forKey:hash]; + } + // + // Test the same object produce always the same hash. + // + test([obj hash] == [obj hash]); + test(collisions < maxCollisions); + } + [seenObject removeAllObjects]; +#if defined(__clang__) && !__has_feature(objc_arc) + [seenObject release]; +#endif + } + + { + int collisions = 0; + NSMutableDictionary* seenObject = [[NSMutableDictionary alloc] init]; + for(int i = 0; collisions < maxCollisions && i < maxIterations; ++i) + { + TestHashPointD* obj = [TestHashPointD pointD:(arc4random() % 1000)/3 + y:(arc4random() % 1000)/5 + z:(arc4random() % 1000)/7]; + NSNumber* hash = [NSNumber numberWithUnsignedInteger:[obj hash]]; + if([seenObject objectForKey:hash]) + { + if([obj isEqual:[seenObject objectForKey:hash]]) + { + continue; + } + ++collisions; + } + else + { + [seenObject setObject:obj forKey:hash]; + } + // + // Test the same object produce always the same hash. + // + test([obj hash] == [obj hash]); + test(collisions < maxCollisions); + } + [seenObject removeAllObjects]; +#if defined(__clang__) && !__has_feature(objc_arc) + [seenObject release]; +#endif + } + tprintf("ok\n"); +} diff --git a/objc/test/Ice/hash/Client.m b/objc/test/Ice/hash/Client.m new file mode 100644 index 00000000000..e91fddc6370 --- /dev/null +++ b/objc/test/Ice/hash/Client.m @@ -0,0 +1,53 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <HashTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run() +{ + void hashAllTests(); + hashAllTests(); + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main hashClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + @try + { + status = run(); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/hash/HashTest.ice b/objc/test/Ice/hash/HashTest.ice new file mode 100644 index 00000000000..d9e8e42bee0 --- /dev/null +++ b/objc/test/Ice/hash/HashTest.ice @@ -0,0 +1,93 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestHash"] +module Test +{ + + +exception BaseException +{ +}; + +exception InvalidPointException extends BaseException +{ + int index; +}; + +exception InvalidLengthException extends BaseException +{ + int length; +}; + +exception OtherException +{ + int x; + int y; + int z; + bool b; +}; + + +struct PointF +{ + float x; + float y; + float z; +}; + +struct PointD +{ + double x; + double y; + double z; +}; + +struct Point +{ + int x; + int y; +}; +sequence<Point> Points; + +struct Polyline +{ + Points vertices; +}; + +struct Color +{ + int r; + int g; + int b; + int a; +}; +dictionary<int, Color> StringColorMap; + +struct ColorPalette +{ + StringColorMap colors; +}; + +class Pen +{ + int thickness; + Test::Color color; +}; + +struct Draw +{ + Test::Color backgroundColor; + Test::Pen pen; + bool shared; +}; + +}; diff --git a/objc/test/Ice/hash/Makefile b/objc/test/Ice/hash/Makefile new file mode 100644 index 00000000000..cf6376b4c5e --- /dev/null +++ b/objc/test/Ice/hash/Makefile @@ -0,0 +1,29 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client + +TARGETS = $(CLIENT) + +SLICE_OBJS = HashTest.o + +COBJS = Client.o \ + AllTests.o + +OBJS = $(COBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/hash/run.py b/objc/test/Ice/hash/run.py new file mode 100755 index 00000000000..ac32c445572 --- /dev/null +++ b/objc/test/Ice/hash/run.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +client = os.path.join(os.getcwd(), "client") +TestUtil.simpleTest(client) + diff --git a/objc/test/Ice/hold/.gitignore b/objc/test/Ice/hold/.gitignore new file mode 100644 index 00000000000..4e573bb9e5f --- /dev/null +++ b/objc/test/Ice/hold/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +HoldTest.m +HoldTest.h diff --git a/objc/test/Ice/hold/AllTests.m b/objc/test/Ice/hold/AllTests.m new file mode 100644 index 00000000000..30219fa74c1 --- /dev/null +++ b/objc/test/Ice/hold/AllTests.m @@ -0,0 +1,266 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <HoldTest.h> + +#import <Foundation/Foundation.h> + +@interface Condition : NSObject +{ + BOOL value; +} +-(id) initWithValue:(BOOL)value; +@property (assign) BOOL value; +@end + +@implementation Condition + +@synthesize value; + +-(id) initWithValue:(BOOL)v +{ + self = [super init]; + if(!self) + { + return nil; + } + value = v; + return self; +} +@end + +@interface AMICheckSetValue : NSObject +{ + Condition* condition; + ICEInt expected; + BOOL sent; + NSCondition* cond; +} +-(id)init:(Condition*)cond expected:(ICEInt)expected; +-(void) waitForSent; +@end + +@implementation AMICheckSetValue +-(id)init:(Condition*)c expected:(ICEInt)e +{ + self = [super init]; + if(!self) + { + return nil; + } + cond = [[NSCondition alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + condition = [c retain]; +#else + condition = c; +#endif + expected = e; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [condition release]; + [super dealloc]; +} +#endif + +-(void) ice_response:(ICEInt)value +{ + if(value != expected) + { + condition.value = NO; + } +} +-(void) ice_exception:(ICEException*)ex +{ + tprintf("unexpected exception: %@", ex); + test(false); +} +-(void) ice_sent +{ + [cond lock]; + sent = YES; + [cond signal]; + [cond unlock]; +} +-(void) waitForSent +{ + [cond lock]; + while(!sent) + { + [cond wait]; + } + [cond unlock]; +} +@end + +void +allTests(id<ICECommunicator> communicator) +{ + tprintf("testing stringToProxy... "); + NSString* ref = @"hold:default -p 12010 -t 30000"; + id<ICEObjectPrx> base = [communicator stringToProxy:ref]; + test(base); + NSString* refSerialized = @"hold:default -p 12011 -t 60000"; + id<ICEObjectPrx> baseSerialized = [communicator stringToProxy:refSerialized]; + test(base); + tprintf("ok\n"); + + tprintf("testing checked cast... "); + id<TestHoldHoldPrx> hold = [TestHoldHoldPrx checkedCast:base]; + test(hold); + test([hold isEqual:base]); + id<TestHoldHoldPrx> holdSerialized = [TestHoldHoldPrx checkedCast:baseSerialized]; + test(holdSerialized); + test([holdSerialized isEqual:baseSerialized]); + tprintf("ok\n"); + + tprintf("changing state between active and hold rapidly... "); + int i; + for(i = 0; i < 100; ++i) + { + [hold putOnHold:0]; + } + for(i = 0; i < 100; ++i) + { + [[hold ice_oneway] putOnHold:0]; + } + for(i = 0; i < 100; ++i) + { + [holdSerialized putOnHold:0]; + } + for(i = 0; i < 100; ++i) + { + [[holdSerialized ice_oneway] putOnHold:0]; + } + tprintf("ok\n"); + + tprintf("testing without serialize mode... "); + { +#if defined(__clang__) && !__has_feature(objc_arc) + Condition* cond = [[[Condition alloc] initWithValue:YES] autorelease]; +#else + Condition* cond = [[Condition alloc] initWithValue:YES]; +#endif + int value = 0; + AMICheckSetValue* cb; + while([cond value]) + { +#if defined(__clang__) && !__has_feature(objc_arc) + cb = [[[AMICheckSetValue alloc] init:cond expected:value] autorelease]; +#else + cb = [[AMICheckSetValue alloc] init:cond expected:value]; +#endif + if([hold begin_set:++value delay:(random() % 5 + 1) response:^(ICEInt r) { [cb ice_response:r]; } + exception:^(ICEException* ex) { [cb ice_exception:ex]; } sent:^(BOOL ss) { [cb ice_sent]; }]) + { + cb = 0; + } + if(value % 100 == 0) + { + if(cb) + { + [cb waitForSent]; + cb = 0; + } + } + } + if(cb) + { + [cb waitForSent]; + cb = 0; + } + } + tprintf("ok\n"); + + tprintf("testing with serialize mode... "); + { +#if defined(__clang__) && !__has_feature(objc_arc) + Condition* cond = [[[Condition alloc] initWithValue:YES] autorelease]; +#else + Condition* cond = [[Condition alloc] initWithValue:YES]; +#endif + int value = 0; + AMICheckSetValue* cb; +#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR + while(value < 300 && [cond value]) +#else + while(value < 3000 && [cond value]) +#endif + { +#if defined(__clang__) && !__has_feature(objc_arc) + cb = [[[AMICheckSetValue alloc] init:cond expected:value] autorelease]; +#else + cb = [[AMICheckSetValue alloc] init:cond expected:value]; +#endif + if([holdSerialized begin_set:++value delay:0 response:^(ICEInt r) { [cb ice_response:r]; } + exception:^(ICEException* ex) { [cb ice_exception:ex]; } sent:^(BOOL ss) { [cb ice_sent]; }]) + { + cb = 0; + } + if(value % 100 == 0) + { + if(cb) + { + [cb waitForSent]; + cb = 0; + } + } + } + if(cb) + { + [cb waitForSent]; + cb = 0; + } + test([cond value]); + int i; +#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR + for(i = 0; i < 400; ++i) +#else + for(i = 0; i < 20000; ++i) +#endif + { + [[holdSerialized ice_oneway] setOneway:(value + 1) expected:value]; + ++value; + if((i % 100) == 0) + { + [[holdSerialized ice_oneway] putOnHold:1]; + } + } + } + tprintf("ok\n"); + + tprintf("testing waitForHold... "); + { + [hold waitForHold]; + [hold waitForHold]; + for(i = 0; i < 1000; ++i) + { + [[hold ice_oneway] ice_ping]; + if((i % 20) == 0) + { + [hold putOnHold:0]; + } + } + [hold putOnHold:-1]; + [hold ice_ping]; + [hold putOnHold:-1]; + [hold ice_ping]; + } + tprintf("ok\n"); + + tprintf("changing state to hold and shutting down server... "); + [hold shutdown]; + tprintf("ok\n"); +} diff --git a/objc/test/Ice/hold/Client.m b/objc/test/Ice/hold/Client.m new file mode 100644 index 00000000000..d3b5a40408a --- /dev/null +++ b/objc/test/Ice/hold/Client.m @@ -0,0 +1,76 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <HoldTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +int +run(id<ICECommunicator> communicator) +{ + void allTests(id<ICECommunicator>); + allTests(communicator); + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main holdClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestHold", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/hold/HoldTest.ice b/objc/test/Ice/hold/HoldTest.ice new file mode 100644 index 00000000000..bc77416ef31 --- /dev/null +++ b/objc/test/Ice/hold/HoldTest.ice @@ -0,0 +1,25 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestHold"] +module Test +{ + +interface Hold +{ + void putOnHold(int seconds); + void waitForHold(); + int set(int value, int delay); + void setOneway(int value, int expected); + void shutdown(); +}; + +}; diff --git a/objc/test/Ice/hold/Makefile b/objc/test/Ice/hold/Makefile new file mode 100644 index 00000000000..bf682f4e99f --- /dev/null +++ b/objc/test/Ice/hold/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = HoldTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/hold/Server.m b/objc/test/Ice/hold/Server.m new file mode 100644 index 00000000000..0c0c4918524 --- /dev/null +++ b/objc/test/Ice/hold/Server.m @@ -0,0 +1,101 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <hold/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter1.Endpoints" value:@"default -p 12010 -t 10000:udp"]; + [[communicator getProperties] setProperty:@"TestAdapter1.ThreadPool.Size" value:@"5"]; + [[communicator getProperties] setProperty:@"TestAdapter1.ThreadPool.SizeMax" value:@"5"]; + [[communicator getProperties] setProperty:@"TestAdapter1.ThreadPool.SizeWarn" value:@"0"]; + [[communicator getProperties] setProperty:@"TestAdapter1.ThreadPool.Serialize" value:@"0"]; + id<ICEObjectAdapter> adapter1 = [communicator createObjectAdapter:@"TestAdapter1"]; + + + [[communicator getProperties] setProperty:@"TestAdapter2.Endpoints" value:@"default -p 12011 -t 10000:udp"]; + [[communicator getProperties] setProperty:@"TestAdapter2.ThreadPool.Size" value:@"5"]; + [[communicator getProperties] setProperty:@"TestAdapter2.ThreadPool.SizeMax" value:@"5"]; + [[communicator getProperties] setProperty:@"TestAdapter2.ThreadPool.SizeWarn" value:@"0"]; + [[communicator getProperties] setProperty:@"TestAdapter2.ThreadPool.Serialize" value:@"1"]; + id<ICEObjectAdapter> adapter2 = [communicator createObjectAdapter:@"TestAdapter2"]; + +#if defined(__clang__) && !__has_feature(objc_arc) + [adapter1 add:[[[HoldI alloc] init] autorelease] identity:[communicator stringToIdentity:@"hold"]]; + [adapter2 add:[[[HoldI alloc] init] autorelease] identity:[communicator stringToIdentity:@"hold"]]; +#else + [adapter1 add:[[HoldI alloc] init] identity:[communicator stringToIdentity:@"hold"]]; + [adapter2 add:[[HoldI alloc] init] identity:[communicator stringToIdentity:@"hold"]]; +#endif + + [adapter1 activate]; + [adapter2 activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main holdServer +#endif + +int +main(int argc, char* argv[]) +{ + @autoreleasepool + { + int status; + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestHold", @"::Test", + nil]; +#endif + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; + } +} diff --git a/objc/test/Ice/hold/TestI.h b/objc/test/Ice/hold/TestI.h new file mode 100644 index 00000000000..07c6906264c --- /dev/null +++ b/objc/test/Ice/hold/TestI.h @@ -0,0 +1,28 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + + +#import <HoldTest.h> + +#include <dispatch/dispatch.h> + +@interface Timer : NSObject +{ + dispatch_queue_t queue; +} +-(void) schedule:(void(^)())callback timeout:(ICEInt)timeout; +@end + +@interface HoldI : TestHoldHold<TestHoldHold> +{ + ICEInt last; + Timer* timer; +} + +@end diff --git a/objc/test/Ice/hold/TestI.m b/objc/test/Ice/hold/TestI.m new file mode 100644 index 00000000000..c65ec48a150 --- /dev/null +++ b/objc/test/Ice/hold/TestI.m @@ -0,0 +1,140 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <hold/TestI.h> +#import <TestCommon.h> + +#import <Foundation/Foundation.h> + +@implementation Timer +-(id) init +{ + self = [super init]; + if(self != nil) + { + queue = dispatch_queue_create("timer", NULL); + } + return self; +} +-(void) dealloc +{ + dispatch_release(queue); +#if defined(__clang__) && !__has_feature(objc_arc) + [super dealloc]; +#endif +} +-(void) schedule:(void(^)())callback timeout:(ICEInt)t +{ + dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); + dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, t * NSEC_PER_MSEC), DISPATCH_TIME_FOREVER, 0); + dispatch_source_set_event_handler(timer, ^{ + callback(); + dispatch_source_cancel(timer); + dispatch_release(timer); + }); + dispatch_resume(timer); +} +@end + +@implementation HoldI +-(id) init +{ + self = [super init]; + if(self != nil) + { + timer = [Timer new]; + } + return self; +} +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [timer release]; + [super dealloc]; +} +#endif +-(void) putOnHold:(ICEInt)milliSeconds current:(ICECurrent*)current +{ + if(milliSeconds < 0) + { + [current.adapter hold]; + } + else if(milliSeconds == 0) + { + [current.adapter hold]; + [current.adapter activate]; + } + else + { + [timer schedule:^{ + @try + { + [current.adapter hold]; + [current.adapter activate]; + } + @catch(ICEObjectAdapterDeactivatedException* ex) + { + } + @catch(id ex) + { + test(NO); + } + } timeout:milliSeconds]; + } +} + +-(void) waitForHold:(ICECurrent*)current +{ + [timer schedule:^{ + @try + { + [current.adapter waitForHold]; + [current.adapter activate]; + } + @catch(ICEObjectAdapterDeactivatedException* ex) + { + test(NO); + } + @catch(id ex) + { + test(NO); + } + } timeout:0]; +} + +-(ICEInt) set:(ICEInt)value delay:(ICEInt)delay current:(ICECurrent*)current +{ + [NSThread sleepForTimeInterval:delay / 1000.0]; + @synchronized(self) + { + ICEInt tmp = last; + last = value; + return tmp; + } + return 0; +} + + +-(void) setOneway:(ICEInt)value expected:(ICEInt)expected current:(ICECurrent*)current +{ + @synchronized(self) + { + test(last == expected); + last = value; + } +} + +-(void) shutdown:(ICECurrent*)current +{ + [current.adapter hold]; + [[current.adapter getCommunicator] shutdown]; +} + +@end diff --git a/objc/test/Ice/hold/run.py b/objc/test/Ice/hold/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/hold/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/info/.gitignore b/objc/test/Ice/info/.gitignore new file mode 100644 index 00000000000..23a7fa22453 --- /dev/null +++ b/objc/test/Ice/info/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +InfoTest.m +InfoTest.h diff --git a/objc/test/Ice/info/AllTests.m b/objc/test/Ice/info/AllTests.m new file mode 100644 index 00000000000..c364ed99d4e --- /dev/null +++ b/objc/test/Ice/info/AllTests.m @@ -0,0 +1,173 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <InfoTest.h> + + +TestInfoTestIntfPrx* +infoAllTests(id<ICECommunicator> communicator) +{ + tprintf("testing proxy endpoint information... "); + { + ICEObjectPrx* p1 = [communicator stringToProxy:@"test -t:default -h tcphost -p 10000 -t 1200 -z:" + "udp -h udphost -p 10001 --interface eth0 --ttl 5:" + "opaque -e 1.8 -t 100 -v ABCD"]; + + ICEEndpointSeq* endps = [p1 ice_getEndpoints]; + id<ICEEndpoint> endpoint = [endps objectAtIndex:0]; + ICEIPEndpointInfo* ipEndpoint = (ICEIPEndpointInfo*)[endpoint getInfo]; + test([ipEndpoint isKindOfClass:[ICEIPEndpointInfo class]]); + test([[ipEndpoint host] isEqualToString:@"tcphost"]); + test(ipEndpoint.port == 10000); + test(ipEndpoint.timeout == 1200); + test(ipEndpoint.compress); + test(![ipEndpoint datagram]); + test(([ipEndpoint type] == ICETCPEndpointType && ![ipEndpoint secure]) || + ([ipEndpoint type] == ICESSLEndpointType && [ipEndpoint secure])); + + test(([ipEndpoint type] == ICETCPEndpointType && [ipEndpoint isKindOfClass:[ICETCPEndpointInfo class]]) || + ([ipEndpoint type] == ICESSLEndpointType && [ipEndpoint isKindOfClass:[ICESSLEndpointInfo class]])); + + + endpoint = [endps objectAtIndex:1]; + ICEUDPEndpointInfo* udpEndpoint = (ICEUDPEndpointInfo*)[endpoint getInfo]; + test([udpEndpoint isKindOfClass:[ICEUDPEndpointInfo class]]); + test([udpEndpoint.host isEqualToString:@"udphost"]); + test(udpEndpoint.port == 10001); + test([udpEndpoint.mcastInterface isEqualToString:@"eth0"]); + test(udpEndpoint.mcastTtl == 5); + test(udpEndpoint.timeout == -1); + test(!udpEndpoint.compress); + test(![udpEndpoint secure]); + test([udpEndpoint datagram]); + test([udpEndpoint type] == ICEUDPEndpointType); + + endpoint = [endps objectAtIndex:2]; + ICEOpaqueEndpointInfo* opaqueEndpoint = (ICEOpaqueEndpointInfo*)[endpoint getInfo]; + test([opaqueEndpoint isKindOfClass:[ICEOpaqueEndpointInfo class]]); + ICEEncodingVersion* rev = [[ICEEncodingVersion alloc] init:1 minor:8]; +#if defined(__clang__) && !__has_feature(objc_arc) + [rev autorelease]; +#endif + test([opaqueEndpoint.rawEncoding isEqual:rev]); + } + tprintf("ok\n"); + + NSString* defaultHost = [[communicator getProperties] getProperty:@"Ice.Default.Host"]; + tprintf("test object adapter endpoint information... "); + { + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -t 15000:udp"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; + + ICEEndpointSeq* endpoints = [adapter getEndpoints]; + test([endpoints count] == 2); + ICEEndpointSeq* publishedEndpoints = [adapter getPublishedEndpoints]; + test([endpoints isEqualToArray:publishedEndpoints]); + + id<ICEEndpoint> endpoint = [endpoints objectAtIndex:0]; + ICEIPEndpointInfo* ipEndpoint = (ICEIPEndpointInfo*)[endpoint getInfo]; + test([ipEndpoint isKindOfClass:[ICEIPEndpointInfo class]]); + test([ipEndpoint type] == ICETCPEndpointType || [ipEndpoint type] == ICESSLEndpointType); + test([ipEndpoint.host isEqualToString:defaultHost]); + test(ipEndpoint.port > 0); + test(ipEndpoint.timeout == 15000); + + endpoint = [endpoints objectAtIndex:1]; + ICEUDPEndpointInfo* udpEndpoint = (ICEUDPEndpointInfo*)[endpoint getInfo]; + test([udpEndpoint isKindOfClass:[ICEUDPEndpointInfo class]]); + test([udpEndpoint.host isEqualToString:defaultHost]); + test([udpEndpoint datagram]); + test(udpEndpoint.port > 0); + + [adapter destroy]; + + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -h * -p 12020"]; + [[communicator getProperties] setProperty:@"TestAdapter.PublishedEndpoints" value:@"default -h 127.0.0.1 -p 12020"]; + adapter = [communicator createObjectAdapter:@"TestAdapter"]; + + endpoints = [adapter getEndpoints]; + test([endpoints count] >= 1); + publishedEndpoints = [adapter getPublishedEndpoints]; + test([publishedEndpoints count] == 1); + + for(id object in endpoints) + { + endpoint = (id<ICEEndpoint>)object; + ipEndpoint = (ICEIPEndpointInfo*)[endpoint getInfo]; + test(ipEndpoint.port == 12020); + } + + ipEndpoint = (ICEIPEndpointInfo*)[[publishedEndpoints objectAtIndex:0] getInfo]; + test([ipEndpoint.host isEqualToString:@"127.0.0.1"]); + test(ipEndpoint.port == 12020); + + [adapter destroy]; + } + tprintf("ok\n"); + + ICEObjectPrx* base = [communicator stringToProxy:@"test:default -p 12010:udp -p 12010"]; + TestInfoTestIntfPrx* testIntf = [TestInfoTestIntfPrx checkedCast:base]; + + tprintf("test connection endpoint information... "); + { + ICEEndpointInfo* info = [[[base ice_getConnection] getEndpoint] getInfo]; + ICEIPEndpointInfo* ipinfo = (ICEIPEndpointInfo*)info; + test([ipinfo isKindOfClass:[ICEIPEndpointInfo class]]); + test(ipinfo.port == 12010); + test(!ipinfo.compress); + test([ipinfo.host isEqualToString:defaultHost]); + + ICEContext* ctx = [testIntf getEndpointInfoAsContext]; + test([[ctx objectForKey:@"host"] isEqualToString:ipinfo.host]); + test([[ctx objectForKey:@"compress"] isEqualToString:@"false"]); + test([[ctx objectForKey:@"port"] intValue] > 0); + + info = [[[[base ice_datagram] ice_getConnection] getEndpoint] getInfo]; + ICEUDPEndpointInfo* udp = (ICEUDPEndpointInfo*)info; + test([udp isKindOfClass:[ICEUDPEndpointInfo class]]); + test(udp.port == 12010); + test([udp.host isEqualToString:defaultHost]); + } + tprintf("ok\n"); + + tprintf("testing connection information... "); + { + ICEIPConnectionInfo* info = (ICEIPConnectionInfo*)[[base ice_getConnection] getInfo]; + test([info isKindOfClass:[ICEIPConnectionInfo class]]); + test(!info.incoming); + test([info.adapterName isEqualToString:@""]); + test(info.localPort > 0); + test(info.remotePort == 12010); + test([info.remoteAddress isEqualToString:defaultHost]); + test([info.localAddress isEqualToString:defaultHost]); + + + ICEContext* ctx = [testIntf getConnectionInfoAsContext]; + test([[ctx objectForKey:@"incoming"] isEqualToString:@"true"]); + test([[ctx objectForKey:@"adapterName"] isEqualToString:@"TestAdapter"]); + test([[ctx objectForKey:@"remoteAddress"] isEqualToString:info.remoteAddress]); + test([[ctx objectForKey:@"localAddress"] isEqualToString:info.localAddress]); + test([[ctx objectForKey:@"remotePort"] intValue] == info.localPort); + test([[ctx objectForKey:@"localPort"] intValue] == info.remotePort); + + info = (ICEIPConnectionInfo*)[[[base ice_datagram] ice_getConnection] getInfo]; + test([info isKindOfClass:[ICEIPConnectionInfo class]]); + test(!info.incoming); + test([info.adapterName isEqualToString:@""]); + test(info.localPort > 0); + test(info.remotePort == 12010); + test([info.remoteAddress isEqualToString:defaultHost]); + test([info.localAddress isEqualToString:defaultHost]); + } + tprintf("ok\n"); + + return testIntf; +} diff --git a/objc/test/Ice/info/Client.m b/objc/test/Ice/info/Client.m new file mode 100644 index 00000000000..85dfcb28eb5 --- /dev/null +++ b/objc/test/Ice/info/Client.m @@ -0,0 +1,79 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <InfoTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + TestInfoTestIntfPrx* infoAllTests(id<ICECommunicator>); + TestInfoTestIntfPrx* intf = infoAllTests(communicator); + + [intf shutdown]; + + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main infoClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestInfo", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/info/InfoTest.ice b/objc/test/Ice/info/InfoTest.ice new file mode 100644 index 00000000000..dfeb7fc62e4 --- /dev/null +++ b/objc/test/Ice/info/InfoTest.ice @@ -0,0 +1,27 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +#include <Ice/Current.ice> + +["objc:prefix:TestInfo"] +module Test +{ + +interface TestIntf +{ + void shutdown(); + + Ice::Context getEndpointInfoAsContext(); + + Ice::Context getConnectionInfoAsContext(); +}; + +}; diff --git a/objc/test/Ice/info/Makefile b/objc/test/Ice/info/Makefile new file mode 100644 index 00000000000..3156167470a --- /dev/null +++ b/objc/test/Ice/info/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = InfoTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/info/Server.m b/objc/test/Ice/info/Server.m new file mode 100644 index 00000000000..408b98a85ff --- /dev/null +++ b/objc/test/Ice/info/Server.m @@ -0,0 +1,83 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <info/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010:udp"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + [adapter add:[[[TestInfoTestIntfI alloc] init] autorelease] + identity:[communicator stringToIdentity:@"test"]]; +#else + [adapter add:[[TestInfoTestIntfI alloc] init] identity:[communicator stringToIdentity:@"test"]]; +#endif + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main infoServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestProxy", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/info/TestI.h b/objc/test/Ice/info/TestI.h new file mode 100644 index 00000000000..295eb601ab2 --- /dev/null +++ b/objc/test/Ice/info/TestI.h @@ -0,0 +1,19 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <InfoTest.h> + +@interface TestInfoTestIntfI : TestInfoTestIntf<TestInfoTestIntf> +{ +} + +-(void) shutdown:(ICECurrent*)current; +-(ICEContext*) getEndpointInfoAsContext:(ICECurrent*)current; +-(ICEContext*) getConnectionInfoAsContext:(ICECurrent*)current; +@end diff --git a/objc/test/Ice/info/TestI.m b/objc/test/Ice/info/TestI.m new file mode 100644 index 00000000000..16c44bf48fc --- /dev/null +++ b/objc/test/Ice/info/TestI.m @@ -0,0 +1,60 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <info/TestI.h> +#import <TestCommon.h> + +@implementation TestInfoTestIntfI + + +-(void) shutdown:(ICECurrent*)c +{ + [[[c adapter] getCommunicator] shutdown]; +} + +-(ICEContext*) getEndpointInfoAsContext:(ICECurrent*)current +{ + id<ICEEndpoint> endpoint = [current.con getEndpoint]; + ICEEndpointInfo* info = [endpoint getInfo]; + + ICEMutableContext* ctx = [ICEMutableContext dictionaryWithObject:[NSString stringWithFormat:@"%d", [info timeout]] + forKey:@"timeout"]; + + [ctx setObject:info.compress ? @"true" : @"false" forKey:@"compress"]; + [ctx setObject:[info datagram] ? @"true" : @"false" forKey:@"datagram"]; + [ctx setObject:[info secure] ? @"true" : @"false" forKey:@"secure"]; + [ctx setObject:[NSString stringWithFormat:@"%d", [info type]] forKey:@"type"]; + + ICEIPEndpointInfo* ipinfo = (ICEIPEndpointInfo*)info; + [ctx setObject:ipinfo.host forKey:@"host"]; + [ctx setObject:[NSString stringWithFormat:@"%d", ipinfo.port] forKey:@"port"]; + + if([ipinfo isKindOfClass:[ICEUDPEndpointInfo class]]) + { + ICEUDPEndpointInfo* udp = (ICEUDPEndpointInfo*)ipinfo; + [ctx setObject:udp.mcastInterface forKey:@"mcastInterface"]; + [ctx setObject:[NSString stringWithFormat:@"%d", udp.mcastTtl] forKey:@"mcastTtl"]; + } + return ctx; +} + +-(ICEContext*) getConnectionInfoAsContext:(ICECurrent*)current +{ + ICEConnectionInfo* info = [[current con] getInfo]; + ICEMutableContext* ctx = [ICEMutableContext dictionaryWithObject:[info adapterName] forKey:@"adapterName"]; + [ctx setObject:info.incoming ? @"true" : @"false" forKey:@"incoming"]; + ICEIPConnectionInfo* ipinfo = (ICEIPConnectionInfo*)info; + [ctx setObject:ipinfo.localAddress forKey:@"localAddress"]; + [ctx setObject:[NSString stringWithFormat:@"%d", ipinfo.localPort] forKey:@"localPort"]; + [ctx setObject:ipinfo.remoteAddress forKey:@"remoteAddress"]; + [ctx setObject:[NSString stringWithFormat:@"%d", ipinfo.remotePort] forKey:@"remotePort"]; + return ctx; +} +@end diff --git a/objc/test/Ice/info/run.py b/objc/test/Ice/info/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/info/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/inheritance/.gitignore b/objc/test/Ice/inheritance/.gitignore new file mode 100644 index 00000000000..54661118c80 --- /dev/null +++ b/objc/test/Ice/inheritance/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +InheritanceTest.m +InheritanceTest.h diff --git a/objc/test/Ice/inheritance/AllTests.m b/objc/test/Ice/inheritance/AllTests.m new file mode 100644 index 00000000000..f55588b0b64 --- /dev/null +++ b/objc/test/Ice/inheritance/AllTests.m @@ -0,0 +1,222 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <InheritanceTest.h> + + +id<TestInheritanceInitialPrx> +inheritanceAllTests(id<ICECommunicator> communicator) +{ + tprintf("testing stringToProxy... "); + NSString* ref = @"initial:default -p 12010"; + id<ICEObjectPrx> base = [communicator stringToProxy:ref]; + test(base); + tprintf("ok\n"); + + tprintf("testing checked cast... "); + id<TestInheritanceInitialPrx> initial = [TestInheritanceInitialPrx checkedCast:base]; + test(initial); + test([initial isEqual:base]); + tprintf("ok\n"); + + tprintf("getting proxies for class hierarchy... "); + id<TestInheritanceMACAPrx> ca = [initial caop]; + id<TestInheritanceMBCBPrx> cb = [initial cbop]; + id<TestInheritanceMACCPrx> cc = [initial ccop]; + id<TestInheritanceMACDPrx> cd = [initial cdop]; + test(ca != cb); + test(ca != cc); + test(ca != cd); + test(cb != cc); + test(cb != cd); + test(cc != cd); + tprintf("ok\n"); + + tprintf("getting proxies for interface hierarchy... "); + id<TestInheritanceMAIAPrx> ia = [initial iaop]; + id<TestInheritanceMBIB1Prx> ib1 = [initial ib1op]; + id<TestInheritanceMBIB2Prx> ib2 = [initial ib2op]; + id<TestInheritanceMAICPrx> ic = [initial icop]; + test(ia != ib1); + test(ia != ib2); + test(ia != ic); + test(ib1 != ic); + test(ib2 != ic); + tprintf("ok\n"); + + tprintf("invoking proxy operations on class hierarchy... "); + id<TestInheritanceMACAPrx> cao; + id<TestInheritanceMBCBPrx> cbo; + id<TestInheritanceMACCPrx> cco; + + cao = [ca caop:ca]; + test([cao isEqual:ca]); + cao = [ca caop:cb]; + test([cao isEqual:cb]); + cao = [ca caop:cc]; + test([cao isEqual:cc]); + cao = [cb caop:ca]; + test([cao isEqual:ca]); + cao = [cb caop:cb]; + test([cao isEqual:cb]); + cao = [cb caop:cc]; + test([cao isEqual:cc]); + cao = [cc caop:ca]; + test([cao isEqual:ca]); + cao = [cc caop:cb]; + test([cao isEqual:cb]); + cao = [cc caop:cc]; + test([cao isEqual:cc]); + + cao = [cb cbop:cb]; + test([cao isEqual:cb]); + cbo = [cb cbop:cb]; + test([cbo isEqual:cb]); + cao = [cb cbop:cc]; + test([cao isEqual:cc]); + cbo = [cb cbop:cc]; + test([cbo isEqual:cc]); + cao = [cc cbop:cb]; + test([cao isEqual:cb]); + cbo = [cc cbop:cb]; + test([cbo isEqual:cb]); + cao = [cc cbop:cc]; + test([cao isEqual:cc]); + cbo = [cc cbop:cc]; + test([cbo isEqual:cc]); + + cao = [cc ccop:cc]; + test([cao isEqual:cc]); + cbo = [cc ccop:cc]; + test([cbo isEqual:cc]); + cco = [cc ccop:cc]; + test([cco isEqual:cc]); + tprintf("ok\n"); + + tprintf("ditto, but for interface hierarchy... "); + id<TestInheritanceMAIAPrx> iao; + id<TestInheritanceMBIB1Prx> ib1o; + id<TestInheritanceMBIB2Prx> ib2o; + id<TestInheritanceMAICPrx> ico; + + iao = [ia iaop:ia]; + test([iao isEqual:ia]); + iao = [ia iaop:ib1]; + test([iao isEqual:ib1]); + iao = [ia iaop:ib2]; + test([iao isEqual:ib2]); + iao = [ia iaop:ic]; + test([iao isEqual:ic]); + iao = [ib1 iaop:ia]; + test([iao isEqual:ia]); + iao = [ib1 iaop:ib1]; + test([iao isEqual:ib1]); + iao = [ib1 iaop:ib2]; + test([iao isEqual:ib2]); + iao = [ib1 iaop:ic]; + test([iao isEqual:ic]); + iao = [ib2 iaop:ia]; + test([iao isEqual:ia]); + iao = [ib2 iaop:ib1]; + test([iao isEqual:ib1]); + iao = [ib2 iaop:ib2]; + test([iao isEqual:ib2]); + iao = [ib2 iaop:ic]; + test([iao isEqual:ic]); + iao = [ic iaop:ia]; + test([iao isEqual:ia]); + iao = [ic iaop:ib1]; + test([iao isEqual:ib1]); + iao = [ic iaop:ib2]; + test([iao isEqual:ib2]); + iao = [ic iaop:ic]; + test([iao isEqual:ic]); + + iao = [ib1 ib1op:ib1]; + test([iao isEqual:ib1]); + ib1o = [ib1 ib1op:ib1]; + test([ib1o isEqual:ib1]); + iao = [ib1 ib1op:ic]; + test([iao isEqual:ic]); + ib1o = [ib1 ib1op:ic]; + test([ib1o isEqual:ic]); + iao = [ic ib1op:ib1]; + test([iao isEqual:ib1]); + ib1o = [ic ib1op:ib1]; + test([ib1o isEqual:ib1]); + iao = [ic ib1op:ic]; + test([iao isEqual:ic]); + ib1o = [ic ib1op:ic]; + test([ib1o isEqual:ic]); + + iao = [ib2 ib2op:ib2]; + test([iao isEqual:ib2]); + ib2o = [ib2 ib2op:ib2]; + test([ib2o isEqual:ib2]); + iao = [ib2 ib2op:ic]; + test([iao isEqual:ic]); + ib2o = [ib2 ib2op:ic]; + test([ib2o isEqual:ic]); + iao = [ic ib2op:ib2]; + test([iao isEqual:ib2]); + ib2o = [ic ib2op:ib2]; + test([ib2o isEqual:ib2]); + iao = [ic ib2op:ic]; + test([iao isEqual:ic]); + ib2o = [ic ib2op:ic]; + test([ib2o isEqual:ic]); + + iao = [ic icop:ic]; + test([iao isEqual:ic]); + ib1o = [ic icop:ic]; + test([ib1o isEqual:ic]); + ib2o = [ic icop:ic]; + test([ib2o isEqual:ic]); + ico = [ic icop:ic]; + test([ico isEqual:ic]); + + tprintf("ok\n"); + + tprintf("ditto, but for class implementing interfaces... "); +// id<TestInheritanceMACDPrx> cdo; + + cao = [cd caop:cd]; + test([cao isEqual:cd]); + cbo = [cd cbop:cd]; + test([cbo isEqual:cd]); + cco = [cd ccop:cd]; + test([cco isEqual:cd]); + + iao = [cd iaop:cd]; + test([iao isEqual:cd]); + ib1o = [cd ib1op:cd]; + test([ib1o isEqual:cd]); + ib2o = [cd ib2op:cd]; + test([ib2o isEqual:cd]); + + cao = [cd cdop:cd]; + test([cao isEqual:cd]); + cbo = [cd cdop:cd]; + test([cbo isEqual:cd]); + cco = [cd cdop:cd]; + test([cco isEqual:cd]); + + iao = [cd cdop:cd]; + test([iao isEqual:cd]); + ib1o = [cd cdop:cd]; + test([ib1o isEqual:cd]); + ib2o = [cd cdop:cd]; + test([ib2o isEqual:cd]); + + tprintf("ok\n"); + + return initial; +} diff --git a/objc/test/Ice/inheritance/Client.m b/objc/test/Ice/inheritance/Client.m new file mode 100644 index 00000000000..684b462f80b --- /dev/null +++ b/objc/test/Ice/inheritance/Client.m @@ -0,0 +1,77 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <InheritanceTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + id<TestInheritanceInitialPrx> inheritanceAllTests(id<ICECommunicator>); + id<TestInheritanceInitialPrx> initial = inheritanceAllTests(communicator); + [initial shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main inheritanceClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestInheritance", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/inheritance/InheritanceTest.ice b/objc/test/Ice/inheritance/InheritanceTest.ice new file mode 100644 index 00000000000..aa5c59b2171 --- /dev/null +++ b/objc/test/Ice/inheritance/InheritanceTest.ice @@ -0,0 +1,87 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestInheritance"] +module Test +{ + +["objc:prefix:TestInheritanceMA"] +module MA +{ + +interface IA +{ + IA* iaop(IA* p); +}; + +class CA +{ + CA* caop(CA* p); +}; + +}; + +["objc:prefix:TestInheritanceMB"] +module MB +{ + +interface IB1 extends MA::IA +{ + IB1* ib1op(IB1* p); +}; + +interface IB2 extends MA::IA +{ + IB2* ib2op(IB2* p); +}; + +class CB extends MA::CA +{ + CB* cbop(CB* p); +}; + +}; + +["objc:prefix:TestInheritanceMA"] +module MA +{ + +interface IC extends MB::IB1, MB::IB2 +{ + IC* icop(IC* p); +}; + +class CC extends MB::CB +{ + CC* ccop(CC* p); +}; + +class CD extends CC implements MB::IB1, MB::IB2 +{ + CD* cdop(CD* p); +}; + +}; + +interface Initial +{ + void shutdown(); + MA::CA* caop(); + MB::CB* cbop(); + MA::CC* ccop(); + MA::CD* cdop(); + MA::IA* iaop(); + MB::IB1* ib1op(); + MB::IB2* ib2op(); + MA::IC* icop(); +}; + +}; diff --git a/objc/test/Ice/inheritance/Makefile b/objc/test/Ice/inheritance/Makefile new file mode 100644 index 00000000000..eb5f28651d7 --- /dev/null +++ b/objc/test/Ice/inheritance/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = InheritanceTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/inheritance/Server.m b/objc/test/Ice/inheritance/Server.m new file mode 100644 index 00000000000..b105154f4a1 --- /dev/null +++ b/objc/test/Ice/inheritance/Server.m @@ -0,0 +1,83 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <inheritance/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* object = [[[TestInheritanceInitialI alloc] initWithAdapter:adapter] autorelease]; +#else + ICEObject* object = [[TestInheritanceInitialI alloc] initWithAdapter:adapter]; +#endif + [adapter add:object identity:[communicator stringToIdentity:@"initial"]]; + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main inheritanceServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestInheritance", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/inheritance/TestI.h b/objc/test/Ice/inheritance/TestI.h new file mode 100644 index 00000000000..8ade1ba0402 --- /dev/null +++ b/objc/test/Ice/inheritance/TestI.h @@ -0,0 +1,50 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <InheritanceTest.h> + +@interface TestInheritanceInitialI : TestInheritanceInitial<TestInheritanceInitial> +{ + id<ICEObjectAdapter> adapter_; + id<TestInheritanceMACAPrx> ca_; + id<TestInheritanceMBCBPrx> cb_; + id<TestInheritanceMACCPrx> cc_; + id<TestInheritanceMACDPrx> cd_; + id<TestInheritanceMAIAPrx> ia_; + id<TestInheritanceMBIB1Prx> ib1_; + id<TestInheritanceMBIB2Prx> ib2_; + id<TestInheritanceMAICPrx> ic_; +} +-(id)initWithAdapter:(id<ICEObjectAdapter>) adapter; +@end + +@interface CAI : TestInheritanceMACA<TestInheritanceMACA> +@end + +@interface CBI : TestInheritanceMBCB<TestInheritanceMBCB> +@end + +@interface CCI : TestInheritanceMACC<TestInheritanceMACC> +@end + +@interface IAI : TestInheritanceMAIA<TestInheritanceMAIA> +@end + +@interface IB1I : TestInheritanceMBIB1<TestInheritanceMBIB1> +@end + +@interface IB2I : TestInheritanceMBIB2<TestInheritanceMBIB2> +@end + +@interface ICI : TestInheritanceMAIC<TestInheritanceMAIC> +@end + +@interface CDI : TestInheritanceMACD<TestInheritanceMACD> +@end + diff --git a/objc/test/Ice/inheritance/TestI.m b/objc/test/Ice/inheritance/TestI.m new file mode 100644 index 00000000000..b1e981d0fce --- /dev/null +++ b/objc/test/Ice/inheritance/TestI.m @@ -0,0 +1,198 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <inheritance/TestI.h> + +@implementation CAI +-(id<TestInheritanceMACAPrx>) caop:(id<TestInheritanceMACAPrx>)p current:(ICECurrent*)current +{ + return p; +} +@end + +@implementation CBI +-(id<TestInheritanceMACAPrx>) caop:(id<TestInheritanceMACAPrx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMBCBPrx>) cbop:(id<TestInheritanceMBCBPrx>)p current:(ICECurrent*)current +{ + return p; +} +@end + +@implementation CCI +-(id<TestInheritanceMACAPrx>) caop:(id<TestInheritanceMACAPrx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMBCBPrx>) cbop:(id<TestInheritanceMBCBPrx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMACCPrx>) ccop:(id<TestInheritanceMACCPrx>)p current:(ICECurrent*)current +{ + return p; +} +@end + +@implementation IAI +-(id<TestInheritanceMAIAPrx>) iaop:(id<TestInheritanceMAIAPrx>)p current:(ICECurrent*)current +{ + return p; +} +@end + +@implementation IB1I +-(id<TestInheritanceMAIAPrx>) iaop:(id<TestInheritanceMAIAPrx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMBIB1Prx>) ib1op:(id<TestInheritanceMBIB1Prx>)p current:(ICECurrent*)current +{ + return p; +} +@end + +@implementation IB2I +-(id<TestInheritanceMAIAPrx>) iaop:(id<TestInheritanceMAIAPrx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMBIB2Prx>) ib2op:(id<TestInheritanceMBIB2Prx>)p current:(ICECurrent*)current +{ + return p; +} +@end + +@implementation ICI +-(id<TestInheritanceMAIAPrx>) iaop:(id<TestInheritanceMAIAPrx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMBIB1Prx>) ib1op:(id<TestInheritanceMBIB1Prx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMBIB2Prx>) ib2op:(id<TestInheritanceMBIB2Prx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMAICPrx>) icop:(id<TestInheritanceMAICPrx>)p current:(ICECurrent*)current +{ + return p; +} +@end + +@implementation CDI +-(id<TestInheritanceMACAPrx>) caop:(id<TestInheritanceMACAPrx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMBCBPrx>) cbop:(id<TestInheritanceMBCBPrx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMACCPrx>) ccop:(id<TestInheritanceMACCPrx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMACDPrx>) cdop:(id<TestInheritanceMACDPrx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMAIAPrx>) iaop:(id<TestInheritanceMAIAPrx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMBIB1Prx>) ib1op:(id<TestInheritanceMBIB1Prx>)p current:(ICECurrent*)current +{ + return p; +} +-(id<TestInheritanceMBIB2Prx>) ib2op:(id<TestInheritanceMBIB2Prx>)p current:(ICECurrent*)current +{ + return p; +} +@end + +@implementation TestInheritanceInitialI +-(id) initWithAdapter:(id<ICEObjectAdapter>)adapter +{ + self = [super init]; + if(!self) + { + return nil; + } +#if defined(__clang__) && !__has_feature(objc_arc) + ca_ = [TestInheritanceMACAPrx uncheckedCast:[adapter addWithUUID:[[[CAI alloc] init] autorelease]]]; + cb_ = [TestInheritanceMBCBPrx uncheckedCast:[adapter addWithUUID:[[[CBI alloc] init] autorelease]]]; + cc_ = [TestInheritanceMACCPrx uncheckedCast:[adapter addWithUUID:[[[CCI alloc] init] autorelease]]]; + cd_ = [TestInheritanceMACDPrx uncheckedCast:[adapter addWithUUID:[[[CDI alloc] init] autorelease]]]; + ia_ = [TestInheritanceMAIAPrx uncheckedCast:[adapter addWithUUID:[[[IAI alloc] init] autorelease]]]; + ib1_ = [TestInheritanceMBIB1Prx uncheckedCast:[adapter addWithUUID:[[[IB1I alloc] init] autorelease]]]; + ib2_ = [TestInheritanceMBIB2Prx uncheckedCast:[adapter addWithUUID:[[[IB2I alloc] init] autorelease]]]; + ic_ = [TestInheritanceMAICPrx uncheckedCast:[adapter addWithUUID:[[[ICI alloc] init] autorelease]]]; +#else + ca_ = [TestInheritanceMACAPrx uncheckedCast:[adapter addWithUUID:[[CAI alloc] init]]]; + cb_ = [TestInheritanceMBCBPrx uncheckedCast:[adapter addWithUUID:[[CBI alloc] init]]]; + cc_ = [TestInheritanceMACCPrx uncheckedCast:[adapter addWithUUID:[[CCI alloc] init]]]; + cd_ = [TestInheritanceMACDPrx uncheckedCast:[adapter addWithUUID:[[CDI alloc] init]]]; + ia_ = [TestInheritanceMAIAPrx uncheckedCast:[adapter addWithUUID:[[IAI alloc] init]]]; + ib1_ = [TestInheritanceMBIB1Prx uncheckedCast:[adapter addWithUUID:[[IB1I alloc] init]]]; + ib2_ = [TestInheritanceMBIB2Prx uncheckedCast:[adapter addWithUUID:[[IB2I alloc] init]]]; + ic_ = [TestInheritanceMAICPrx uncheckedCast:[adapter addWithUUID:[[ICI alloc] init]]]; +#endif + return self; +} +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} + +-(id<TestInheritanceMACAPrx>) caop:(ICECurrent*)current +{ + return ca_; +} + +-(id<TestInheritanceMBCBPrx>) cbop:(ICECurrent*)current +{ + return cb_; +} + +-(id<TestInheritanceMACCPrx>) ccop:(ICECurrent*)current +{ + return cc_; +} + +-(id<TestInheritanceMACDPrx>) cdop:(ICECurrent*)current +{ + return cd_; +} + +-(id<TestInheritanceMAIAPrx>) iaop:(ICECurrent*)current +{ + return ia_; +} + +-(id<TestInheritanceMBIB1Prx>) ib1op:(ICECurrent*)current +{ + return ib1_; +} + +-(id<TestInheritanceMBIB2Prx>) ib2op:(ICECurrent*)current +{ + return ib2_; +} + +-(id<TestInheritanceMAICPrx>) icop:(ICECurrent*)current +{ + return ic_; +} +@end diff --git a/objc/test/Ice/inheritance/run.py b/objc/test/Ice/inheritance/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/inheritance/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/interceptor/.gitignore b/objc/test/Ice/interceptor/.gitignore new file mode 100644 index 00000000000..a7aee74ccef --- /dev/null +++ b/objc/test/Ice/interceptor/.gitignore @@ -0,0 +1,7 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +.depend +InterceptorTest.m +InterceptorTest.h diff --git a/objc/test/Ice/interceptor/Client.m b/objc/test/Ice/interceptor/Client.m new file mode 100644 index 00000000000..fc426770700 --- /dev/null +++ b/objc/test/Ice/interceptor/Client.m @@ -0,0 +1,166 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <InterceptorTest.h> +#import <interceptor/MyObjectI.h> +#import <interceptor/InterceptorI.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + // + // Create OA and servants + // + id<ICEObjectAdapter> oa = [communicator createObjectAdapterWithEndpoints:@"MyOA" endpoints:@"tcp -h localhost"]; + ICEObject* servant = [[TestInterceptorMyObjectI alloc] init]; + InterceptorI* interceptor = [[InterceptorI alloc] init:servant]; + +#if defined(__clang__) && !__has_feature(objc_arc) + [servant autorelease]; + [interceptor autorelease]; +#endif + id<TestInterceptorMyObjectPrx> prx = [TestInterceptorMyObjectPrx uncheckedCast:[oa addWithUUID:interceptor]]; + + [oa activate]; + + tprintf("testing simple interceptor... "); + test([[interceptor getLastOperation] length] == 0); + [prx ice_ping]; + test([[interceptor getLastOperation] isEqualToString:@"ice_ping"]); + test([interceptor getLastStatus]); + NSString* typeId = [prx ice_id]; + test([[interceptor getLastOperation] isEqualToString:@"ice_id"]); + test([interceptor getLastStatus]); + test([prx ice_isA:typeId]); + test([[interceptor getLastOperation] isEqualToString:@"ice_isA"]); + test([interceptor getLastStatus]); + test([prx add:33 y:12] == 45); + test([[interceptor getLastOperation] isEqualToString:@"add"]); + test([interceptor getLastStatus]); + tprintf("ok\n"); + + tprintf("testing retry... "); + test([prx addWithRetry:33 y:12] == 45); + test([[interceptor getLastOperation] isEqualToString:@"addWithRetry"]); + test([interceptor getLastStatus]); + tprintf("ok\n"); + + tprintf("testing user exception... "); + @try + { + [prx badAdd:33 y:12]; + test(NO); + } + @catch(TestInterceptorInvalidInputException*) + { + // expected + } + test([[interceptor getLastOperation] isEqualToString:@"badAdd"]); + test([interceptor getLastStatus] == NO); + tprintf("ok\n"); + tprintf("testing ONE... "); + + [interceptor clear]; + @try + { + [prx notExistAdd:33 y:12]; + test(NO); + } + @catch(ICEObjectNotExistException*) + { + // expected + } + test([[interceptor getLastOperation] isEqualToString:@"notExistAdd"]); + tprintf("ok\n"); + tprintf("testing system exception... "); + [interceptor clear]; + @try + { + [prx badSystemAdd:33 y:12]; + test(NO); + } + @catch(ICEUnknownLocalException*) + { + } + @catch(NSException*) + { + test(NO); + } + test([[interceptor getLastOperation] isEqualToString:@"badSystemAdd"]); + tprintf("ok\n"); + + return 0; +} + +#if TARGET_OS_IPHONE +# define main interceptorClient + +int +interceptorServer(int argc, char* argv[]) +{ + serverReady(nil); + return 0; +} +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); + [initData.properties setProperty:@"Ice.Warn.Dispatch" value:@"0"]; +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestInterceptor", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} + diff --git a/objc/test/Ice/interceptor/InterceptorI.h b/objc/test/Ice/interceptor/InterceptorI.h new file mode 100644 index 00000000000..6557d12a7cf --- /dev/null +++ b/objc/test/Ice/interceptor/InterceptorI.h @@ -0,0 +1,25 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> + +@interface InterceptorI : ICEDispatchInterceptor <ICEDispatchInterceptor> +{ + ICEObject* servant; + NSString* lastOperation; + BOOL lastStatus; +} + +-(id) init:(ICEObject*)servant; +-(BOOL) getLastStatus; +-(NSString*) getLastOperation; +-(void) clear; + +@end + diff --git a/objc/test/Ice/interceptor/InterceptorI.m b/objc/test/Ice/interceptor/InterceptorI.m new file mode 100644 index 00000000000..66897f07a81 --- /dev/null +++ b/objc/test/Ice/interceptor/InterceptorI.m @@ -0,0 +1,100 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <interceptor/InterceptorI.h> +#import <InterceptorTest.h> +#import <TestCommon.h> + +@implementation InterceptorI + +-(id) init:(ICEObject*) servant_ +{ + self = [super init]; + if(!self) + { + return nil; + } +#if defined(__clang__) && !__has_feature(objc_arc) + servant = [servant_ retain]; +#else + servant = servant_; +#endif + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [lastOperation release]; + [servant release]; + [super dealloc]; +} +#endif + +-(BOOL) dispatch:(id<ICERequest>) request +{ + ICECurrent* current = [request getCurrent]; + +#if defined(__clang__) && !__has_feature(objc_arc) + [lastOperation release]; + lastOperation = [current.operation retain]; +#else + lastOperation = current.operation; +#endif + + if([lastOperation isEqualToString:@"addWithRetry"]) + { + int i = 0; + for(i = 0; i < 10; ++i) + { + @try + { + [servant ice_dispatch:request]; + test(NO); + } + @catch(TestInterceptorRetryException*) + { + // + // Expected, retry + // + } + } + + [(NSMutableDictionary*)current.ctx setObject:@"no" forKey:@"retry"]; + + // + // A successful dispatch that writes a result we discard + // + [servant ice_dispatch:request]; + } + + lastStatus = [servant ice_dispatch:request]; + return lastStatus; +} + +-(BOOL) getLastStatus +{ + return lastStatus; +} + +-(NSString*) getLastOperation +{ + return lastOperation; +} + +-(void) clear +{ + lastStatus = NO; +#if defined(__clang__) && !__has_feature(objc_arc) + [lastOperation release]; +#endif + lastOperation = nil; +} + +@end diff --git a/objc/test/Ice/interceptor/InterceptorTest.ice b/objc/test/Ice/interceptor/InterceptorTest.ice new file mode 100644 index 00000000000..b2a0776e804 --- /dev/null +++ b/objc/test/Ice/interceptor/InterceptorTest.ice @@ -0,0 +1,53 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestInterceptor"] +module Test +{ + +exception InvalidInputException +{ + string reason; +}; + +local exception RetryException +{ +}; + +interface MyObject +{ + // + // A simple addition + // + int add(int x, int y); + + // + // Will throw RetryException until current.ctx["retry"] is "no" + // + int addWithRetry(int x, int y); + + // + // Raise user exception + // + int badAdd(int x, int y) throws InvalidInputException; + + // + // Raise ONE + // + int notExistAdd(int x, int y); + + // + // Raise system exception + // + int badSystemAdd(int x, int y); +}; + +}; diff --git a/objc/test/Ice/interceptor/Makefile b/objc/test/Ice/interceptor/Makefile new file mode 100644 index 00000000000..80dde2f1048 --- /dev/null +++ b/objc/test/Ice/interceptor/Makefile @@ -0,0 +1,30 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client + +TARGETS = $(CLIENT) + +SLICE_OBJS = InterceptorTest.o + +COBJS = Client.o \ + InterceptorI.o \ + MyObjectI.o \ + +OBJS = $(COBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/interceptor/MyObjectI.h b/objc/test/Ice/interceptor/MyObjectI.h new file mode 100644 index 00000000000..a3e9b33ee1d --- /dev/null +++ b/objc/test/Ice/interceptor/MyObjectI.h @@ -0,0 +1,13 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <InterceptorTest.h> + +@interface TestInterceptorMyObjectI : TestInterceptorMyObject<TestInterceptorMyObject> +@end diff --git a/objc/test/Ice/interceptor/MyObjectI.m b/objc/test/Ice/interceptor/MyObjectI.m new file mode 100644 index 00000000000..2725890c1fd --- /dev/null +++ b/objc/test/Ice/interceptor/MyObjectI.m @@ -0,0 +1,46 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <interceptor/MyObjectI.h> +#import <TestCommon.h> + +@implementation TestInterceptorMyObjectI +-(int) add:(int)x y:(int)y current:(ICECurrent*)current +{ + return x + y; +} + +-(int) addWithRetry:(int)x y:(int)y current:(ICECurrent*)current +{ + id val = [current.ctx objectForKey:@"retry"]; + + if(val == nil || ![(NSString*)val isEqualToString:@"no"]) + { + @throw [TestInterceptorRetryException retryException:__FILE__ line:__LINE__]; + } + return x + y; +} + +-(int) badAdd:(int)x y:(int)y current:(ICECurrent*)current +{ + @throw [TestInterceptorInvalidInputException invalidInputException]; +} + +-(int) notExistAdd:(int)x y:(int)y current:(ICECurrent*)current +{ + @throw [ICEObjectNotExistException objectNotExistException:__FILE__ line:__LINE__]; +} + +-(int) badSystemAdd:(int)x y:(int)y current:(ICECurrent*)current +{ + @throw [ICEInitializationException initializationException:__FILE__ line:__LINE__ reason_:@"testing"]; +} + +@end diff --git a/objc/test/Ice/interceptor/run.py b/objc/test/Ice/interceptor/run.py new file mode 100755 index 00000000000..7f9e0ba78f4 --- /dev/null +++ b/objc/test/Ice/interceptor/run.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +client = os.path.join(os.getcwd(), "client") + +TestUtil.simpleTest(client, " --Ice.Warn.Dispatch=0") diff --git a/objc/test/Ice/invoke/.gitignore b/objc/test/Ice/invoke/.gitignore new file mode 100644 index 00000000000..76608e6287a --- /dev/null +++ b/objc/test/Ice/invoke/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +InvokeTest.m +InvokeTest.h diff --git a/objc/test/Ice/invoke/AllTests.m b/objc/test/Ice/invoke/AllTests.m new file mode 100644 index 00000000000..ab3757e9e73 --- /dev/null +++ b/objc/test/Ice/invoke/AllTests.m @@ -0,0 +1,278 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <InvokeTest.h> + +#import <Foundation/Foundation.h> + +static NSString* testString = @"This is a test string"; + +@interface TestInvokeCallback : NSObject +{ + BOOL called; + NSCondition* cond; + id<ICECommunicator> communicator; +} +-(BOOL) check; +-(void) called; +@end + +@implementation TestInvokeCallback +-(id) initWithCommunicator:(id<ICECommunicator>)c +{ + self = [super init]; + if(!self) + { + return nil; + } + cond = [[NSCondition alloc] init]; + communicator = c; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [super dealloc]; +} +#endif + +-(BOOL) check +{ + [cond lock]; + while(!called) + { + if(![cond waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:50]]) + { + return NO; + } + } + called = NO; + [cond unlock]; + return YES; +} +-(void) called +{ + [cond lock]; + called = YES; + [cond signal]; + [cond unlock]; +} +-(void) opString:(BOOL)ok outEncaps:(NSMutableData*)outEncaps +{ + if(ok) + { + id<ICEInputStream> inS = [ICEUtil createInputStream:communicator data:outEncaps]; + [inS startEncapsulation]; + NSString* s; + s = [inS readString]; + test([s isEqualToString:testString]); + s = [inS readString]; + test([s isEqualToString:testString]); + [inS endEncapsulation]; + [self called]; + } + else + { + test(NO); + } +} + +-(void) opException:(BOOL)ok outEncaps:(NSMutableData*)outEncaps +{ + if(ok) + { + test(NO); + } + else + { + id<ICEInputStream> inS = [ICEUtil createInputStream:communicator data:outEncaps]; + [inS startEncapsulation]; + @try + { + [inS throwException]; + } + @catch(TestInvokeMyException*) + { + [inS endEncapsulation]; + [self called]; + } + @catch(NSException*) + { + test(NO); + } + } +} +@end + +id<TestInvokeMyClassPrx> +invokeAllTests(id<ICECommunicator> communicator) +{ + NSString* ref = @"test:default -p 12010"; + id<ICEObjectPrx> base = [communicator stringToProxy:ref]; + test(base); + + id<TestInvokeMyClassPrx> cl = [TestInvokeMyClassPrx checkedCast:base]; + test(cl); + + id<TestInvokeMyClassPrx> onewayCl = [cl ice_oneway]; + + tprintf("testing ice_invoke... "); + + { + NSData* inEncaps = [NSData data]; + NSMutableData* outEncaps; + if(![onewayCl ice_invoke:@"opOneway" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]) + { + test(NO); + } + + id<ICEOutputStream> outS = [ICEUtil createOutputStream:communicator]; + [outS startEncapsulation]; + [outS writeString:testString]; + [outS endEncapsulation]; + inEncaps = [outS finished]; + // ice_invoke + if([cl ice_invoke:@"opString" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]) + { + id<ICEInputStream> inS = [ICEUtil createInputStream:communicator data:outEncaps]; + [inS startEncapsulation]; + NSString* s; + s = [inS readString]; + test([s isEqualToString:testString]); + s = [inS readString]; + test([s isEqualToString:testString]); + [inS endEncapsulation]; + } + else + { + test(NO); + } + } + + { + NSData* inEncaps = [NSData data]; + NSMutableData* outEncaps; + if([cl ice_invoke:@"opException" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]) + { + test(NO); + } + else + { + id<ICEInputStream> inS = [ICEUtil createInputStream:communicator data:outEncaps]; + [inS startEncapsulation]; + @try + { + [inS throwException]; + } + @catch(TestInvokeMyException*) + { + } + @catch(NSException*) + { + test(NO); + } + [inS endEncapsulation]; + } + } + + tprintf("ok\n"); + + tprintf("testing asynchronous ice_invoke... "); + + { + NSData* inEncaps = [NSData data]; + NSMutableData* outEncaps; + id<ICEAsyncResult> result = [onewayCl begin_ice_invoke:@"opOneway" mode:ICENormal inEncaps:inEncaps]; + if(![onewayCl end_ice_invoke:&outEncaps result:result]) + { + test(NO); + } + + id<ICEOutputStream> outS = [ICEUtil createOutputStream:communicator]; + [outS startEncapsulation]; + [outS writeString:testString]; + [outS endEncapsulation]; + inEncaps = [outS finished]; + + // begin_ice_invoke with no callback + result = [cl begin_ice_invoke:@"opString" mode:ICENormal inEncaps:inEncaps]; + if([cl end_ice_invoke:&outEncaps result:result]) + { + id<ICEInputStream> inS = [ICEUtil createInputStream:communicator data:outEncaps]; + [inS startEncapsulation]; + NSString* s; + s = [inS readString]; + test([s isEqualToString:testString]); + s = [inS readString]; + test([s isEqualToString:testString]); + [inS endEncapsulation]; + } + else + { + test(NO); + }; + + TestInvokeCallback* cb = [[TestInvokeCallback alloc] initWithCommunicator:communicator]; + [cl begin_ice_invoke:@"opString" mode:ICENormal inEncaps:inEncaps + response:^(BOOL ok, NSMutableData* outEncaps) { [cb opString:ok outEncaps:outEncaps]; } + exception:^(ICEException* ex) { test(NO); }]; + [cb check]; +#if defined(__clang__) && !__has_feature(objc_arc) + [cb release]; +#endif + } + + { + NSData* inEncaps = [NSData data]; + NSMutableData* outEncaps; + + // begin_ice_invoke with no callback + id<ICEAsyncResult> result = [cl begin_ice_invoke:@"opException" mode:ICENormal inEncaps:inEncaps]; + if([cl end_ice_invoke:&outEncaps result:result]) + { + test(NO); + } + else + { + id<ICEInputStream> inS = [ICEUtil createInputStream:communicator data:outEncaps]; + [inS startEncapsulation]; + @try + { + [inS throwException]; + } + @catch(TestInvokeMyException*) + { + } + @catch(NSException*) + { + test(NO); + } + [inS endEncapsulation]; + } + + // begin_ice_invoke with Callback_Object_ice_invoke + TestInvokeCallback* cb = [[TestInvokeCallback alloc] initWithCommunicator:communicator]; + [cl begin_ice_invoke:@"opException" mode:ICENormal inEncaps:inEncaps + response:^(BOOL ok, NSMutableData* outP) { [cb opException:ok outEncaps:outP]; } + exception:^(ICEException* ex) { test(NO); }]; + [cb check]; +#if defined(__clang__) && !__has_feature(objc_arc) + [cb release]; +#endif + } + + tprintf("ok\n"); + + return cl; + +} diff --git a/objc/test/Ice/invoke/BlobjectI.h b/objc/test/Ice/invoke/BlobjectI.h new file mode 100644 index 00000000000..ae45836eb31 --- /dev/null +++ b/objc/test/Ice/invoke/BlobjectI.h @@ -0,0 +1,14 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <InvokeTest.h> + +@interface BlobjectI : ICEBlobject<ICEBlobject> +-(BOOL) ice_invoke:(NSData*)inEncaps outEncaps:(NSMutableData**)outEncaps current:(ICECurrent*)current; +@end diff --git a/objc/test/Ice/invoke/BlobjectI.m b/objc/test/Ice/invoke/BlobjectI.m new file mode 100644 index 00000000000..8d768aa5b1f --- /dev/null +++ b/objc/test/Ice/invoke/BlobjectI.m @@ -0,0 +1,76 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <invoke/BlobjectI.h> + +@implementation BlobjectI +-(BOOL) ice_invoke:(NSData*)inEncaps outEncaps:(NSMutableData**)outEncaps current:(ICECurrent*)current +{ + id<ICECommunicator> communicator = [current.adapter getCommunicator]; + id<ICEInputStream> inS = [ICEUtil createInputStream:communicator data:inEncaps]; + id<ICEOutputStream> outS = [ICEUtil createOutputStream:communicator]; + [outS startEncapsulation]; + if([current.operation isEqualToString:@"opOneway"]) + { + return YES; + } + else if([current.operation isEqualToString:@"opString"]) + { + [inS startEncapsulation]; + NSString* s = [inS readString]; + [inS endEncapsulation]; + [outS writeString:s]; + [outS writeString:s]; + [outS endEncapsulation]; + *outEncaps = [outS finished]; + return YES; + } + else if([current.operation isEqualToString:@"opException"]) + { + TestInvokeMyException* ex = [TestInvokeMyException myException]; + [outS writeException:ex]; + [outS endEncapsulation]; + *outEncaps = [outS finished]; + return NO; + } + else if([current.operation isEqualToString:@"shutdown"]) + { + [outS endEncapsulation]; + *outEncaps = [outS finished]; + [communicator shutdown]; + return YES; + } + else if([current.operation isEqualToString:@"ice_isA"]) + { + [inS startEncapsulation]; + NSString* s = [inS readString]; + [inS endEncapsulation]; + if([s isEqualToString:[TestInvokeMyClass ice_staticId]]) + { + [outS writeBool:YES]; + } + else + { + [outS writeBool:NO]; + } + [outS endEncapsulation]; + *outEncaps = [outS finished]; + return YES; + } + else + { + @throw [ICEOperationNotExistException operationNotExistException:__FILE__ + line:__LINE__ + id_:current.id_ + facet:current.facet + operation:current.operation]; + } +} +@end diff --git a/objc/test/Ice/invoke/Client.m b/objc/test/Ice/invoke/Client.m new file mode 100644 index 00000000000..c3055182a33 --- /dev/null +++ b/objc/test/Ice/invoke/Client.m @@ -0,0 +1,77 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <InvokeTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + TestInvokeMyClassPrx* invokeAllTests(id<ICECommunicator>); + TestInvokeMyClassPrx* invoke = invokeAllTests(communicator); + [invoke shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main invokeClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestInvoke", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/invoke/InvokeTest.ice b/objc/test/Ice/invoke/InvokeTest.ice new file mode 100644 index 00000000000..d7391b9799d --- /dev/null +++ b/objc/test/Ice/invoke/InvokeTest.ice @@ -0,0 +1,31 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestInvoke"] +module Test +{ + +exception MyException +{ +}; + +class MyClass +{ + void opOneway(); + + string opString(string s1, out string s2); + + void opException() throws MyException; + + void shutdown(); +}; + +}; diff --git a/objc/test/Ice/invoke/Makefile b/objc/test/Ice/invoke/Makefile new file mode 100644 index 00000000000..a955fa552de --- /dev/null +++ b/objc/test/Ice/invoke/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = InvokeTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = BlobjectI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/invoke/Server.m b/objc/test/Ice/invoke/Server.m new file mode 100644 index 00000000000..25e2a50e75b --- /dev/null +++ b/objc/test/Ice/invoke/Server.m @@ -0,0 +1,81 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <invoke/BlobjectI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010:udp"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + [adapter addDefaultServant:[[[BlobjectI alloc] init] autorelease] category:@""]; +#else + [adapter addDefaultServant:[[BlobjectI alloc] init] category:@""]; +#endif + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main invokeServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestInvoke", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/invoke/run.py b/objc/test/Ice/invoke/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/invoke/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/location/.gitignore b/objc/test/Ice/location/.gitignore new file mode 100644 index 00000000000..cd321e6c61d --- /dev/null +++ b/objc/test/Ice/location/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +LocationTest.m +LocationTest.h diff --git a/objc/test/Ice/location/AllTests.m b/objc/test/Ice/location/AllTests.m new file mode 100644 index 00000000000..c79090cb5dd --- /dev/null +++ b/objc/test/Ice/location/AllTests.m @@ -0,0 +1,479 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <LocationTest.h> + +#include <Foundation/NSThread.h> + +@interface DummyHelloI : TestLocationHello +@end + +@implementation DummyHelloI +-(void) sayHello:(ICECurrent*)current +{ + // Do nothing, this is just a dummy servant. +} +@end + +void +locationAllTests(id<ICECommunicator> communicator, NSString* ref) +{ + id<TestLocationServerManagerPrx> manager = + [TestLocationServerManagerPrx checkedCast:[communicator stringToProxy:ref]]; + id<TestLocationTestLocatorPrx> locator = + [TestLocationTestLocatorPrx uncheckedCast:[communicator getDefaultLocator]]; + test(manager); + + id<TestLocationTestLocatorRegistryPrx> registry = + [TestLocationTestLocatorRegistryPrx checkedCast:[locator getRegistry]]; + test(registry); + + tprintf("testing stringToProxy... "); + id<ICEObjectPrx> base = [communicator stringToProxy:@"test @ TestAdapter"]; + id<ICEObjectPrx> base2 = [communicator stringToProxy:@"test @ TestAdapter"]; + id<ICEObjectPrx> base3 = [communicator stringToProxy:@"test"]; + id<ICEObjectPrx> base4 = [communicator stringToProxy:@"ServerManager"]; + id<ICEObjectPrx> base5 = [communicator stringToProxy:@"test2"]; + id<ICEObjectPrx> base6 = [communicator stringToProxy:@"test @ ReplicatedAdapter"]; + tprintf("ok\n"); + + tprintf("testing ice_locator and ice_getLocator... "); + test([[base ice_getLocator] compareIdentity:[communicator getDefaultLocator]] == NSOrderedSame); + id<ICELocatorPrx> anotherLocator = [ICELocatorPrx uncheckedCast:[communicator stringToProxy:@"anotherLocator"]]; + base = [base ice_locator:anotherLocator]; + test([[base ice_getLocator] compareIdentity:anotherLocator] == NSOrderedSame); + [communicator setDefaultLocator:0]; + base = [communicator stringToProxy:@"test @ TestAdapter"]; + test(![base ice_getLocator]); + base = [base ice_locator:anotherLocator]; + test([[base ice_getLocator] compareIdentity:anotherLocator] == NSOrderedSame); + [communicator setDefaultLocator:locator]; + base = [communicator stringToProxy:@"test @ TestAdapter"]; + test([[base ice_getLocator] compareIdentity:[communicator getDefaultLocator]] == NSOrderedSame); + + // + // We also test ice_router/ice_getRouter (perhaps we should add a + // test/Ice/router test?) + // + test(![base ice_getRouter]); + id<ICERouterPrx> anotherRouter = [ICERouterPrx uncheckedCast:[communicator stringToProxy:@"anotherRouter"]]; + base = [base ice_router:anotherRouter]; + test([[base ice_getRouter] compareIdentity:anotherRouter] == NSOrderedSame); + id<ICERouterPrx> router = [ICERouterPrx uncheckedCast:[communicator stringToProxy:@"dummyrouter"]]; + [communicator setDefaultRouter:router]; + base = [communicator stringToProxy:@"test @ TestAdapter"]; + test([[base ice_getRouter] compareIdentity:[communicator getDefaultRouter]] == NSOrderedSame); + [communicator setDefaultRouter:0]; + base = [communicator stringToProxy:@"test @ TestAdapter"]; + test(![base ice_getRouter]); + tprintf("ok\n"); + + tprintf("starting server... "); + [manager startServer]; + tprintf("ok\n"); + + tprintf("testing checked cast... "); + id<TestLocationTestIntfPrx> obj = [TestLocationTestIntfPrx checkedCast:base]; + obj = [TestLocationTestIntfPrx checkedCast:[communicator stringToProxy:@"test@TestAdapter"]]; + obj = [TestLocationTestIntfPrx checkedCast:[communicator stringToProxy:@"test @TestAdapter"]]; + obj = [TestLocationTestIntfPrx checkedCast:[communicator stringToProxy:@"test@ TestAdapter"]]; + test(obj); + id<TestLocationTestIntfPrx> obj2 = [TestLocationTestIntfPrx checkedCast:base2]; + test(obj2); + id<TestLocationTestIntfPrx> obj3 = [TestLocationTestIntfPrx checkedCast:base3]; + test(obj3); + id<TestLocationServerManagerPrx> obj4 = [TestLocationServerManagerPrx checkedCast:base4]; + test(obj4); + id<TestLocationTestIntfPrx> obj5 = [TestLocationTestIntfPrx checkedCast:base5]; + test(obj5); + id<TestLocationTestIntfPrx> obj6 = [TestLocationTestIntfPrx checkedCast:base6]; + test(obj6); + tprintf("ok\n"); + + tprintf("testing id@AdapterId indirect proxy... "); + [obj shutdown]; + [manager startServer]; + @try + { + obj2 = [TestLocationTestIntfPrx checkedCast:base2]; + [obj2 ice_ping]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + tprintf("ok\n"); + + tprintf("testing id@ReplicaGroupId indirect proxy... "); + [obj shutdown]; + [manager startServer]; + @try + { + obj6 = [TestLocationTestIntfPrx checkedCast:base6]; + [obj6 ice_ping]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + tprintf("ok\n"); + + tprintf("testing identity indirect proxy... "); + [obj shutdown]; + [manager startServer]; + @try + { + obj3 = [TestLocationTestIntfPrx checkedCast:base3]; + [obj3 ice_ping]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + @try + { + obj2 = [TestLocationTestIntfPrx checkedCast:base2]; + [obj2 ice_ping]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + [obj shutdown]; + [manager startServer]; + @try + { + obj2 = [TestLocationTestIntfPrx checkedCast:base2]; + [obj2 ice_ping]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + @try + { + obj3 = [TestLocationTestIntfPrx checkedCast:base3]; + [obj3 ice_ping]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + [obj shutdown]; + [manager startServer]; + + @try + { + obj2 = [TestLocationTestIntfPrx checkedCast:base2]; + [obj2 ice_ping]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + [obj shutdown]; + [manager startServer]; + @try + { + obj3 = [TestLocationTestIntfPrx checkedCast:base3]; + [obj3 ice_ping]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + [obj shutdown]; + [manager startServer]; + @try + { + obj2 = [TestLocationTestIntfPrx checkedCast:base2]; + [obj2 ice_ping]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + [obj shutdown]; + [manager startServer]; + + @try + { + obj5 = [TestLocationTestIntfPrx checkedCast:base5]; + [obj5 ice_ping]; + } + @catch(ICELocalException* ex) + { + NSLog(@"%@", ex); + test(NO); + } + tprintf("ok\n"); + + tprintf("testing proxy with unknown identity... "); + @try + { + base = [communicator stringToProxy:@"unknown/unknown"]; + [base ice_ping]; + test(NO); + } + @catch(ICENotRegisteredException* ex) + { + test([ex.kindOfObject isEqualToString:@"object"]); + test([ex.id_ isEqualToString:@"unknown/unknown"]); + } + tprintf("ok\n"); + + tprintf("testing proxy with unknown adapter... "); + @try + { + base = [communicator stringToProxy:@"test @ TestAdapterUnknown"]; + [base ice_ping]; + test(NO); + } + @catch(ICENotRegisteredException* ex) + { + test([ex.kindOfObject isEqualToString:@"object adapter"]); + test([ex.id_ isEqualToString:@"TestAdapterUnknown"]); + } + tprintf("ok\n"); + + tprintf("testing locator cache timeout... "); + + int count = [locator getRequestCount]; + [[[communicator stringToProxy:@"test@TestAdapter"] ice_locatorCacheTimeout:0] ice_ping]; // No locator cache. + test(++count == [locator getRequestCount]); + [[[communicator stringToProxy:@"test@TestAdapter"] ice_locatorCacheTimeout:0] ice_ping]; // No locator cache. + test(++count == [locator getRequestCount]); + [[[communicator stringToProxy:@"test@TestAdapter"] ice_locatorCacheTimeout:1] ice_ping]; // 1s timeout. + test(count == [locator getRequestCount]); + [NSThread sleepForTimeInterval:1.2]; + [[[communicator stringToProxy:@"test@TestAdapter"] ice_locatorCacheTimeout:1] ice_ping]; // 1s timeout. + test(++count == [locator getRequestCount]); + + [[[communicator stringToProxy:@"test"] ice_locatorCacheTimeout:0] ice_ping]; // No locator cache. + count += 2; + test(count == [locator getRequestCount]); + [[[communicator stringToProxy:@"test"] ice_locatorCacheTimeout:1] ice_ping]; // 1s timeout + test(count == [locator getRequestCount]); + [NSThread sleepForTimeInterval:1.2]; + [[[communicator stringToProxy:@"test"] ice_locatorCacheTimeout:1] ice_ping]; // 1s timeout + count += 2; + test(count == [locator getRequestCount]); + + [[[communicator stringToProxy:@"test@TestAdapter"] ice_locatorCacheTimeout:-1] ice_ping]; + test(count == [locator getRequestCount]); + [[[communicator stringToProxy:@"test"] ice_locatorCacheTimeout:-1] ice_ping]; + test(count == [locator getRequestCount]); + [[communicator stringToProxy:@"test@TestAdapter"] ice_ping]; + test(count == [locator getRequestCount]); + [[communicator stringToProxy:@"test"] ice_ping]; + test(count == [locator getRequestCount]); + + test([[[communicator stringToProxy:@"test"] ice_locatorCacheTimeout:99] ice_getLocatorCacheTimeout] == 99); + + tprintf("ok\n"); + + tprintf("testing proxy from server... "); + id<TestLocationHelloPrx> hello = [obj getHello]; + test([[hello ice_getAdapterId] isEqualToString:@"TestAdapter"]); + [hello sayHello]; + hello = [obj getReplicatedHello]; + test([[hello ice_getAdapterId] isEqualToString:@"ReplicatedAdapter"]); + [hello sayHello]; + tprintf("ok\n"); + + tprintf("testing well-known object locator cache... "); + + [registry addObject:[communicator stringToProxy:@"test3@TestUnknown"]]; + @try + { + [[communicator stringToProxy:@"test3"] ice_ping]; + test(NO); + } + @catch(ICENotRegisteredException* ex) + { + test([ex.kindOfObject isEqualToString:@"object adapter"]); + test([ex.id_ isEqualToString:@"TestUnknown"]); + } + [registry addObject:[communicator stringToProxy:@"test3@TestAdapter4"]]; // Update + [registry setAdapterDirectProxy:@"TestAdapter4" proxy:[communicator stringToProxy:@"dummy:tcp"]]; + @try + { + [[communicator stringToProxy:@"test3"] ice_ping]; + test(NO); + } + @catch(ICELocalException* ex) + { + } + [registry setAdapterDirectProxy:@"TestAdapter4" proxy:[locator findAdapterById:@"TestAdapter"]]; + @try + { + [[communicator stringToProxy:@"test3"] ice_ping]; + } + @catch(ICELocalException* ex) + { + test(NO); + } + + [registry setAdapterDirectProxy:@"TestAdapter4" proxy:[communicator stringToProxy:@"dummy:tcp"]]; + @try + { + [[communicator stringToProxy:@"test3"] ice_ping]; + } + @catch(ICELocalException* ex) + { + test(NO); + } + + @try + { + [[[communicator stringToProxy:@"test@TestAdapter4"] ice_locatorCacheTimeout:0] ice_ping]; + test(NO); + } + @catch(ICELocalException* ex) + { + } + @try + { + [[communicator stringToProxy:@"test@TestAdapter4"] ice_ping]; + test(NO); + } + @catch(ICELocalException* ex) + { + } + @try + { + [[communicator stringToProxy:@"test3"] ice_ping]; + test(NO); + } + @catch(ICELocalException* ex) + { + } + [registry addObject:[communicator stringToProxy:@"test3@TestAdapter"]]; + @try + { + [[communicator stringToProxy:@"test3"] ice_ping]; + } + @catch(ICELocalException* ex) + { + test(NO); + } + + [registry addObject:[communicator stringToProxy:@"test4"]]; + @try + { + [[communicator stringToProxy:@"test4"] ice_ping]; + test(NO); + } + @catch(ICENoEndpointException* ex) + { + } + tprintf("ok\n"); + + tprintf("testing proxy from server after shutdown... "); + [obj shutdown]; + [manager startServer]; + [hello sayHello]; + tprintf("ok\n"); + + tprintf("testing object migration... "); + hello = [TestLocationHelloPrx checkedCast:[communicator stringToProxy:@"hello"]]; + [obj migrateHello]; + [hello sayHello]; + [obj migrateHello]; + [hello sayHello]; + [obj migrateHello]; + [hello sayHello]; + tprintf("ok\n"); + + tprintf("testing locator encoding resolution... "); + hello = [TestLocationHelloPrx checkedCast:[communicator stringToProxy:@"hello"]]; + count = [locator getRequestCount]; + [[[communicator stringToProxy:@"test@TestAdapter"] ice_encodingVersion:ICEEncoding_1_1] ice_ping]; + test(count == [locator getRequestCount]); + [[[communicator stringToProxy:@"test@TestAdapter10"] ice_encodingVersion:ICEEncoding_1_0] ice_ping]; + test(++count == [locator getRequestCount]); + [[communicator stringToProxy:@"test -e 1.0@TestAdapter10-2"] ice_ping]; + test(++count == [locator getRequestCount]); + tprintf("ok\n"); + + tprintf("shutdown server... "); + [obj shutdown]; + tprintf("ok\n"); + + tprintf("testing whether server is gone... "); + @try + { + [obj2 ice_ping]; + test(NO); + } + @catch(ICELocalException*) + { + } + @try + { + [obj3 ice_ping]; + test(NO); + } + @catch(ICELocalException*) + { + } + @try + { + [obj5 ice_ping]; + test(NO); + } + @catch(ICELocalException*) + { + } + tprintf("ok\n"); + +// tprintf("testing indirect proxies to collocated objects... "); +// // +// // Set up test for calling a collocated object through an indirect, adapterless reference. +// // +// id<ICEProperties> properties = [communicator getProperties]; +// [properties setProperty:@"Ice.PrintAdapterReady" value:@"0"]; +// id<ICEObjectAdapter> adapter = [communicator createObjectAdapterWithEndpoints:@"Hello" endpoints:@"default"]; +// [adapter setLocator:locator]; + +// id<TestLocationTestLocatorRegistryPrx> registry = [TestLocationTestLocatorRegistryPrx checkedCast:[locator getRegistry]]; +// test(registry); + +// ICEIdentity* ident = [ICEIdentity identity:[ICEUtil generateUUID] category:@""]; +// [registry addObject:[adapter add:[[DummyHelloI alloc] init] identity:ident]]; +// [adapter activate]; + +// @try +// { +// id<TestLocationHelloPrx> helloPrx = [TestLocationHelloPrx checkedCast:[communicator stringToProxy: +// [communicator identityToString:ident]]]; +// [helloPrx ice_getConnection]; +// test(NO); +// } +// @catch(ICECollocationOptimizationException*) +// { +// } +// [adapter deactivate]; +// tprintf("ok\n"); + + tprintf("shutdown server manager... "); + [manager shutdown]; + tprintf("ok\n"); +} diff --git a/objc/test/Ice/location/Client.m b/objc/test/Ice/location/Client.m new file mode 100644 index 00000000000..f39de979383 --- /dev/null +++ b/objc/test/Ice/location/Client.m @@ -0,0 +1,78 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <LocationTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + void locationAllTests(id<ICECommunicator>, NSString*); + locationAllTests(communicator, @"ServerManager:default -p 12010"); + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main locationClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); + [initData.properties setProperty:@"Ice.Default.Locator" value:@"locator:default -p 12010"]; +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestLocation", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/location/LocationTest.ice b/objc/test/Ice/location/LocationTest.ice new file mode 100644 index 00000000000..02ed275861d --- /dev/null +++ b/objc/test/Ice/location/LocationTest.ice @@ -0,0 +1,56 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Ice/Locator.ice> + +["objc:prefix:TestLocation"] +module Test +{ + +interface TestLocatorRegistry extends ::Ice::LocatorRegistry +{ + // + // Allow remote addition of objects to the locator registry. + // + void addObject(Object* obj); +}; + +interface TestLocator extends ::Ice::Locator +{ + // + // Returns the number of request on the locator interface. + // + ["cpp:const"] idempotent int getRequestCount(); +}; + +interface ServerManager +{ + void startServer(); + void shutdown(); +}; + +interface Hello +{ + void sayHello(); +}; + +interface TestIntf +{ + void shutdown(); + + Hello* getHello(); + + Hello* getReplicatedHello(); + + void migrateHello(); +}; + +}; diff --git a/objc/test/Ice/location/Makefile b/objc/test/Ice/location/Makefile new file mode 100644 index 00000000000..2794d0a627f --- /dev/null +++ b/objc/test/Ice/location/Makefile @@ -0,0 +1,38 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = LocationTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + ServerLocator.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/location/Server.m b/objc/test/Ice/location/Server.m new file mode 100644 index 00000000000..7436a6ea25e --- /dev/null +++ b/objc/test/Ice/location/Server.m @@ -0,0 +1,113 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <location/ServerLocator.h> +#import <location/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator, ICEInitializationData* initData) +{ + // + // Register the server manager. The server manager creates a new + // 'server' (a server isn't a different process, it's just a new + // communicator and object adapter). + // + [[communicator getProperties] setProperty:@"Ice.ThreadPool.Server.Size" value:@"2"]; + [[communicator getProperties] setProperty:@"ServerManager.Endpoints" value:@"default -p 12010:udp"]; + + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"ServerManager"]; + + // + // We also register a sample server locator which implements the + // locator interface, this locator is used by the clients and the + // 'servers' created with the server manager interface. + // +#if defined(__clang__) && !__has_feature(objc_arc) + ServerLocatorRegistry* registry = [[[ServerLocatorRegistry alloc] init] autorelease]; + ServerManagerI* serverManager = [[[ServerManagerI alloc] init:registry initData:initData] autorelease]; +#else + ServerLocatorRegistry* registry = [[ServerLocatorRegistry alloc] init]; + ServerManagerI* serverManager = [[ServerManagerI alloc] init:registry initData:initData]; +#endif + [registry addObject:[adapter createProxy:[communicator stringToIdentity:@"ServerManager"]]]; + [adapter add:serverManager identity:[communicator stringToIdentity:@"ServerManager"]]; + + id<ICELocatorRegistryPrx> registryPrx = + [ICELocatorRegistryPrx uncheckedCast:[adapter add:registry + identity:[communicator stringToIdentity:@"registry"]]]; + +#if defined(__clang__) && !__has_feature(objc_arc) + ServerLocator* locator = [[[ServerLocator alloc] init:registry proxy:registryPrx] autorelease]; +#else + ServerLocator* locator = [[ServerLocator alloc] init:registry proxy:registryPrx]; +#endif + [adapter add:locator identity:[communicator stringToIdentity:@"locator"]]; + + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + [serverManager terminate]; + + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main locationServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestLocation", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator, initData); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/location/ServerLocator.h b/objc/test/Ice/location/ServerLocator.h new file mode 100644 index 00000000000..9f830f829dd --- /dev/null +++ b/objc/test/Ice/location/ServerLocator.h @@ -0,0 +1,29 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <LocationTest.h> + +@interface ServerLocatorRegistry : TestLocationTestLocatorRegistry<TestLocationTestLocatorRegistry> +{ + NSMutableDictionary* adapters_; + NSMutableDictionary* objects_; +} +-(id<ICEObjectPrx>) getAdapter:(NSString*)adapterId; +-(id<ICEObjectPrx>) getObject:(ICEIdentity*)ident; +-(void) addObject:(id<ICEObjectPrx>)prx; +@end + +@interface ServerLocator : TestLocationTestLocator<TestLocationTestLocator> +{ + ServerLocatorRegistry* registry_; + id<ICELocatorRegistryPrx> registryPrx_; + int requestCount_; +} +-(id) init:(ServerLocatorRegistry*)registry proxy:(id<ICELocatorRegistryPrx>)proxy; +@end diff --git a/objc/test/Ice/location/ServerLocator.m b/objc/test/Ice/location/ServerLocator.m new file mode 100644 index 00000000000..5e7e146a105 --- /dev/null +++ b/objc/test/Ice/location/ServerLocator.m @@ -0,0 +1,129 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <location/ServerLocator.h> + +@implementation ServerLocatorRegistry +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + adapters_ = [[NSMutableDictionary alloc] init]; + objects_ = [[NSMutableDictionary alloc] init]; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [adapters_ release]; + [objects_ release]; + [super dealloc]; +} +#endif + +-(void) setAdapterDirectProxy:(NSMutableString *)adapter proxy:(id<ICEObjectPrx>)proxy current:(ICECurrent *)current +{ + if(proxy == nil) + { + [adapters_ removeObjectForKey:adapter]; + } + else + { + [adapters_ setObject:proxy forKey:adapter]; + } +} +-(void) setReplicatedAdapterDirectProxy:(NSMutableString *)adapterId + replicaGroupId:(NSMutableString *)replicaGroupId + p:(id<ICEObjectPrx>)p + current:(ICECurrent *)current +{ + if(p == nil) + { + [adapters_ removeObjectForKey:adapterId]; + [adapters_ removeObjectForKey:replicaGroupId]; + } + else + { + [adapters_ setObject:p forKey:adapterId]; + [adapters_ setObject:p forKey:replicaGroupId]; + } +} +-(void) setServerProcessProxy:(NSMutableString *)id_ proxy:(id<ICEProcessPrx>)proxy current:(ICECurrent *)current +{ +} +-(void) addObject:(id<ICEObjectPrx>)object current:(ICECurrent*)current +{ + [self addObject:object]; +} +-(id<ICEObjectPrx>) getAdapter:(NSString*)adapterId +{ + id<ICEObjectPrx> proxy = [adapters_ objectForKey:adapterId]; + if(proxy == nil) + { + @throw [ICEAdapterNotFoundException adapterNotFoundException]; + } + return proxy; +} +-(id<ICEObjectPrx>) getObject:(ICEIdentity*)ident +{ + id<ICEObjectPrx> proxy = [objects_ objectForKey:ident]; + if(proxy == nil) + { + @throw [ICEObjectNotFoundException objectNotFoundException]; + } + return proxy; +} +-(void) addObject:(id<ICEObjectPrx>)object +{ + [objects_ setObject:object forKey:[object ice_getIdentity]]; +} +@end + +@implementation ServerLocator +-(id) init:(ServerLocatorRegistry*)registry proxy:(id<ICELocatorRegistryPrx>)registryPrx +{ + self = [super init]; + if(!self) + { + return nil; + } + registry_ = registry; + registryPrx_ = registryPrx; + requestCount_ = 0; + return self; +} +-(id<ICEObjectPrx>) findObjectById:(ICEIdentity *)id_ current:(ICECurrent *)current +{ + ++requestCount_; + return [registry_ getObject:id_]; +} +-(id<ICEObjectPrx>) findAdapterById:(NSMutableString *)id_ current:(ICECurrent *)current +{ + ++requestCount_; + if([id_ isEqualToString:@"TestAdapter10"] || [id_ isEqualToString:@"TestAdapter10-2"]) + { + NSAssert([current.encoding isEqual:ICEEncoding_1_0], @"unexpected encoding"); + return [registry_ getAdapter:@"TestAdapter"]; + } + return [registry_ getAdapter:id_]; +} +-(id<ICELocatorRegistryPrx>) getRegistry:(ICECurrent *)current +{ + return registryPrx_; +} +-(int) getRequestCount:(ICECurrent*)current +{ + return requestCount_; +} +@end diff --git a/objc/test/Ice/location/TestI.h b/objc/test/Ice/location/TestI.h new file mode 100644 index 00000000000..2f96f71e092 --- /dev/null +++ b/objc/test/Ice/location/TestI.h @@ -0,0 +1,34 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <LocationTest.h> +#import <location/ServerLocator.h> + +@interface ServerManagerI : TestLocationServerManager<TestLocationServerManager> +{ + NSMutableArray* communicators_; + ServerLocatorRegistry* registry_; + ICEInitializationData* initData_; +} +-(id)init:(ServerLocatorRegistry*)registry initData:(ICEInitializationData*)d; + +-(void)terminate; +@end + +@interface HelloI : TestLocationHello<TestLocationHello> +@end + +@interface TestLocationI : TestLocationTestIntf<TestLocationTestIntf> +{ + id<ICEObjectAdapter> adapter1_; + id<ICEObjectAdapter> adapter2_; + ServerLocatorRegistry* registry_; +} +-(id) init:(id<ICEObjectAdapter>)adapter1 adapter2:(id<ICEObjectAdapter>)adpt2 registry:(ServerLocatorRegistry*)r; +@end diff --git a/objc/test/Ice/location/TestI.m b/objc/test/Ice/location/TestI.m new file mode 100644 index 00000000000..ba32fa0c9fe --- /dev/null +++ b/objc/test/Ice/location/TestI.m @@ -0,0 +1,176 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <location/TestI.h> + +@implementation ServerManagerI +-(id) init:(ServerLocatorRegistry*)registry initData:(ICEInitializationData*)initData +{ + self = [super init]; + if(!self) + { + return nil; + } + registry_ = registry; + initData_ = initData; + + [initData_.properties setProperty:@"TestAdapter.Endpoints" value:@"default"]; + [initData_.properties setProperty:@"TestAdapter.AdapterId" value:@"TestAdapter"]; + [initData_.properties setProperty:@"TestAdapter.ReplicaGroupId" value:@"ReplicatedAdapter"]; + + [initData_.properties setProperty:@"TestAdapter2.Endpoints" value:@"default"]; + [initData_.properties setProperty:@"TestAdapter2.AdapterId" value:@"TestAdapter2"]; + + [initData_.properties setProperty:@"Ice.PrintAdapterReady" value:@"0"]; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [communicators_ release]; + [super dealloc]; +} +#endif + +-(void) startServer:(ICECurrent*)current +{ + for(id<ICECommunicator> c in communicators_) + { + [c waitForShutdown]; + [c destroy]; + } +#if defined(__clang__) && !__has_feature(objc_arc) + [communicators_ release]; +#endif + communicators_ = [[NSMutableArray alloc] init]; + + // + // Simulate a server: create a [[communicator alloc] init] and object + // adapter. The object adapter is started on a system allocated + // port. The configuration used here contains the Ice.Locator + // configuration variable. The [[object alloc] init] adapter will register + // its endpoints with the locator and create references containing + // the adapter id instead of the endpoints. + // + + id<ICECommunicator> serverCommunicator = [ICEUtil createCommunicator:initData_]; + [communicators_ addObject:serverCommunicator]; + + id<ICEObjectAdapter> adapter = [serverCommunicator createObjectAdapter:@"TestAdapter"]; + id<ICEObjectAdapter> adapter2 = [serverCommunicator createObjectAdapter:@"TestAdapter2"]; + + id<ICEObjectPrx> locator = [serverCommunicator stringToProxy:@"locator:default -p 12010"]; + [adapter setLocator:[ICELocatorPrx uncheckedCast:locator]]; + [adapter2 setLocator:[ICELocatorPrx uncheckedCast:locator]]; + +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* object = [[[TestLocationI alloc] init:adapter adapter2:adapter2 registry:registry_] autorelease]; +#else + ICEObject* object = [[TestLocationI alloc] init:adapter adapter2:adapter2 registry:registry_]; +#endif + [registry_ addObject:[adapter add:object identity:[serverCommunicator stringToIdentity:@"test"]]]; + [registry_ addObject:[adapter add:object identity:[serverCommunicator stringToIdentity:@"test2"]]]; + [adapter add:object identity:[serverCommunicator stringToIdentity:@"test3"]]; + + [adapter activate]; + [adapter2 activate]; +} + +-(void) shutdown:(ICECurrent*)current +{ + for(id<ICECommunicator> c in communicators_) + { + [c destroy]; + } + [communicators_ removeAllObjects]; + [[current.adapter getCommunicator] shutdown]; +} + +-(void) terminate +{ + for(id<ICECommunicator> c in communicators_) + { + [c destroy]; + } + [communicators_ removeAllObjects]; +} +@end + +@implementation TestLocationI +-(id) init:(id<ICEObjectAdapter>)adapter + adapter2:(id<ICEObjectAdapter>)adapter2 + registry:(ServerLocatorRegistry*)registry +{ + self = [super init]; + if(!self) + { + return nil; + } +#if defined(__clang__) && !__has_feature(objc_arc) + adapter1_ = [adapter retain]; + adapter2_ = [adapter2 retain]; + registry_ = registry; + [registry_ addObject:[adapter1_ add:[[[HelloI alloc] init] autorelease] + identity:[[adapter1_ getCommunicator] stringToIdentity:@"hello"]]]; +#else + adapter1_ = adapter; + adapter2_ = adapter2; + registry_ = registry; + [registry_ addObject:[adapter1_ add:[[HelloI alloc] init] + identity:[[adapter1_ getCommunicator] stringToIdentity:@"hello"]]]; +#endif + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [adapter1_ release]; + [adapter2_ release]; + [super dealloc]; +} +#endif + +-(void) shutdown:(ICECurrent*)current +{ + [[adapter1_ getCommunicator] shutdown]; +} + +-(id<TestLocationHelloPrx>) getHello:(ICECurrent*)current +{ + return [TestLocationHelloPrx uncheckedCast:[adapter1_ createIndirectProxy:[[adapter1_ getCommunicator] + stringToIdentity:@"hello"]]]; +} + +-(id<TestLocationHelloPrx>) getReplicatedHello:(ICECurrent*)current +{ + return [TestLocationHelloPrx uncheckedCast:[adapter1_ createProxy:[[adapter1_ getCommunicator] stringToIdentity:@"hello"]]]; +} + +-(void) migrateHello:(ICECurrent*)current +{ + ICEIdentity* ident = [[adapter1_ getCommunicator] stringToIdentity:@"hello"]; + @try + { + [registry_ addObject:[adapter2_ add:[adapter1_ remove:ident] identity:ident]]; + } + @catch(ICENotRegisteredException*) + { + [registry_ addObject:[adapter1_ add:[adapter2_ remove:ident] identity:ident]]; + } +} +@end + +@implementation HelloI +-(void) sayHello:(ICECurrent*)current +{ +} +@end diff --git a/objc/test/Ice/location/run.py b/objc/test/Ice/location/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/location/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/metrics/.gitignore b/objc/test/Ice/metrics/.gitignore new file mode 100644 index 00000000000..919d41acc0f --- /dev/null +++ b/objc/test/Ice/metrics/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +MetricsTest.m +MetricsTest.h diff --git a/objc/test/Ice/metrics/AllTests.m b/objc/test/Ice/metrics/AllTests.m new file mode 100644 index 00000000000..4bd1f1a0301 --- /dev/null +++ b/objc/test/Ice/metrics/AllTests.m @@ -0,0 +1,1192 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <MetricsTest.h> + +#import <Foundation/Foundation.h> + +@interface UpdateCallbackI : ICEPropertiesAdminUpdateCallback<ICEPropertiesAdminUpdateCallback> +{ +@private +BOOL updated; +id<ICEPropertiesAdminPrx> serverProps; +NSCondition* cond; +} +-(id) initWithServerProps:(id<ICEPropertiesAdminPrx>)serverProps; +-(void) waitForUpdate; +-(void) updated:(ICEMutablePropertyDict*)properties; +@end + +@implementation UpdateCallbackI +-(id) initWithServerProps:(id<ICEPropertiesAdminPrx>)serverProps_ +{ + self = [super init]; + if(self) + { +#if defined(__clang__) && !__has_feature(objc_arc) + self->serverProps = [serverProps_ retain]; +#else + self->serverProps = serverProps_; +#endif + self->cond = [[NSCondition alloc] init]; + } + return self; +} + +-(void) waitForUpdate +{ + [cond lock]; + while(!updated) + { + [cond wait]; + } + // Ensure that the previous updates were committed, the setProperties call returns before + // notifying the callbacks so to ensure all the update callbacks have be notified we call + // a second time, this will block until all the notifications from the first update have + // completed. + [serverProps setProperties:[ICEPropertyDict dictionary]]; + updated = NO; + [cond unlock]; +} + +-(void) updated:(ICEMutablePropertyDict*)properties +{ + [cond lock]; + updated = YES; + [cond signal]; + [cond unlock]; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [serverProps release]; + [cond release]; + [super dealloc]; +} +#endif +@end + +@interface Callback : NSObject +{ +BOOL wait; +NSCondition* cond; +} + +-(id) init; ++(id) callback; + +-(void) response; +-(void) exception:(ICEException*)exception; +-(void) waitForResponse; +@end + +@implementation Callback +-(id) init +{ + self = [super init]; + if(self) + { + wait = true; + cond = [[NSCondition alloc] init]; + } + return self; +} + ++(id) callback +{ +#if defined(__clang__) && !__has_feature(objc_arc) + return [[[Callback alloc] init] autorelease]; +#else + return [[Callback alloc] init]; +#endif +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [super dealloc]; +} +#endif + +-(void) response +{ + [cond lock]; + wait = false; + [cond signal]; + [cond unlock]; +} + +-(void) exception:(ICEException*)exception +{ + [self response]; +} + +-(void) waitForResponse +{ + [cond lock]; + while(wait) + { + [cond wait]; + } + wait = true; + [cond unlock]; +} +@end + +@interface Operation : NSObject +{ +@protected + ICEObjectPrx* proxy; +} +-(id) init:(ICEObjectPrx*)proxy_; +@end + +@implementation Operation +-(id) init:(ICEObjectPrx*)proxy_ +{ + self = [super init]; + if(self) + { +#if defined(__clang__) && !__has_feature(objc_arc) + self->proxy = [proxy_ retain]; +#else + self->proxy = proxy_; +#endif + } + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [self->proxy release]; + [super dealloc]; +} +#endif +@end + +@interface Connect : Operation +-(id) init:(ICEObjectPrx*)proxy_; ++(id) connect:(ICEObjectPrx*)proxy_; +-(void) run; +@end + +@implementation Connect +-(id) init:(ICEObjectPrx*)proxy_ +{ + self = [super init:proxy_]; + return self; +} + ++(id) connect:(ICEObjectPrx*)proxy_ +{ +#if defined(__clang__) && !__has_feature(objc_arc) + return [[[Connect alloc] init:proxy_] autorelease]; +#else + return [[Connect alloc] init:proxy_]; +#endif +} + +-(void) run +{ + if([proxy ice_getCachedConnection]) + { + [[proxy ice_getCachedConnection] close:NO]; + } + @try + { + [proxy ice_ping]; + } + @catch(ICELocalException*) + { + } + if([proxy ice_getCachedConnection]) + { + [[proxy ice_getCachedConnection] close:NO]; + } +} +@end + + +@interface InvokeOp : Operation +-(id) init:(ICEObjectPrx*)proxy_; ++(id) invokeOp:(ICEObjectPrx*)proxy_; +-(void) run; +@end + +@implementation InvokeOp +-(id) init:(ICEObjectPrx*)proxy_ +{ + self = [super init:proxy_]; + return self; +} + ++(id) invokeOp:(ICEObjectPrx*)proxy_ +{ +#if defined(__clang__) && !__has_feature(objc_arc) + return [[[InvokeOp alloc] init:proxy_] autorelease]; +#else + return [[InvokeOp alloc] init:proxy_]; +#endif +} + +-(void) run +{ + ICEMutableContext* ctx = [ICEMutableContext dictionary]; + [ctx setObject:@"test" forKey:@"entry1"]; + [ctx setObject:@"" forKey:@"entry2"]; + TestMetricsMetricsPrx* metrics = [TestMetricsMetricsPrx uncheckedCast:proxy]; + [metrics op:ctx]; +} +@end + +void +waitForCurrent(ICEMXMetricsAdminPrx* metrics, NSString* viewName, NSString* map, int value) +{ + while(true) + { + ICELong timestamp; + ICEMXMetricsView* view = [metrics getMetricsView:viewName timestamp:×tamp]; + test([view objectForKey:map] != nil); + + bool ok = true; + ICEMXMetricsMap* mmap = [view objectForKey:map]; + for(ICEMXMetrics* m in mmap) + { + if(m.current != value) + { + ok = false; + break; + } + } + + if(ok) + { + break; + } + [NSThread sleepForTimeInterval:50 / 1000.0]; + } +} + +ICEMutablePropertyDict* +getClientProps(id<ICEPropertiesAdminPrx> p, ICEMutablePropertyDict* orig, NSString* m) +{ + ICEMutablePropertyDict* props = [p getPropertiesForPrefix:@"IceMX.Metrics"]; +#if defined(__clang__) && !__has_feature(objc_arc) + ICEPropertyDict* cprops = [[props copy] autorelease]; +#else + ICEPropertyDict* cprops = [props copy]; +#endif + [cprops enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + [props setObject:@"" forKey:key]; + }]; + + [orig enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + [props setObject:obj forKey:key]; + }]; + + NSString* map = @""; + if(![m isEqualToString:@""]) + { + map = [map stringByAppendingFormat:@"Map.%@.", m]; + } + [props setObject:@"Ice\\.Admin" + forKey:[NSString stringWithFormat:@"IceMX.Metrics.View.%@Reject.parent", map]]; + + [props setObject:@"12010" + forKey:[NSString stringWithFormat:@"IceMX.Metrics.View.%@Accept.endpointPort", map] ]; + + [props setObject:@".*/admin|controller" + forKey:[NSString stringWithFormat:@"IceMX.Metrics.View.%@Reject.identity", map]]; + return props; +} + +ICEMutablePropertyDict* +getServerProps(id<ICEPropertiesAdminPrx> p, ICEMutablePropertyDict* orig, NSString* m) +{ + ICEMutablePropertyDict* props = [p getPropertiesForPrefix:@"IceMX.Metrics"]; +#if defined(__clang__) && !__has_feature(objc_arc) + ICEPropertyDict* sprops = [[props copy] autorelease]; +#else + ICEPropertyDict* sprops = [props copy]; +#endif + [sprops enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + [props setObject:@"" forKey:key]; + }]; + + [orig enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + [props setObject:obj forKey:key]; + }]; + + NSString* map = @""; + if(![m isEqualToString:@""]) + { + map = [map stringByAppendingFormat:@"Map.%@.", m]; + } + [props setObject:@"Ice\\.Admin|Controller" + forKey:[NSString stringWithFormat:@"IceMX.Metrics.View.%@Reject.parent", map]]; + + [props setObject:@"12010" + forKey:[NSString stringWithFormat:@"IceMX.Metrics.View.%@Accept.endpointPort", map]]; + + [props setObject:@".*/admin|controller" + forKey:[NSString stringWithFormat:@"IceMX.Metrics.View.%@Reject.identity", map]]; + return props; +} + +ICEMXConnectionMetrics* +getServerConnectionMetrics(ICEMXMetricsAdminPrx* metrics, ICELong expected) +{ + ICEMXConnectionMetrics* s; + int nRetry = 30; + ICELong timestamp; + s = (ICEMXConnectionMetrics*) + [[[metrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] objectAtIndex:0]; + while(s.sentBytes != expected && nRetry-- > 0) + { + // On some platforms, it's necessary to wait a little before obtaining the server metrics + // to get an accurate sentBytes metric. The sentBytes metric is updated before the response + // to the operation is sent and getMetricsView can be dispatched before the metric is really + // updated. + [NSThread sleepForTimeInterval:100 / 1000.0]; + s = (ICEMXConnectionMetrics*) + [[[metrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] objectAtIndex:0]; + } + return s; +} + +void +updateProps(id<ICEPropertiesAdminPrx> cprops, + id<ICEPropertiesAdminPrx> sprops, + UpdateCallbackI* callback, + ICEMutablePropertyDict* props, + NSString* map) +{ + [cprops setProperties:getClientProps(cprops, props, map)]; + [sprops setProperties:getServerProps(sprops, props, map)]; + [callback waitForUpdate]; +} + +void +testAttribute(ICEMXMetricsAdminPrx* metrics, + ICEPropertiesAdminPrx* props, + UpdateCallbackI* update, + NSString* map, + NSString* attr, + NSString* value, + id func) +{ + ICEMutablePropertyDict* dict = [ICEMutablePropertyDict dictionary]; + [dict setObject:attr forKey:[NSString stringWithFormat:@"IceMX.Metrics.View.Map.%@.GroupBy", map]]; + if([[props ice_getIdentity].category isEqualToString:@"client"]) + { + [props setProperties:getClientProps(props, dict, map)]; + [update waitForUpdate]; + } + else + { + [props setProperties:getServerProps(props, dict, map)]; + [props setProperties:[ICEPropertyDict dictionary]]; + } + [func run]; + ICELong timestamp; + ICEMXMetricsView* view = [metrics getMetricsView:@"View" timestamp:×tamp]; + if([view objectForKey:map] == nil || [[view objectForKey:map] count] == 0) + { + if(![value isEqualToString:@""]) + { + test(NO); + } + } + else if([[view objectForKey:map] count] != 1 || + ![((ICEMXMetrics*)[[view objectForKey:map] objectAtIndex:0]).id_ isEqualToString:value]) + { + test(NO); + } + + [dict removeAllObjects]; + if([[props ice_getIdentity].category isEqualToString:@"client"]) + { + [props setProperties:getClientProps(props, dict, map)]; + [update waitForUpdate]; + } + else + { + [props setProperties:getServerProps(props, dict, map)]; +#if defined(__clang__) && !__has_feature(objc_arc) + [props setProperties:[ICEPropertyDict dictionary]]; +#else + [props setProperties:[ICEPropertyDict dictionary]]; +#endif + } +} + +void +clearView(ICEPropertiesAdminPrx* cprops, ICEPropertiesAdminPrx* sprops, UpdateCallbackI* callback) +{ + ICEMutablePropertyDict* dict = [cprops getPropertiesForPrefix:@"IceMX.Metrics"]; + [dict setObject:@"1" forKey:@"IceMX.Metrics.View.Disabled"]; + [cprops setProperties:dict]; + + dict = [sprops getPropertiesForPrefix:@"IceMX.Metrics"]; + [dict setObject:@"1" forKey:@"IceMX.Metrics.View.Disabled"]; + [sprops setProperties:dict]; + + [callback waitForUpdate]; + + dict = [cprops getPropertiesForPrefix:@"IceMX.Metrics"]; + [dict setObject:@"" forKey:@"IceMX.Metrics.View.Disabled"]; + [cprops setProperties:dict]; + + dict = [sprops getPropertiesForPrefix:@"IceMX.Metrics"]; + [dict setObject:@"" forKey:@"IceMX.Metrics.View.Disabled"]; + [sprops setProperties:dict]; + + [callback waitForUpdate]; +} + +void +checkFailure(ICEMXMetricsAdminPrx* m, NSString* map, NSString* id_, NSString* failure, int count) +{ + ICEMXMetricsFailures* f = [m getMetricsFailures:@"View" map:map id_:id_]; + if([f.failures objectForKey:failure] == nil) + { + NSLog(@"couldn't find failure `%@' for `%@'", failure, id_); + test(NO); + } + if(count > 0 && [[f.failures objectForKey:failure] intValue] != count) + { + NSLog(@"count for failure `%@' of `%@' is different from expected: ", failure, id_); + NSLog(@"%i != %@", count, [f.failures objectForKey:failure]); + test(NO); + } +} + +NSMutableDictionary* +toMap(ICEMXMetricsMap* mmap) +{ + NSMutableDictionary* m = [NSMutableDictionary dictionary]; + for(ICEMXMetrics* metrics in mmap) + { + [m setObject:metrics forKey:metrics.id_]; + } + return m; +} + +id<TestMetricsMetricsPrx> +metricsAllTests(id<ICECommunicator> communicator) +{ + id<TestMetricsMetricsPrx> metrics = [TestMetricsMetricsPrx checkedCast: + [communicator stringToProxy:@"metrics:default -p 12010"]]; + + tprintf("testing metrics admin facet checkedCast... "); + id<ICEObjectPrx> admin = [communicator getAdmin]; + id<ICEPropertiesAdminPrx> clientProps = [ICEPropertiesAdminPrx checkedCast:admin facet:@"Properties"]; + + id<ICEMXMetricsAdminPrx> clientMetrics = [ICEMXMetricsAdminPrx checkedCast:admin facet:@"Metrics"]; + test(clientProps && clientMetrics); + + admin = [metrics getAdmin]; + id<ICEPropertiesAdminPrx> serverProps = [ICEPropertiesAdminPrx checkedCast:admin facet:@"Properties"]; + id<ICEMXMetricsAdminPrx> serverMetrics = [ICEMXMetricsAdminPrx checkedCast:admin facet:@"Metrics"]; + test(serverProps && serverMetrics); + + UpdateCallbackI* update = [[UpdateCallbackI alloc] initWithServerProps:serverProps]; +#if defined(__clang__) && !__has_feature(objc_arc) + [update autorelease]; +#endif + id<ICENativePropertiesAdmin> nativePropertiesAdmin = + (id<ICENativePropertiesAdmin>)[communicator findAdminFacet:@"Properties"]; + [nativePropertiesAdmin addUpdateCallback:update]; + tprintf("ok\n"); + + ICEMutablePropertyDict* props = [ICEMutablePropertyDict dictionary]; + tprintf("testing group by none..."); + + [props setObject:@"none" forKey:@"IceMX.Metrics.View.GroupBy"]; + + updateProps(clientProps, serverProps, update, props, @""); + +#if !TARGET_OS_IPHONE + int threadCount = 4; +#else + int threadCount = 3; // No endpoint host resolver thread with iOS. +#endif + + ICELong timestamp = 0; + ICEMXMetricsView* view = [clientMetrics getMetricsView:@"View" timestamp:×tamp]; + + test([[view objectForKey:@"Connection"] count] == 1 && + [[[view objectForKey:@"Connection"] objectAtIndex:0] current] == 1 && + [[[view objectForKey:@"Connection"] objectAtIndex:0] total] == 1); + + test([[view objectForKey:@"Thread"] count] == 1); + test([[[view objectForKey:@"Thread"] objectAtIndex:0] current] == threadCount); + test([[[view objectForKey:@"Thread"] objectAtIndex:0] total] == threadCount); + + tprintf("ok\n"); + + tprintf("testing connection metrics... "); + + [props setObject:@"none" forKey:@"IceMX.Metrics.View.Map.Connection.GroupBy"]; + updateProps(clientProps, serverProps, update, props, @"Connection"); + + test([[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] count] == 1); + test([[[serverMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] count] == 1); + + [metrics ice_ping]; + + ICEMXConnectionMetrics *cm1, *sm1, *cm2, *sm2; + cm1 = (ICEMXConnectionMetrics*) + [[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] objectAtIndex:0]; + + sm1 = (ICEMXConnectionMetrics*) + [[[serverMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] objectAtIndex:0]; + + sm1 = getServerConnectionMetrics(serverMetrics, 25); + + test(cm1.total == 1 && sm1.total == 1); + + [metrics ice_ping]; + + cm2 = (ICEMXConnectionMetrics*) + [[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] objectAtIndex:0]; + sm2 = getServerConnectionMetrics(serverMetrics, 50); + + test(cm2.sentBytes - cm1.sentBytes == 45); // 45 for ice_ping request + test(cm2.receivedBytes - cm1.receivedBytes == 25); // 25 bytes for ice_ping response + test(sm2.receivedBytes - sm1.receivedBytes == 45); + test(sm2.sentBytes - sm1.sentBytes == 25); + + cm1 = cm2; + sm1 = sm2; + + TestMetricsMutableByteSeq* bs = [TestMetricsMutableByteSeq dataWithLength:0]; + [metrics opByteS:bs]; + + cm2 = (ICEMXConnectionMetrics*) + [[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] objectAtIndex:0]; + + sm2 = getServerConnectionMetrics(serverMetrics, sm1.sentBytes + cm2.receivedBytes - cm1.receivedBytes); + ICELong requestSz = cm2.sentBytes - cm1.sentBytes; + ICELong replySz = cm2.receivedBytes - cm1.receivedBytes; + + cm1 = cm2; + sm1 = sm2; + + [bs setLength:456]; + [metrics opByteS:bs]; + + cm2 = (ICEMXConnectionMetrics*) + [[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] objectAtIndex:0]; + sm2 = getServerConnectionMetrics(serverMetrics, sm1.sentBytes + replySz); + + // 4 is for the seq variable size + test(cm2.sentBytes - cm1.sentBytes == requestSz + [bs length] + 4); + test(cm2.receivedBytes - cm1.receivedBytes == replySz); + test(sm2.receivedBytes - sm1.receivedBytes == requestSz + [bs length] + 4); + test(sm2.sentBytes - sm1.sentBytes == replySz); + + cm1 = cm2; + sm1 = sm2; + + [bs setLength:(1024 * 1024 * 10)]; // Try with large amount of data which should be sent in several chunks + [metrics opByteS:bs]; + + cm2 = (ICEMXConnectionMetrics*) + [[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] objectAtIndex:0]; + sm2 = getServerConnectionMetrics(serverMetrics, sm1.sentBytes + replySz); + + // 4 is for the seq variable size + test(cm2.sentBytes - cm1.sentBytes == requestSz + [bs length] + 4); + test(cm2.receivedBytes - cm1.receivedBytes == replySz); + test(sm2.receivedBytes - sm1.receivedBytes == requestSz + [bs length] + 4); + test(sm2.sentBytes - sm1.sentBytes == replySz); + + [props setObject:@"state" forKey:@"IceMX.Metrics.View.Map.Connection.GroupBy"]; + updateProps(clientProps, serverProps, update, props, @"Connection"); + + NSMutableDictionary* map = + toMap([[serverMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"]); + + test([[map objectForKey:@"active"] current] == 1); + + TestMetricsControllerPrx* controller = + [TestMetricsControllerPrx checkedCast:[communicator stringToProxy:@"controller:default -p 12011"]]; + + [controller hold]; + + map = toMap([[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"]); + test([[map objectForKey:@"active"] current] == 1); + map = toMap([[serverMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"]); + test([[map objectForKey:@"holding"] current] == 1); + + [[metrics ice_getConnection] close:false]; + + map = toMap([[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"]); + test([[map objectForKey:@"closing"] current] == 1); + map = toMap([[serverMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"]); + test([[map objectForKey:@"holding"] current] == 1); + + [controller resume]; + + map = toMap([[serverMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"]); + test([[map objectForKey:@"holding"] current] == 0); + + [props setObject:@"none" forKey:@"IceMX.Metrics.View.Map.Connection.GroupBy"]; + updateProps(clientProps, serverProps, update, props, @"Connection"); + + [[metrics ice_getConnection] close:false]; + + [[metrics ice_timeout:500] ice_ping]; + [controller hold]; + @try + { + [[metrics ice_timeout:500] opByteS:[NSMutableData dataWithLength:10000000]]; + test(NO); + } + @catch(const ICETimeoutException*) + { + } + [controller resume]; + + cm1 = (ICEMXConnectionMetrics*) + [[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] objectAtIndex:0]; + while(true) + { + sm1 = (ICEMXConnectionMetrics*) + [[[serverMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Connection"] objectAtIndex:0]; + if(sm1.failures >= 2) + { + break; + } + [NSThread sleepForTimeInterval:10 / 1000.0]; + } + + test(cm1.failures == 2 && sm1.failures >= 1); + + checkFailure(clientMetrics, @"Connection", cm1.id_, @"Ice::TimeoutException", 1); + checkFailure(clientMetrics, @"Connection", cm1.id_, @"Ice::ConnectTimeoutException", 1); + checkFailure(serverMetrics, @"Connection", sm1.id_, @"Ice::ConnectionLostException", 0); + + ICEMXMetricsPrx* m = [[metrics ice_timeout:500] ice_connectionId:@"Con1"]; + [m ice_ping]; + + testAttribute(clientMetrics, clientProps, update, @"Connection", @"parent", @"Communicator", nil); + //testAttribute(clientMetrics, clientProps, update, "Connection", "id", ""); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"endpoint", @"tcp -h 127.0.0.1 -p 12010 -t 500", nil); + + testAttribute(clientMetrics, clientProps, update, @"Connection", @"endpointType", @"1", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"endpointIsDatagram", @"false", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"endpointIsSecure", @"false", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"endpointTimeout", @"500", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"endpointCompress", @"false", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"endpointHost", @"127.0.0.1", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"endpointPort", @"12010", nil); + + testAttribute(clientMetrics, clientProps, update, @"Connection", @"incoming", @"false", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"adapterName", @"", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"connectionId", @"Con1", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"localHost", @"127.0.0.1", nil); + //testAttribute(clientMetrics, clientProps, update, "Connection", "localPort", ""); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"remoteHost", @"127.0.0.1", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"remotePort", @"12010", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"mcastHost", @"", nil); + testAttribute(clientMetrics, clientProps, update, @"Connection", @"mcastPort", @"", nil); + + [[m ice_getConnection] close:false]; + + waitForCurrent(clientMetrics, @"View", @"Connection", 0); + waitForCurrent(serverMetrics, @"View", @"Connection", 0); + + tprintf("ok\n"); + + tprintf("testing connection establishment metrics... "); + + [props setObject:@"id" forKey:@"IceMX.Metrics.View.Map.ConnectionEstablishment.GroupBy"]; + updateProps(clientProps, serverProps, update, props, @"ConnectionEstablishment"); + test([[[clientMetrics getMetricsView:@"View" timestamp:×tamp] + objectForKey:@"ConnectionEstablishment"] count] == 0); + + [metrics ice_ping]; + + test([[[clientMetrics getMetricsView:@"View" timestamp:×tamp] + objectForKey:@"ConnectionEstablishment"] count] == 1); + ICEMXMetrics* m1 = [[[clientMetrics getMetricsView:@"View" timestamp:×tamp] + objectForKey:@"ConnectionEstablishment"] objectAtIndex:0]; + + test(m1.current == 0 && m1.total == 1 && [m1.id_ isEqualToString:@"127.0.0.1:12010"]); + + [[metrics ice_getConnection] close:NO]; + [controller hold]; + @try + { + [[[communicator stringToProxy:@"test:tcp -p 12010 -h 127.0.0.1"] ice_timeout:10] ice_ping]; + test(NO); + } + @catch(ICEConnectTimeoutException*) + { + } + @catch(const ICELocalException*) + { + test(NO); + } + [controller resume]; + test([[[clientMetrics getMetricsView:@"View" timestamp:×tamp] + objectForKey:@"ConnectionEstablishment"] count] == 1); + m1 = [[[clientMetrics getMetricsView:@"View" timestamp:×tamp] + objectForKey:@"ConnectionEstablishment"] objectAtIndex:0]; + test([m1.id_ isEqualToString:@"127.0.0.1:12010"] && m1.total == 3 && m1.failures == 2); + + checkFailure(clientMetrics, @"ConnectionEstablishment", m1.id_, @"Ice::ConnectTimeoutException", 2); + + Connect* c = [Connect connect:metrics]; + + testAttribute(clientMetrics, clientProps, update, @"ConnectionEstablishment", @"parent", @"Communicator", c); + testAttribute(clientMetrics, clientProps, update, @"ConnectionEstablishment", @"id", @"127.0.0.1:12010", c); + testAttribute(clientMetrics, clientProps, update, @"ConnectionEstablishment", @"endpoint", + @"tcp -h 127.0.0.1 -p 12010 -t 60000", c); + + testAttribute(clientMetrics, clientProps, update, @"ConnectionEstablishment", @"endpointType", @"1", c); + testAttribute(clientMetrics, clientProps, update, @"ConnectionEstablishment", @"endpointIsDatagram", @"false", c); + testAttribute(clientMetrics, clientProps, update, @"ConnectionEstablishment", @"endpointIsSecure", @"false", c); + testAttribute(clientMetrics, clientProps, update, @"ConnectionEstablishment", @"endpointTimeout", @"60000", c); + testAttribute(clientMetrics, clientProps, update, @"ConnectionEstablishment", @"endpointCompress", @"false", c); + testAttribute(clientMetrics, clientProps, update, @"ConnectionEstablishment", @"endpointHost", @"127.0.0.1", c); + testAttribute(clientMetrics, clientProps, update, @"ConnectionEstablishment", @"endpointPort", @"12010", c); + + tprintf("ok\n"); + + // + // Ice doesn't do any endpoint lookup with WinRT, the WinRT + // runtime takes care of if. + // + // In iOS we use CFStream transports that doesn't do any enpoint + // lookup. + // +#if !defined(ICE_OS_WINRT) && (!defined(__APPLE__) || (defined(__APPLE__) && !TARGET_OS_IPHONE)) + tprintf("testing endpoint lookup metrics... "); + + [props setObject:@"id" forKey:@"IceMX.Metrics.View.Map.EndpointLookup.GroupBy"]; + updateProps(clientProps, serverProps, update, props, @"EndpointLookup"); + test([[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"EndpointLookup"] count] == 0); + + ICEObjectPrx* prx = [communicator stringToProxy:@"metrics:default -p 12010 -h localhost -t infinite"]; + [prx ice_ping]; + test([[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"EndpointLookup"] count] == 1); + m1 = [[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"EndpointLookup"] objectAtIndex:0]; + + test(m1.current <= 1 && m1.total == 1 && [m1.id_ isEqualToString:@"tcp -h localhost -p 12010 -t infinite"]); + + [[prx ice_getConnection] close:NO]; + + BOOL dnsException = NO; + @try + { + [[communicator stringToProxy:@"test:tcp -t 500 -p 12010 -h unknownfoo.zeroc.com"] ice_ping]; + test(NO); + } + @catch(const ICEDNSException*) + { + dnsException = YES; + } + @catch(ICELocalException*) + { + // Some DNS servers don't fail on unknown DNS names. + } + test([[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"EndpointLookup"] count] == 2); + m1 = [[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"EndpointLookup"] objectAtIndex:1]; + test([m1.id_ isEqualToString:@"tcp -h unknownfoo.zeroc.com -p 12010 -t 500"] && m1.total == 2 && + (!dnsException || m1.failures == 2)); + if(dnsException) + { + checkFailure(clientMetrics, @"EndpointLookup", m1.id_, @"Ice::DNSException", 2); + } + + c = [Connect connect:prx]; + testAttribute(clientMetrics, clientProps, update, @"EndpointLookup", @"parent", @"Communicator", c); + testAttribute(clientMetrics, clientProps, update, @"EndpointLookup", @"id", + @"tcp -h localhost -p 12010 -t infinite", c); + testAttribute(clientMetrics, clientProps, update, @"EndpointLookup", @"endpoint", + @"tcp -h localhost -p 12010 -t infinite", c); + + testAttribute(clientMetrics, clientProps, update, @"EndpointLookup", @"endpointType", @"1", c); + testAttribute(clientMetrics, clientProps, update, @"EndpointLookup", @"endpointIsDatagram", @"false", c); + testAttribute(clientMetrics, clientProps, update, @"EndpointLookup", @"endpointIsSecure", @"false", c); + testAttribute(clientMetrics, clientProps, update, @"EndpointLookup", @"endpointTimeout", @"-1", c); + testAttribute(clientMetrics, clientProps, update, @"EndpointLookup", @"endpointCompress", @"false", c); + testAttribute(clientMetrics, clientProps, update, @"EndpointLookup", @"endpointHost", @"localhost", c); + testAttribute(clientMetrics, clientProps, update, @"EndpointLookup", @"endpointPort", @"12010", c); + + tprintf("ok\n"); +#endif + + tprintf("testing dispatch metrics... "); + + [props setObject:@"operation" forKey:@"IceMX.Metrics.View.Map.Dispatch.GroupBy"]; + updateProps(clientProps, serverProps, update, props, @"Dispatch"); + test([[[serverMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Dispatch"] count] == 0); + + [metrics op]; + @try + { + [metrics opWithUserException]; + test(NO); + } + @catch(TestMetricsUserEx*) + { + } + @try + { + [metrics opWithRequestFailedException]; + test(NO); + } + @catch(ICERequestFailedException*) + { + } + @try + { + [metrics opWithLocalException]; + test(NO); + } + @catch(ICELocalException*) + { + } + @try + { + [metrics opWithUnknownException]; + test(NO); + } + @catch(ICEUnknownException*) + { + } + @try + { + [metrics fail]; + test(NO); + } + @catch(ICEConnectionLostException*) + { + } + + map = toMap([[serverMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Dispatch"]); + test([map count] == 6); + + ICEMXDispatchMetrics* dm1 = (ICEMXDispatchMetrics*)[map objectForKey:@"op"]; + test(dm1.current <= 1 && dm1.total == 1 && dm1.failures == 0 && dm1.userException == 0); + test(dm1.size == 21 && dm1.replySize == 7); + + dm1 = (ICEMXDispatchMetrics*)[map objectForKey:@"opWithUserException"]; + test(dm1.current <= 1 && dm1.total == 1 && dm1.failures == 0 && dm1.userException == 1); + test(dm1.size == 38 && dm1.replySize == 23); + + dm1 = (ICEMXDispatchMetrics*)[map objectForKey:@"opWithLocalException"]; + test(dm1.current <= 1 && dm1.total == 1 && dm1.failures == 1 && dm1.userException == 0); + checkFailure(serverMetrics, @"Dispatch", dm1.id_, @"Ice::SyscallException", 1); + test(dm1.size == 39 && dm1.replySize > 7); // Reply contains the exception stack depending on the OS. + + dm1 = (ICEMXDispatchMetrics*)[map objectForKey:@"opWithRequestFailedException"]; + test(dm1.current <= 1 && dm1.total == 1 && dm1.failures == 1 && dm1.userException == 0); + checkFailure(serverMetrics, @"Dispatch", dm1.id_, @"Ice::ObjectNotExistException", 1); + test(dm1.size == 47 && dm1.replySize == 40); + + dm1 = (ICEMXDispatchMetrics*)[map objectForKey:@"opWithUnknownException"]; + test(dm1.current <= 1 && dm1.total == 1 && dm1.failures == 1 && dm1.userException == 0); + checkFailure(serverMetrics, @"Dispatch", dm1.id_, @"IceObjC::Exception", 1); + test(dm1.size == 41 && dm1.replySize > 7); // Reply contains the exception stack depending on the OS. + + InvokeOp* op = [InvokeOp invokeOp:metrics]; + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"parent", @"TestAdapter", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"id", @"metrics [op]", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"endpoint", + @"tcp -h 127.0.0.1 -p 12010 -t 60000", op); + //testAttribute(serverMetrics, serverProps, update, "Dispatch", "connection", "", op); + + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"endpointType", @"1", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"endpointIsDatagram", @"false", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"endpointIsSecure", @"false", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"endpointTimeout", @"60000", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"endpointCompress", @"false", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"endpointHost", @"127.0.0.1", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"endpointPort", @"12010", op); + + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"incoming", @"true", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"adapterName", @"TestAdapter", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"connectionId", @"", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"localHost", @"127.0.0.1", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"localPort", @"12010", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"remoteHost", @"127.0.0.1", op); + //testAttribute(serverMetrics, serverProps, update, "Dispatch", "remotePort", "12010", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"mcastHost", @"", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"mcastPort", @"", op); + + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"operation", @"op", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"identity", @"metrics", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"facet", @"", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"mode", @"twoway", op); + + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"context.entry1", @"test", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"context.entry2", @"", op); + testAttribute(serverMetrics, serverProps, update, @"Dispatch", @"context.entry3", @"", op); + + tprintf("ok\n"); + + tprintf("testing invocation metrics... "); + + [props setObject:@"operation" forKey:@"IceMX.Metrics.View.Map.Invocation.GroupBy"]; + [props setObject:@"localPort" forKey:@"IceMX.Metrics.View.Map.Invocation.Map.Remote.GroupBy"]; + updateProps(clientProps, serverProps, update, props, @"Invocation"); + test([[[serverMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Invocation"] count] == 0); + + Callback* cb = [Callback callback]; + + void(^responseCB)() = ^() + { + [cb response]; + }; + + void(^exceptionCB)(ICEException*) = ^(ICEException* ex) + { + [cb exception:ex]; + }; + + [metrics op]; + [metrics end_op:[metrics begin_op]]; + [metrics begin_op:responseCB exception:exceptionCB]; + [cb waitForResponse]; + + // User exception + @try + { + [metrics opWithUserException]; + test(NO); + } + @catch(TestMetricsUserEx*) + { + } + @try + { + [metrics end_opWithUserException:[metrics begin_opWithUserException]]; + test(NO); + } + @catch(const TestMetricsUserEx*) + { + } + [metrics begin_opWithUserException:responseCB exception:exceptionCB]; + [cb waitForResponse]; + + // Request failed exception + @try + { + [metrics opWithRequestFailedException]; + test(NO); + } + @catch(ICERequestFailedException*) + { + } + @try + { + [metrics end_opWithRequestFailedException:[metrics begin_opWithRequestFailedException]]; + test(NO); + } + @catch(const ICERequestFailedException*) + { + } + [metrics begin_opWithRequestFailedException:responseCB exception:exceptionCB]; + [cb waitForResponse]; + + // Local exception + @try + { + [metrics opWithLocalException]; + test(NO); + } + @catch(ICELocalException*) + { + } + @try + { + [metrics end_opWithLocalException:[metrics begin_opWithLocalException]]; + test(NO); + } + @catch(ICELocalException*) + { + } + [metrics begin_opWithLocalException:responseCB exception:exceptionCB]; + [cb waitForResponse]; + + // Unknown exception + @try + { + [metrics opWithUnknownException]; + test(NO); + } + @catch(ICEUnknownException*) + { + } + @try + { + [metrics end_opWithUnknownException:[metrics begin_opWithUnknownException]]; + test(NO); + } + @catch(ICEUnknownException*) + { + } + [metrics begin_opWithUnknownException:responseCB exception:exceptionCB]; + [cb waitForResponse]; + + // Fail + @try + { + [metrics fail]; + test(NO); + } + @catch(ICEConnectionLostException*) + { + } + @try + { + [metrics end_fail:[metrics begin_fail]]; + test(NO); + } + @catch(ICEConnectionLostException*) + { + } + [metrics begin_fail:responseCB exception:exceptionCB]; + [cb waitForResponse]; + + map = toMap([[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Invocation"]); + test([map count] == 6); + + ICEMXInvocationMetrics* im1; + ICEMXRemoteMetrics* rim1; + im1 = (ICEMXInvocationMetrics*)[map objectForKey:@"op"]; + test(im1.current <= 1 && im1.total == 3 && im1.failures == 0 && im1.retry == 0 && [im1.remotes count] == 1); + rim1 = (ICEMXRemoteMetrics*)[im1.remotes objectAtIndex:0]; + test(rim1.current == 0 && rim1.total == 3 && rim1.failures == 0); + test(rim1.size == 63 && rim1.replySize == 21); + + im1 = (ICEMXInvocationMetrics*)[map objectForKey:@"opWithUserException"]; + test(im1.current <= 1 && im1.total == 3 && im1.failures == 0 && im1.retry == 0 && [im1.remotes count] == 1); + rim1 = (ICEMXRemoteMetrics*)[im1.remotes objectAtIndex:0]; + test(rim1.current == 0 && rim1.total == 3 && rim1.failures == 0); + test(rim1.size == 114 && rim1.replySize == 69); + test(im1.userException == 3); + + im1 = (ICEMXInvocationMetrics*)[map objectForKey:@"opWithLocalException"]; + test(im1.current <= 1 && im1.total == 3 && im1.failures == 3 && im1.retry == 0 && [im1.remotes count] == 1); + rim1 = (ICEMXRemoteMetrics*)[im1.remotes objectAtIndex:0]; + test(rim1.current == 0 && rim1.total == 3 && rim1.failures == 0); + test(rim1.size == 117 && rim1.replySize > 7); + checkFailure(clientMetrics, @"Invocation", im1.id_, @"Ice::UnknownLocalException", 3); + + im1 = (ICEMXInvocationMetrics*)[map objectForKey:@"opWithRequestFailedException"]; + test(im1.current <= 1 && im1.total == 3 && im1.failures == 3 && im1.retry == 0 && [im1.remotes count] == 1); + rim1 = (ICEMXRemoteMetrics*)[im1.remotes objectAtIndex:0]; + test(rim1.current == 0 && rim1.total == 3 && rim1.failures == 0); + test(rim1.size == 141 && rim1.replySize == 120); + checkFailure(clientMetrics, @"Invocation", im1.id_, @"Ice::ObjectNotExistException", 3); + + im1 = (ICEMXInvocationMetrics*)[map objectForKey:@"opWithUnknownException"]; + test(im1.current <= 1 && im1.total == 3 && im1.failures == 3 && im1.retry == 0 && [im1.remotes count] == 1); + rim1 = (ICEMXRemoteMetrics*)[im1.remotes objectAtIndex:0]; + test(rim1.current == 0 && rim1.total == 3 && rim1.failures == 0); + checkFailure(clientMetrics, @"Invocation", im1.id_, @"Ice::UnknownException", 3); + + im1 = (ICEMXInvocationMetrics*)[map objectForKey:@"fail"]; + test(im1.current <= 1 && im1.total == 3 && im1.failures == 3 && im1.retry == 3 && [im1.remotes count] == 6); + + test(((ICEMXMetrics*)[im1.remotes objectAtIndex:0]).current == 0 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:0]).total == 1 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:0]).failures == 1); + + test(((ICEMXMetrics*)[im1.remotes objectAtIndex:1]).current == 0 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:1]).total == 1 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:1]).failures == 1); + + test(((ICEMXMetrics*)[im1.remotes objectAtIndex:2]).current == 0 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:2]).total == 1 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:2]).failures == 1); + + test(((ICEMXMetrics*)[im1.remotes objectAtIndex:3]).current == 0 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:3]).total == 1 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:3]).failures == 1); + + test(((ICEMXMetrics*)[im1.remotes objectAtIndex:4]).current == 0 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:4]).total == 1 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:4]).failures == 1); + + test(((ICEMXMetrics*)[im1.remotes objectAtIndex:5]).current == 0 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:5]).total == 1 && + ((ICEMXMetrics*)[im1.remotes objectAtIndex:5]).failures == 1); + + checkFailure(clientMetrics, @"Invocation", im1.id_, @"Ice::ConnectionLostException", 3); + + testAttribute(clientMetrics, clientProps, update, @"Invocation", @"parent", @"Communicator", op); + testAttribute(clientMetrics, clientProps, update, @"Invocation", @"id", @"metrics -t -e 1.1 [op]", op); + + testAttribute(clientMetrics, clientProps, update, @"Invocation", @"operation", @"op", op); + testAttribute(clientMetrics, clientProps, update, @"Invocation", @"identity", @"metrics", op); + testAttribute(clientMetrics, clientProps, update, @"Invocation", @"facet", @"", op); + testAttribute(clientMetrics, clientProps, update, @"Invocation", @"encoding", @"1.1", op); + testAttribute(clientMetrics, clientProps, update, @"Invocation", @"mode", @"twoway", op); + testAttribute(clientMetrics, clientProps, update, @"Invocation", @"proxy", + @"metrics -t -e 1.1:tcp -h 127.0.0.1 -p 12010 -t 60000", op); + + testAttribute(clientMetrics, clientProps, update, @"Invocation", @"context.entry1", @"test", op); + testAttribute(clientMetrics, clientProps, update, @"Invocation", @"context.entry2", @"", op); + testAttribute(clientMetrics, clientProps, update, @"Invocation", @"context.entry3", @"", op); + + tprintf("ok\n"); + + tprintf("testing metrics view enable/disable..."); + + + [props setObject:@"none" forKey:@"IceMX.Metrics.View.GroupBy"]; + [props setObject:@"0" forKey:@"IceMX.Metrics.View.Disabled"]; + updateProps(clientProps, serverProps, update, props, @"Thread"); + test([[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Thread"] count] > 0); + + ICEMutableStringSeq* disabledViews; + ICEMutableStringSeq* names = [clientMetrics getMetricsViewNames:&disabledViews]; + test([names count] == 1 && [disabledViews count] == 0); + + [props setObject:@"1" forKey:@"IceMX.Metrics.View.Disabled"]; + updateProps(clientProps, serverProps, update, props, @"Thread"); + test([[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Thread"] count] == 0); + test([[clientMetrics getMetricsViewNames:&disabledViews] count] == 0 && [disabledViews count] == 1); + + [clientMetrics enableMetricsView:@"View"]; + test([[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Thread"] count] > 0); + test([[clientMetrics getMetricsViewNames:&disabledViews] count] == 1 && [disabledViews count] == 0); + + [clientMetrics disableMetricsView:@"View"]; + test([[[clientMetrics getMetricsView:@"View" timestamp:×tamp] objectForKey:@"Thread"] count] == 0); + test([[clientMetrics getMetricsViewNames:&disabledViews] count] == 0 && [disabledViews count] == 1); + + @try + { + [clientMetrics enableMetricsView:@"UnknownView"]; + } + @catch(ICEMXUnknownMetricsView*) + { + } + + tprintf("ok\n"); + + return metrics; +} diff --git a/objc/test/Ice/metrics/Client.m b/objc/test/Ice/metrics/Client.m new file mode 100644 index 00000000000..02bf2733872 --- /dev/null +++ b/objc/test/Ice/metrics/Client.m @@ -0,0 +1,87 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <MetricsTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + id<TestMetricsMetricsPrx> metricsAllTests(id<ICECommunicator>); + id<TestMetricsMetricsPrx> metrics = metricsAllTests(communicator); + [metrics shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main metricsClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); + [initData.properties setProperty:@"Ice.Admin.Endpoints" value:@"tcp"]; + [initData.properties setProperty:@"Ice.Admin.InstanceName" value:@"client"]; + [initData.properties setProperty:@"Ice.Admin.DelayCreation" value:@"1"]; + [initData.properties setProperty:@"Ice.Warn.Connections" value:@"0"]; + [initData.properties setProperty:@"Ice.MessageSizeMax" value:@"50000"]; + + [initData.properties setProperty:@"IceMX.Metrics.Debug.GroupBy" value:@"id"]; + [initData.properties setProperty:@"IceMX.Metrics.Parent.GroupBy" value:@"parent"]; + [initData.properties setProperty:@"IceMX.Metrics.All.GroupBy" value:@"none"]; +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestMetrics", @"::Test", + @"ICEMX", @"::IceMX", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/metrics/Makefile b/objc/test/Ice/metrics/Makefile new file mode 100644 index 00000000000..5cb7680df69 --- /dev/null +++ b/objc/test/Ice/metrics/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = MetricsTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/metrics/MetricsTest.ice b/objc/test/Ice/metrics/MetricsTest.ice new file mode 100644 index 00000000000..690eef9c1da --- /dev/null +++ b/objc/test/Ice/metrics/MetricsTest.ice @@ -0,0 +1,51 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestMetrics"] +module Test +{ + +exception UserEx +{ +}; + +sequence<byte> ByteSeq; + +interface Metrics +{ + void op(); + + idempotent void fail(); + + void opWithUserException() + throws UserEx; + + void opWithRequestFailedException(); + + void opWithLocalException(); + + void opWithUnknownException(); + + void opByteS(ByteSeq bs); + + Object* getAdmin(); + + void shutdown(); +}; + +interface Controller +{ + void hold(); + + void resume(); +}; + +}; diff --git a/objc/test/Ice/metrics/Server.m b/objc/test/Ice/metrics/Server.m new file mode 100644 index 00000000000..908ed2710ad --- /dev/null +++ b/objc/test/Ice/metrics/Server.m @@ -0,0 +1,103 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <metrics/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; + + ICEObject* object = [[MetricsI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [object autorelease]; +#endif + [adapter add:object identity:[communicator stringToIdentity:@"metrics"]]; + [adapter activate]; + + [[communicator getProperties] setProperty:@"ControllerAdapter.Endpoints" value:@"default -p 12011"]; + id<ICEObjectAdapter> controllerAdapter = [communicator createObjectAdapter:@"ControllerAdapter"]; + + ICEObject* controller = [[ControllerI alloc] init:adapter]; +#if defined(__clang__) && !__has_feature(objc_arc) + [controller autorelease]; +#endif + [controllerAdapter add:controller identity:[communicator stringToIdentity:@"controller"]]; + [controllerAdapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main metricsServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); + [initData.properties setProperty:@"Ice.Admin.Endpoints" value:@"tcp"]; + [initData.properties setProperty:@"Ice.Admin.InstanceName" value:@"server"]; + [initData.properties setProperty:@"Ice.Warn.Connections" value:@"0"]; + [initData.properties setProperty:@"Ice.Warn.Dispatch" value:@"0"]; + [initData.properties setProperty:@"Ice.MessageSizeMax" value:@"50000"]; + + [initData.properties setProperty:@"IceMX.Metrics.Debug.GroupBy" value:@"id"]; + [initData.properties setProperty:@"IceMX.Metrics.Parent.GroupBy" value:@"parent"]; + [initData.properties setProperty:@"IceMX.Metrics.All.GroupBy" value:@"none"]; +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestMetrics", @"::Test", + @"ICEMX", @"::IceMX", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/metrics/TestI.h b/objc/test/Ice/metrics/TestI.h new file mode 100644 index 00000000000..ca0f891a535 --- /dev/null +++ b/objc/test/Ice/metrics/TestI.h @@ -0,0 +1,33 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <MetricsTest.h> + +@interface MetricsI : TestMetricsMetrics<TestMetricsMetrics> +-(id) init; +-(void) op:(ICECurrent*)current; +-(void) fail:(ICECurrent*)current; +-(void) opWithUserException:(ICECurrent*)current; +-(void) opWithRequestFailedException:(ICECurrent*)current; +-(void) opWithLocalException:(ICECurrent*)current; +-(void) opWithUnknownException:(ICECurrent*)current; +-(void) opByteS:(ICEByteSeq*)bs current:(ICECurrent*)current; +-(ICEObjectPrx*) getAdmin:(ICECurrent*)current; +-(void) shutdown:(ICECurrent*)current; +@end + +@interface ControllerI : TestMetricsController<TestMetricsController> +{ +@private + id<ICEObjectAdapter> adapter; +} +-(id) init:(id<ICEObjectAdapter>)adapter_p; +-(void) hold:(ICECurrent*)current; +-(void) resume:(ICECurrent*)current; +@end
\ No newline at end of file diff --git a/objc/test/Ice/metrics/TestI.m b/objc/test/Ice/metrics/TestI.m new file mode 100644 index 00000000000..5ec6252138d --- /dev/null +++ b/objc/test/Ice/metrics/TestI.m @@ -0,0 +1,98 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <metrics/TestI.h> + +@implementation MetricsI + +-(id) init +{ + self = [super init]; + return self; +} + +-(void) op:(ICECurrent*)current +{ +} + +-(void) fail:(ICECurrent*)current +{ + [current.con close:YES]; +} + +-(void) opWithUserException:(ICECurrent*)current +{ + @throw [TestMetricsUserEx userEx]; +} + +-(void) opWithRequestFailedException:(ICECurrent*)current +{ + @throw [ICEObjectNotExistException objectNotExistException:__FILE__ line:__LINE__]; +} + +-(void) opWithLocalException:(ICECurrent*)current +{ + @throw [ICESyscallException syscallException:__FILE__ line:__LINE__]; +} + +-(void) opWithUnknownException:(ICECurrent*)current +{ + @throw @"TEST"; +} + +-(void) opByteS:(ICEByteSeq*)bs current:(ICECurrent*)current +{ +} + +-(ICEObjectPrx*) getAdmin:(ICECurrent*)current +{ + return [[current.adapter getCommunicator] getAdmin]; +} + +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} +@end + +@implementation ControllerI +-(id) init:(id<ICEObjectAdapter>)adapter_p +{ + self = [super init]; + if(self) + { +#if defined(__clang__) && !__has_feature(objc_arc) + self->adapter = [adapter_p retain]; +#else + self->adapter = adapter_p; +#endif + } + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [self->adapter release]; + [super dealloc]; +} +#endif + +-(void) hold:(ICECurrent*)current +{ + [adapter hold]; + [adapter waitForHold]; +} + +-(void) resume:(ICECurrent*)current +{ + [adapter activate]; +} +@end diff --git a/objc/test/Ice/metrics/run.py b/objc/test/Ice/metrics/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/metrics/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/objects/.gitignore b/objc/test/Ice/objects/.gitignore new file mode 100644 index 00000000000..6f8684420f8 --- /dev/null +++ b/objc/test/Ice/objects/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +ObjectsTest.m +ObjectsTest.h diff --git a/objc/test/Ice/objects/AllTests.m b/objc/test/Ice/objects/AllTests.m new file mode 100644 index 00000000000..775ec995650 --- /dev/null +++ b/objc/test/Ice/objects/AllTests.m @@ -0,0 +1,517 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <ObjectsTest.h> + +void breakRetainCycleB(); +void breakRetainCycleC(); +void breakRetainCycleD(); + +void breakRetainCycleB(TestObjectsB* b1) +{ + if([b1.theA isKindOfClass:[TestObjectsB class]]) + { + TestObjectsB* b2 = (TestObjectsB*)b1.theA; + b2.theA = nil; + b2.theB.theA = nil; + b2.theB.theB = nil; + b2.theB.theC = nil; + b2.theB = nil; + b2.theC = nil; + b2 = nil; + } + b1.theA = nil; + b1.theB = nil; + b1.theC = nil; +} + +void breakRetainCycleC(TestObjectsC* c1) +{ + breakRetainCycleB(c1.theB); + c1.theB = nil; + +} + +void breakRetainCycleD(TestObjectsD* d1) +{ + breakRetainCycleB((TestObjectsB*)d1.theA); + breakRetainCycleB(d1.theB); +} + +id<TestObjectsInitialPrx> +objectsAllTests(id<ICECommunicator> communicator, BOOL collocated) +{ + tprintf("testing stringToProxy... "); + NSString* ref = @"initial:default -p 12010"; + id<ICEObjectPrx> base = [communicator stringToProxy:ref]; + test(base); + tprintf("ok\n"); + + tprintf("testing checked cast... "); + id<TestObjectsInitialPrx> initial = [TestObjectsInitialPrx checkedCast:base]; + test(initial); + test([initial isEqual:base]); + tprintf("ok\n"); + + tprintf("testing constructor, convenience constructor, and copy... "); + + TestObjectsBase* ba1 = [TestObjectsBase base]; + + test(ba1.theS.str == nil); + test(ba1.str == nil); + ba1.theS = nil; + + TestObjectsS* s = [TestObjectsS s]; + s.str = @"hello"; + TestObjectsBase* ba2 = [TestObjectsBase base:s str:@"hi"]; + test(ba2.theS == s); + test([ba2.str isEqualToString:@"hi"]); + ba2.theS = nil; + + TestObjectsBase* ba3 = [ba2 copy]; +#if defined(__clang__) && !__has_feature(objc_arc) + [ba3 autorelease]; +#endif + test(ba3 != ba2); + test(ba3.theS == ba2.theS); + test(ba3.str == ba2.str); + ba3.theS = nil; + +#if 0 + // Can't override assignment operator in Objective-C. + *ba1 = *ba2; + test([ba1.theS.str isEqualToString:@"hello"]); + test([ba1.str isEqualToString:@"hi"]); + + TestObjectsBase* bp1 = [TestObjectsBase base]; + *bp1 = *ba2; + test([bp1.theS.str isEqualToString:@"hello"]); + test([bp1.str isEqualToString:@"hi"]); +#endif + + tprintf("ok\n"); + + tprintf("getting B1... "); + TestObjectsB* b1 = [initial getB1]; + test(b1); + tprintf("ok\n"); + + tprintf("getting B2... "); + TestObjectsB* b2 = [initial getB2]; + test(b2); + tprintf("ok\n"); + + tprintf("getting C... "); + TestObjectsC* c = [initial getC]; + test(c); + tprintf("ok\n"); + + tprintf("getting D... "); + TestObjectsD* d = [initial getD]; + test(d); + tprintf("ok\n"); + + tprintf("checking consistency... "); + test(b1 != b2); + test(b1 != (TestObjectsB*)c); + test(b1 != (TestObjectsB*)d); + test(b2 != (TestObjectsB*)c); + test(b2 != (TestObjectsB*)d); + test(c != (TestObjectsC*)d); + test(b1.theB == b1); + test(b1.theC == 0); + test([b1.theA isKindOfClass:[TestObjectsB class]]); + test(((TestObjectsB*)b1.theA).theA == b1.theA); + test(((TestObjectsB*)b1.theA).theB == b1); + test([((TestObjectsB*)b1.theA).theC isKindOfClass:[TestObjectsC class]]); + test(((TestObjectsC*)((TestObjectsB*)b1.theA).theC).theB == b1.theA); + test(b1.preMarshalInvoked); + test([(id<TestObjectsB>)b1 postUnmarshalInvoked:nil]); + test(b1.theA.preMarshalInvoked); + test([(id<TestObjectsA>)b1.theA postUnmarshalInvoked:nil]); + test(((TestObjectsB*)b1.theA).theC.preMarshalInvoked); + test([(id<TestObjectsC>)((TestObjectsB*)b1.theA).theC postUnmarshalInvoked:nil]); + + // More tests possible for b2 and d, but I think this is already sufficient. + test(b2.theA == b2); + test(d.theC == 0); + + breakRetainCycleB(b1); + breakRetainCycleB(b2); + breakRetainCycleC(c); + breakRetainCycleD(d); + + tprintf("ok\n"); + + tprintf("getting B1, B2, C, and D all at once... "); + [initial getAll:&b1 b2:&b2 theC:&c theD:&d]; + test(b1); + test(b2); + test(c); + test(d); + tprintf("ok\n"); + + tprintf("checking consistency... "); + test(b1 != b2); + test(b1 != (TestObjectsB*)c); + test(b1 != (TestObjectsB*)d); + test(b2 != (TestObjectsB*)c); + test(b2 != (TestObjectsB*)d); + test(c != (TestObjectsC*)d); + test(b1.theA == b2); + test(b1.theB == b1); + //test(b1.theC == 0); + test(b2.theA == b2); + test(b2.theB == b1); + test(b2.theC == c); + test(c.theB == b2); + test(d.theA == b1); + test(d.theB == b2); + //test(d.theC == 0); +// if(!collocated) +// { + test(d.preMarshalInvoked); + test([(id<TestObjectsD>)d postUnmarshalInvoked:nil]); + test(d.theA.preMarshalInvoked); + test([(id<TestObjectsA>)d.theA postUnmarshalInvoked:nil]); + test(d.theB.preMarshalInvoked); + test([(id<TestObjectsA>)d.theB postUnmarshalInvoked:nil]); + test(d.theB.theC.preMarshalInvoked); + test([(id<TestObjectsC>)d.theB.theC postUnmarshalInvoked:nil]); +// } + + breakRetainCycleB(b1); + breakRetainCycleB(b2); + breakRetainCycleC(c); + breakRetainCycleD(d); + + tprintf("ok\n"); + + tprintf("testing protected members... "); + TestObjectsE* e = [initial getE]; + test([(id<TestObjectsE>)e checkValues:nil]); + TestObjectsF* f = [initial getF]; + test([(id<TestObjectsF>)f checkValues:nil]); + test([(id<TestObjectsE>)f.e2 checkValues:nil]); + tprintf("ok\n"); + + tprintf("getting I, J and H... "); + TestObjectsI* i = (TestObjectsI*)[initial getI]; + test(i); + TestObjectsI* j = (TestObjectsI*)[initial getJ]; + test(j && [j isKindOfClass:[TestObjectsJ class]]); + TestObjectsI* h = (TestObjectsI*)[initial getH]; + test(h && [h isKindOfClass:[TestObjectsH class]]); + tprintf("ok\n"); + + tprintf("setting I... "); + [initial setI:i]; + [initial setI:j]; + [initial setI:h]; + tprintf("ok\n"); + + tprintf("testing sequences... "); + TestObjectsMutableBaseSeq* inS = [TestObjectsMutableBaseSeq array]; + TestObjectsMutableBaseSeq* outS; + TestObjectsMutableBaseSeq* retS = [initial opBaseSeq:inS outSeq:&outS]; + + [inS addObject:[TestObjectsBase base]]; + retS = [initial opBaseSeq:inS outSeq:&outS]; + test([retS count] == 1 && [outS count] == 1); + tprintf("ok\n"); + + tprintf("testing compact ID..."); + @try + { + test([initial getCompact]); + } + @catch(ICEOperationNotExistException*) + { + } + tprintf("ok\n"); + +// if(!collocated) +// { + tprintf("testing UnexpectedObjectException... "); + ref = @"uoet:default -p 12010"; + base = [communicator stringToProxy:ref]; + test(base); + id<TestObjectsUnexpectedObjectExceptionTestPrx> uoet = [TestObjectsUnexpectedObjectExceptionTestPrx uncheckedCast:base]; + test(uoet); + @try + { + [uoet op]; + test(NO); + } + @catch(ICEUnexpectedObjectException* ex) + { + test([ex.type isEqualToString:@"::Test::AlsoEmpty"]); + test([ex.expectedType isEqualToString:@"::Test::Empty"]); + } + @catch(ICEException* ex) + { + test(NO); + } + tprintf("ok\n"); +// } + + // + // TestObjectss specific to Objective-C. + // + { + tprintf("setting Object sequence... "); + TestObjectsMutableObjectSeq* seq = [TestObjectsMutableObjectSeq array]; + + [seq addObject:[NSNull null]]; + + TestObjectsBase* b = [TestObjectsBase base]; + b.theS = [TestObjectsS s]; + b.theS.str = @"Hello"; + b.str = @"World"; + [seq addObject:b]; + + @try + { + TestObjectsObjectSeq* r = [initial getObjectSeq:seq]; + test([r objectAtIndex:0 == [NSNull null]]); + TestObjectsBase* br = [r objectAtIndex:1]; + test([br.theS.str isEqualToString:@"Hello"]); + test([br.str isEqualToString:@"World"]); + } + @catch(ICEOperationNotExistException*) + { + // Expected if we are testing against a non-Objective-C server. + } + @catch(...) + { + test(NO); + } + tprintf("ok\n"); + } + + { + tprintf("setting Object proxy sequence... "); + TestObjectsMutableObjectPrxSeq* seq = [TestObjectsMutableObjectPrxSeq array]; + + [seq addObject:[NSNull null]]; + [seq addObject:initial]; + + @try + { + TestObjectsObjectPrxSeq* r = [initial getObjectPrxSeq:seq]; + test([r objectAtIndex:0 == [NSNull null]]); + test([[r objectAtIndex:1] isEqual:initial]); + } + @catch(ICEOperationNotExistException*) + { + // Expected if we are testing against a non-Objective-C server. + } + @catch(...) + { + test(NO); + } + tprintf("ok\n"); + } + + { + tprintf("setting Base sequence... "); + TestObjectsMutableBaseSeq* seq = [TestObjectsMutableBaseSeq array]; + + [seq addObject:[NSNull null]]; + + TestObjectsBase* b = [TestObjectsBase base]; + b.theS = [TestObjectsS s]; + b.theS.str = @"Hello"; + b.str = @"World"; + [seq addObject:b]; + + @try + { + TestObjectsBaseSeq* r = [initial getBaseSeq:seq]; + test([r objectAtIndex:0 == [NSNull null]]); + TestObjectsBase* br = [r objectAtIndex:1]; + test([br.theS.str isEqualToString:@"Hello"]); + test([br.str isEqualToString:@"World"]); + br.theS = nil; + } + @catch(ICEOperationNotExistException*) + { + // Expected if we are testing against a non-Objective-C server. + } + @catch(...) + { + test(NO); + } + + { + TestObjectsBase* br = [seq objectAtIndex:1]; + br.theS = nil; + b.theS = nil; + } + tprintf("ok\n"); + } + + { + tprintf("setting Base proxy sequence... "); + TestObjectsMutableBasePrxSeq* seq = [TestObjectsMutableBasePrxSeq array]; + + [seq addObject:[NSNull null]]; + NSString* ref = @"base:default -p 12010"; + id<ICEObjectPrx> base = [communicator stringToProxy:ref]; + id<TestObjectsBasePrx> b = [TestObjectsBasePrx uncheckedCast:base]; + [seq addObject:b]; + + @try + { + TestObjectsBasePrxSeq* r = [initial getBasePrxSeq:seq]; + test([r objectAtIndex:0 == [NSNull null]]); + test([[r objectAtIndex:1] isEqual:b]); + } + @catch(ICEOperationNotExistException*) + { + // Expected if we are testing against a non-Objective-C server. + } + @catch(...) + { + test(NO); + } + tprintf("ok\n"); + } + + { + tprintf("setting Object dictionary... "); + TestObjectsMutableObjectDict* dict = [TestObjectsMutableObjectDict dictionary]; + + [dict setObject:[NSNull null] forKey:@"zero"]; + + TestObjectsBase* b = [TestObjectsBase base]; + b.theS = [TestObjectsS s]; + b.theS.str = @"Hello"; + b.str = @"World"; + [dict setObject:b forKey:@"one"]; + + @try + { + TestObjectsObjectDict* r = [initial getObjectDict:dict]; + test([r objectForKey:@"zero"] == [NSNull null]); + TestObjectsBase* br = [r objectForKey:@"one"]; + test([br.theS.str isEqualToString:@"Hello"]); + test([br.str isEqualToString:@"World"]); + br.theS = nil; + } + @catch(ICEOperationNotExistException*) + { + // Expected if we are testing against a non-Objective-C server. + } + @catch(...) + { + test(NO); + } + { + TestObjectsBase* br = [dict objectForKey:@"one"]; + br.theS = nil; + b.theS = nil; + } + tprintf("ok\n"); + } + + { + tprintf("setting Object proxy dictionary... "); + TestObjectsMutableObjectPrxDict* dict = [TestObjectsMutableObjectPrxDict dictionary]; + + [dict setObject:[NSNull null] forKey:@"zero"]; + NSString* ref = @"object:default -p 12010"; + id<ICEObjectPrx> o = [communicator stringToProxy:ref]; + [dict setObject:o forKey:@"one"]; + + @try + { + TestObjectsObjectPrxDict* r = [initial getObjectPrxDict:dict]; + test([r objectForKey:@"zero"] == [NSNull null]); + test([[r objectForKey:@"one"] isEqual:o]); + } + @catch(ICEOperationNotExistException*) + { + // Expected if we are testing against a non-Objective-C server. + } + @catch(...) + { + test(NO); + } + tprintf("ok\n"); + } + + { + tprintf("setting Base dictionary... "); + TestObjectsMutableBaseDict* dict = [TestObjectsMutableBaseDict dictionary]; + + [dict setObject:[NSNull null] forKey:@"zero"]; + + TestObjectsBase* b = [TestObjectsBase base]; + b.theS = [TestObjectsS s]; + b.theS.str = @"Hello"; + b.str = @"World"; + [dict setObject:b forKey:@"one"]; + + @try + { + TestObjectsBaseDict* r = [initial getBaseDict:dict]; + test([r objectForKey:@"zero"] == [NSNull null]); + TestObjectsBase* br = [r objectForKey:@"one"]; + test([br.theS.str isEqualToString:@"Hello"]); + test([br.str isEqualToString:@"World"]); + br.theS = nil; + } + @catch(ICEOperationNotExistException*) + { + // Expected if we are testing against a non-Objective-C server. + } + @catch(...) + { + test(NO); + } + { + TestObjectsBase* br = [dict objectForKey:@"one"]; + br.theS = nil; + b.theS = nil; + } + tprintf("ok\n"); + } + + { + tprintf("setting Base proxy dictionary... "); + TestObjectsMutableBasePrxDict* dict = [TestObjectsMutableBasePrxDict dictionary]; + + [dict setObject:[NSNull null] forKey:@"zero"]; + NSString* ref = @"base:default -p 12010"; + id<ICEObjectPrx> base = [communicator stringToProxy:ref]; + id<TestObjectsBasePrx> b = [TestObjectsBasePrx uncheckedCast:base]; + [dict setObject:b forKey:@"one"]; + + @try + { + TestObjectsObjectPrxDict* r = [initial getObjectPrxDict:dict]; + test([r objectForKey:@"zero"] == [NSNull null]); + test([[r objectForKey:@"one"] isEqual:b]); + } + @catch(ICEOperationNotExistException*) + { + // Expected if we are testing against a non-Objective-C server. + } + @catch(...) + { + test(NO); + } + tprintf("ok\n"); + } + + return initial; +} diff --git a/objc/test/Ice/objects/Client.m b/objc/test/Ice/objects/Client.m new file mode 100644 index 00000000000..83c5575def0 --- /dev/null +++ b/objc/test/Ice/objects/Client.m @@ -0,0 +1,146 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <objects/TestI.h> + +#if !TARGET_OS_IPHONE +# import <Foundation/NSGarbageCollector.h> +#endif + +@interface ClientMyObjectFactory : NSObject<ICEObjectFactory> +@end + +@implementation ClientMyObjectFactory + +// Note that the object factory must not autorelease the +// returned objects. +-(ICEObject*) create:(NSString*)type +{ + if([type isEqualToString:@"::Test::B"]) + { + return [[TestObjectsBI alloc] init]; + } + else if([type isEqualToString:@"::Test::C"]) + { + return [[TestObjectsCI alloc] init]; + } + else if([type isEqualToString:@"::Test::D"]) + { + return [[TestObjectsDI alloc] init]; + } + else if([type isEqualToString:@"::Test::E"]) + { + return [[TestObjectsEI alloc] init]; + } + else if([type isEqualToString:@"::Test::F"]) + { + return [[TestObjectsFI alloc] init]; + } + else if([type isEqualToString:@"::Test::I"]) + { + return [[TestObjectsI alloc] init]; + } + else if([type isEqualToString:@"::Test::J"]) + { + return [[TestObjectsJI alloc] init]; + } + else if([type isEqualToString:@"::Test::H"]) + { + return [[TestObjectsHI alloc] init]; + } + else + { + test(NO); + } + return nil; +} + +-(void) destroy +{ + // Nothing to do +} +@end + +static int +run(id<ICECommunicator> communicator) +{ +#if defined(__clang__) && !__has_feature(objc_arc) + id<ICEObjectFactory> factory = [[[ClientMyObjectFactory alloc] init] autorelease]; +#else + id<ICEObjectFactory> factory = [[ClientMyObjectFactory alloc] init]; +#endif + + [communicator addObjectFactory:factory sliceId:@"::Test::B"]; + [communicator addObjectFactory:factory sliceId:@"::Test::C"]; + [communicator addObjectFactory:factory sliceId:@"::Test::D"]; + [communicator addObjectFactory:factory sliceId:@"::Test::E"]; + [communicator addObjectFactory:factory sliceId:@"::Test::F"]; + [communicator addObjectFactory:factory sliceId:@"::Test::I"]; + [communicator addObjectFactory:factory sliceId:@"::Test::J"]; + [communicator addObjectFactory:factory sliceId:@"::Test::H"]; + + id<TestObjectsInitialPrx> objectsAllTests(id<ICECommunicator>, bool); + id<TestObjectsInitialPrx> initial = objectsAllTests(communicator, NO); + [initial shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main objectsClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestObjects", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/objects/Makefile b/objc/test/Ice/objects/Makefile new file mode 100644 index 00000000000..2590019cf26 --- /dev/null +++ b/objc/test/Ice/objects/Makefile @@ -0,0 +1,38 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = ObjectsTest.o + +COBJS = Client.o \ + TestI.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/objects/ObjectsTest.ice b/objc/test/Ice/objects/ObjectsTest.ice new file mode 100644 index 00000000000..eddf50986c7 --- /dev/null +++ b/objc/test/Ice/objects/ObjectsTest.ice @@ -0,0 +1,201 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestObjects"] +module Test +{ + +struct S +{ + string str; +}; + +class Base +{ + S theS; + string str; +}; + +class B; +class C; + +class A +{ + B theB; + C theC; + + bool preMarshalInvoked; + bool postUnmarshalInvoked(); +}; + +class B extends A +{ + A theA; +}; + +class C +{ + B theB; + + bool preMarshalInvoked; + bool postUnmarshalInvoked(); +}; + +class D +{ + A theA; + B theB; + C theC; + + bool preMarshalInvoked; + bool postUnmarshalInvoked(); +}; + +["protected"] class E +{ + int i; + string s; + + bool checkValues(); +}; + +class F +{ + ["protected"] E e1; + E e2; + + bool checkValues(); +}; + +interface I +{ +}; + +interface J extends I +{ +}; + +class H implements I +{ +}; + +class CompactExt; + +class Compact(1) +{ +}; + +const int CompactExtId = 789; + +class CompactExt(CompactExtId) extends Compact +{ +}; + +sequence<Object> ObjectSeq; // For Objective-C only +sequence<Object*> ObjectPrxSeq; // For Objective-C only +sequence<Base> BaseSeq; // For Objective-C only +sequence<Base*> BasePrxSeq; // For Objective-C only + +dictionary<string, Object> ObjectDict; // For Objective-C only +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 Initial +{ + void shutdown(); + B getB1(); + B getB2(); + C getC(); + D getD(); + E getE(); + F getF(); + + void getAll(out B b1, out B b2, out C theC, out D theD); + + I getI(); + I getJ(); + I getH(); + + void setI(I theI); + + BaseSeq opBaseSeq(BaseSeq inSeq, out BaseSeq outSeq); + + Compact getCompact(); + + // + // Remaining operations are here only for Objective-C and are not implemented by other language mappings. + // + ObjectSeq getObjectSeq(ObjectSeq s); + ObjectPrxSeq getObjectPrxSeq(ObjectPrxSeq s); + BaseSeq getBaseSeq(BaseSeq s); + BasePrxSeq getBasePrxSeq(BasePrxSeq s); + + ObjectDict getObjectDict(ObjectDict d); + ObjectPrxDict getObjectPrxDict(ObjectPrxDict d); + BaseDict getBaseDict(BaseDict d); + BasePrxDict getBasePrxDict(BasePrxDict d); +}; + +class Empty +{ +}; + +class AlsoEmpty +{ +}; + +interface UnexpectedObjectExceptionTest +{ + Empty op(); +}; + +// +// Remaining definitions are here to ensure that the generated code compiles. +// + +class COneMember +{ + Empty e; +}; + +class CTwoMembers +{ + Empty e1; + Empty e2; +}; + +exception EOneMember +{ + Empty e; +}; + +exception ETwoMembers +{ + Empty e1; + Empty e2; +}; + +struct SOneMember +{ + Empty e; +}; + +struct STwoMembers +{ + Empty e1; + Empty e2; +}; + +dictionary<int, COneMember> DOneMember; +dictionary<int, CTwoMembers> DTwoMembers; + +}; diff --git a/objc/test/Ice/objects/Server.m b/objc/test/Ice/objects/Server.m new file mode 100644 index 00000000000..8705df09ab9 --- /dev/null +++ b/objc/test/Ice/objects/Server.m @@ -0,0 +1,131 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <objects/TestI.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +@interface ServerMyObjectFactory : NSObject<ICEObjectFactory> +@end + +@implementation ServerMyObjectFactory +// Note that the object factory must not autorelease the +// returned objects. +-(ICEObject*) create:(NSString*)type +{ + if([type isEqualToString:@"::Test::I"]) + { + return [[TestObjectsI alloc] init]; + } + else if([type isEqualToString:@"::Test::J"]) + { + return [[TestObjectsJI alloc] init]; + } + else if([type isEqualToString:@"::Test::H"]) + { + return [[TestObjectsHI alloc] init]; + } + else + { + test(NO); // Should never be reached + } + return nil; +} + +-(void) destroy +{ + // Nothing to do +} +@end + +static int +run(id<ICECommunicator> communicator) +{ +#if defined(__clang__) && !__has_feature(objc_arc) + id<ICEObjectFactory> factory = [[[ServerMyObjectFactory alloc] init] autorelease]; +#else + id<ICEObjectFactory> factory = [[ServerMyObjectFactory alloc] init]; +#endif + [communicator addObjectFactory:factory sliceId:@"::Test::I"]; + [communicator addObjectFactory:factory sliceId:@"::Test::J"]; + [communicator addObjectFactory:factory sliceId:@"::Test::H"]; + + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* initial = [[[TestObjectsInitialI alloc] init] autorelease]; +#else + ICEObject* initial = [[TestObjectsInitialI alloc] init]; +#endif + [adapter add:initial identity:[communicator stringToIdentity:@"initial"]]; + +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* uoet = [[[UnexpectedObjectExceptionTestI alloc] init] autorelease]; +#else + ICEObject* uoet = [[UnexpectedObjectExceptionTestI alloc] init]; +#endif + [adapter add:uoet identity:[communicator stringToIdentity:@"uoet"]]; + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main objectsServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestObjects", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/objects/TestI.h b/objc/test/Ice/objects/TestI.h new file mode 100644 index 00000000000..cfbf2b39567 --- /dev/null +++ b/objc/test/Ice/objects/TestI.h @@ -0,0 +1,79 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <ObjectsTest.h> + +@interface TestObjectsBI : TestObjectsB<TestObjectsB> +{ + BOOL _postUnmarshalInvoked; +} +@end + +@interface TestObjectsCI : TestObjectsC<TestObjectsC> +{ + BOOL _postUnmarshalInvoked; +} +@end + +@interface TestObjectsDI : TestObjectsD<TestObjectsD> +{ + BOOL _postUnmarshalInvoked; +} +@end + +@interface TestObjectsEI : TestObjectsE<TestObjectsE> +@end + +@interface TestObjectsFI : TestObjectsF<TestObjectsF> +@end + +//@interface TestObjectsII : TestObjectsI<TestObjectsI> +//@end + +@interface TestObjectsJI : TestObjectsJ<TestObjectsJ> +@end + +@interface TestObjectsHI : TestObjectsH<TestObjectsH> +@end + +@interface TestObjectsInitialI : TestObjectsInitial<TestObjectsInitial> +{ + TestObjectsB* _b1; + TestObjectsB* _b2; + TestObjectsC* _c; + TestObjectsD* _d; + TestObjectsE* _e; + TestObjectsF* _f; +} +-(id) init; +-(void) shutdown:(ICECurrent*)current; +-(TestObjectsB *) getB1:(ICECurrent *)current; +-(TestObjectsB *) getB2:(ICECurrent *)current; +-(TestObjectsC *) getC:(ICECurrent *)current; +-(TestObjectsD *) getD:(ICECurrent *)current; +-(TestObjectsE *) getE:(ICECurrent *)current; +-(TestObjectsF *) getF:(ICECurrent *)current; +-(void) getAll:(TestObjectsB **)b1 b2:(TestObjectsB **)b2 theC:(TestObjectsC **)theC theD:(TestObjectsD **)theD current:(ICECurrent *)current; +-(TestObjectsI *) getI:(ICECurrent *)current; +-(TestObjectsI *) getJ:(ICECurrent *)current; +-(TestObjectsI *) getH:(ICECurrent *)current; +-(TestObjectsCompact*) getCompact:(ICECurrent*)current; +-(void) setI:(TestObjectsI *)theI current:(ICECurrent *)current; +-(TestObjectsObjectSeq *) getObjectSeq:(TestObjectsMutableObjectSeq *)s current:(ICECurrent *)current; +-(TestObjectsObjectPrxSeq *) getObjectPrxSeq:(TestObjectsMutableObjectPrxSeq *)s current:(ICECurrent *)current; +-(TestObjectsBaseSeq *) getBaseSeq:(TestObjectsMutableBaseSeq *)s current:(ICECurrent *)current; +-(TestObjectsBasePrxSeq *) getBasePrxSeq:(TestObjectsMutableBasePrxSeq *)s current:(ICECurrent *)current; +-(TestObjectsObjectDict *) getObjectDict:(TestObjectsMutableObjectDict *)d current:(ICECurrent *)current; +-(TestObjectsObjectPrxDict *) getObjectPrxDict:(TestObjectsMutableObjectPrxDict *)d current:(ICECurrent *)current; +-(TestObjectsBaseDict *) getBaseDict:(TestObjectsMutableBaseDict *)d current:(ICECurrent *)current; +-(TestObjectsBasePrxDict *) getBasePrxDict:(TestObjectsMutableBasePrxDict *)d current:(ICECurrent *)current; +@end + +@interface UnexpectedObjectExceptionTestI : ICEBlobject<ICEBlobject> +@end diff --git a/objc/test/Ice/objects/TestI.m b/objc/test/Ice/objects/TestI.m new file mode 100644 index 00000000000..006885a56fd --- /dev/null +++ b/objc/test/Ice/objects/TestI.m @@ -0,0 +1,328 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <objects/TestI.h> + +@implementation TestObjectsBI +-(BOOL) postUnmarshalInvoked:(ICECurrent*)current +{ + return _postUnmarshalInvoked; +} +-(void) ice_preMarshal +{ + preMarshalInvoked = YES; +} +-(void) ice_postUnmarshal +{ + _postUnmarshalInvoked = YES; +} + +@end + +@implementation TestObjectsCI +-(BOOL) postUnmarshalInvoked:(ICECurrent*)current +{ + return _postUnmarshalInvoked; +} +-(void) ice_preMarshal +{ + preMarshalInvoked = YES; +} +-(void) ice_postUnmarshal +{ + _postUnmarshalInvoked = YES; +} + +@end + +@implementation TestObjectsDI +-(BOOL) postUnmarshalInvoked:(ICECurrent*)current +{ + return _postUnmarshalInvoked; +} +-(void) ice_preMarshal +{ + preMarshalInvoked = YES; +} +-(void) ice_postUnmarshal +{ + _postUnmarshalInvoked = YES; +} +@end + +@implementation TestObjectsEI +-(id) init +{ + return [super init:1 s:@"hello"]; +} +-(BOOL) checkValues:(ICECurrent*)current +{ + return i == 1 && [s isEqualToString:@"hello"]; +} +@end + +@implementation TestObjectsFI +-(id) init:(TestObjectsE*)e1_ e2:(TestObjectsE*)e2_ +{ + self = [super init:e1_ e2:e2_]; + if(!self) + { + return nil; + } + return self; +} +-(BOOL) checkValues:(ICECurrent*)current +{ + return e1 && e1 == e2; +} +@end + +@implementation TestObjectsHI +@end + +/*@implementation TestObjectsII +-(void) dealloc +{ + printf("Deallocating Object"); +} +@end*/ + +@implementation TestObjectsJI +@end + +@implementation TestObjectsInitialI + +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + + _b1 = [[TestObjectsBI alloc] init]; + _b2 = [[TestObjectsBI alloc] init]; + _c = [[TestObjectsCI alloc] init]; + _d = [[TestObjectsDI alloc] init]; + _e = [[TestObjectsEI alloc] init]; + _f = [[TestObjectsFI alloc] init:_e e2:_e]; + + _b1.theA = _b2; // Cyclic reference to another B + _b1.theB = _b1; // Self reference. + _b1.theC = nil; // Null reference. + + _b2.theA = _b2; // Self reference, using base. + _b2.theB = _b1; // Cyclic reference to another B + _b2.theC = _c; // Cyclic reference to a C. + + _c.theB = _b2; // Cyclic reference to a B. + + _d.theA = _b1; // Reference to a B. + _d.theB = _b2; // Reference to a B. + _d.theC = nil; // Reference to a C. + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [_b1 release]; + [_b2 release]; + [_c release]; + [_d release]; + [_e release]; + [_f release]; + [super dealloc]; +} +#endif + +-(void) shutdown:(ICECurrent*)current +{ + _b1.theA = nil; // Break cyclic reference. + _b1.theB = nil; // Break cyclic reference. + + _b2.theA = nil; // Break cyclic reference. + _b2.theB = nil; // Break cyclic reference. + _b2.theC = nil; // Break cyclic reference. + + _c.theB = nil; // Break cyclic reference. + + _d.theA = nil; // Break cyclic reference. + _d.theB = nil; // Break cyclic reference. + _d.theC = nil; // Break cyclic reference. + [[current.adapter getCommunicator] shutdown]; +} + +-(TestObjectsB*) getB1:(ICECurrent*)current +{ + _b1.preMarshalInvoked = NO; + _b2.preMarshalInvoked = NO; + _c.preMarshalInvoked = NO; + return _b1; +} + +-(TestObjectsB*) getB2:(ICECurrent*)current +{ + _b1.preMarshalInvoked = NO; + _b2.preMarshalInvoked = NO; + _c.preMarshalInvoked = NO; + return _b2; +} + + +-(TestObjectsC*) getC:(ICECurrent*)current +{ + _b1.preMarshalInvoked = NO; + _b2.preMarshalInvoked = NO; + _c.preMarshalInvoked = NO; + return _c; +} + + +-(TestObjectsD*) getD:(ICECurrent*)current +{ + _b1.preMarshalInvoked = NO; + _b2.preMarshalInvoked = NO; + _c.preMarshalInvoked = NO; + _d.preMarshalInvoked = NO; + return _d; +} + + +-(TestObjectsE*) getE:(ICECurrent*)current +{ + return _e; +} + + +-(TestObjectsF*) getF:(ICECurrent*)current +{ + return _f; +} + + +-(void) getAll:(TestObjectsB **)b1 b2:(TestObjectsB **)b2 theC:(TestObjectsC **)theC theD:(TestObjectsD **)theD current:(ICECurrent *)current; +{ + _b1.preMarshalInvoked = NO; + _b2.preMarshalInvoked = NO; + _c.preMarshalInvoked = NO; + _d.preMarshalInvoked = NO; + *b1 = _b1; + *b2 = _b2; + *theC = _c; + *theD = _d; +} + +-(TestObjectsI*) getI:(ICECurrent*)current +{ +#if defined(__clang__) && !__has_feature(objc_arc) + return [[[TestObjectsI alloc] init] autorelease]; +#else + return [[TestObjectsI alloc] init]; +#endif +} + +-(TestObjectsI*) getJ:(ICECurrent*)current +{ +#if defined(__clang__) && !__has_feature(objc_arc) + return (TestObjectsI*)[[[TestObjectsJ alloc] init] autorelease]; +#else + return (TestObjectsI*)[[TestObjectsJ alloc] init]; +#endif +} + +-(TestObjectsI*) getH:(ICECurrent*)current +{ +#if defined(__clang__) && !__has_feature(objc_arc) + return (TestObjectsI*)[[[TestObjectsH alloc] init] autorelease]; +#else + return (TestObjectsI*)[[TestObjectsH alloc] init]; +#endif +} + +-(TestObjectsBaseSeq*) opBaseSeq:(TestObjectsMutableBaseSeq*)inSeq outSeq:(TestObjectsBaseSeq**)outSeq + current:(ICECurrent*)current +{ + *outSeq = inSeq; + return inSeq; +} + +-(TestObjectsCompact*) getCompact:(ICECurrent*)current +{ +#if defined(__clang__) && !__has_feature(objc_arc) + return (TestObjectsCompact*)[[[TestObjectsCompactExt alloc] init] autorelease]; +#else + return (TestObjectsCompact*)[[TestObjectsCompactExt alloc] init]; +#endif +} + +-(void) setI:(TestObjectsI*)i current:(ICECurrent*)current +{ +} + +-(TestObjectsObjectSeq *) getObjectSeq:(TestObjectsMutableObjectSeq *)s current:(ICECurrent*)current +{ + return s; +} + +-(TestObjectsObjectPrxSeq *) getObjectPrxSeq:(TestObjectsMutableObjectPrxSeq *)s current:(ICECurrent*)current +{ + return s; +} + +-(TestObjectsBaseSeq *) getBaseSeq:(TestObjectsMutableBaseSeq *)s current:(ICECurrent*)current +{ + return s; +} + +-(TestObjectsBasePrxSeq *) getBasePrxSeq:(TestObjectsMutableBasePrxSeq *)s current:(ICECurrent*)current +{ + return s; +} + +-(TestObjectsObjectDict *) getObjectDict:(TestObjectsMutableObjectDict *)d current:(ICECurrent*)current +{ + return d; +} + +-(TestObjectsObjectPrxDict *) getObjectPrxDict:(TestObjectsMutableObjectPrxDict *)d current:(ICECurrent*)current +{ + return d; +} + +-(TestObjectsBaseDict *) getBaseDict:(TestObjectsMutableBaseDict *)d current:(ICECurrent*)current +{ + return d; +} + +-(TestObjectsBasePrxDict *) getBasePrxDict:(TestObjectsMutableBasePrxDict *)d current:(ICECurrent*)current +{ + return d; +} +@end + +@implementation UnexpectedObjectExceptionTestI +-(BOOL)ice_invoke:(NSData*)inEncaps outEncaps:(NSMutableData**)outEncaps current:(ICECurrent*)current +{ + id<ICECommunicator> communicator = [current.adapter getCommunicator]; + id<ICEOutputStream> o = [ICEUtil createOutputStream:communicator]; + [o startEncapsulation]; +#if defined(__clang__) && !__has_feature(objc_arc) + TestObjectsAlsoEmpty* ae = [[[TestObjectsAlsoEmpty alloc] init] autorelease]; +#else + TestObjectsAlsoEmpty* ae = [[TestObjectsAlsoEmpty alloc] init]; +#endif + [o writeObject:ae]; + [o writePendingObjects]; + [o endEncapsulation]; + *outEncaps = [o finished]; + return YES; +} +@end diff --git a/objc/test/Ice/objects/run.py b/objc/test/Ice/objects/run.py new file mode 100755 index 00000000000..37acea1668c --- /dev/null +++ b/objc/test/Ice/objects/run.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +print("Running test with compact (default) format.") +TestUtil.clientServerTest() + +print("Running test with sliced format.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.SlicedFormat", + additionalServerOptions="--Ice.Default.SlicedFormat") + +print("Running test with 1.0 encoding.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", + additionalServerOptions="--Ice.Default.EncodingVersion=1.0") diff --git a/objc/test/Ice/objects/test.log b/objc/test/Ice/objects/test.log new file mode 100644 index 00000000000..3150beca6c7 --- /dev/null +++ b/objc/test/Ice/objects/test.log @@ -0,0 +1,1399 @@ +testing stringToProxy... ok +testing checked cast... ok +testing constructor, copy constructor, and assignment operator... ok +getting B1... starting server... ok +starting client... ok +2008-09-05 18:27:29.095 server[74756:2403] write Test::B +2008-09-05 18:27:29.098 client[74758:10b] read Test::B +2008-09-05 18:27:29.100 client[74758:10b] read Test::A +2008-09-05 18:27:29.101 client[74758:10b] readPendingObject +ok +getting B2... 2008-09-05 18:27:29.096 server[74756:2403] write Test::A +2008-09-05 18:27:29.102 server[74756:2203] write Test::B +2008-09-05 18:27:29.102 server[74756:2203] write Test::A +2008-09-05 18:27:29.103 server[74756:2203] write Test::B +2008-09-05 18:27:29.103 server[74756:2203] write Test::A +2008-09-05 18:27:29.104 server[74756:2203] write Test::B +2008-09-05 18:27:29.104 server[74756:2203] write Test::A +2008-09-05 18:27:29.105 server[74756:2203] write Test::B +2008-09-05 18:27:29.105 server[74756:2203] write Test::A +2008-09-05 18:27:29.105 server[74756:2203] write Test::B +2008-09-05 18:27:29.106 server[74756:2203] write Test::A +2008-09-05 18:27:29.106 server[74756:2203] write Test::B +2008-09-05 18:27:29.106 server[74756:2203] write Test::A +2008-09-05 18:27:29.107 server[74756:2203] write Test::B +2008-09-05 18:27:29.107 server[74756:2203] write Test::A +2008-09-05 18:27:29.108 server[74756:2203] write Test::B +2008-09-05 18:27:29.108 server[74756:2203] write Test::A +2008-09-05 18:27:29.108 server[74756:2203] write Test::B +2008-09-05 18:27:29.109 server[74756:2203] write Test::A +2008-09-05 18:27:29.109 server[74756:2203] write Test::B +2008-09-05 18:27:29.109 server[74756:2203] write Test::A +2008-09-05 18:27:29.110 server[74756:2203] write Test::B +2008-09-05 18:27:29.110 server[74756:2203] write Test::A +2008-09-05 18:27:29.110 server[74756:2203] write Test::B +2008-09-05 18:27:29.111 server[74756:2203] write Test::A +2008-09-05 18:27:29.111 server[74756:2203] write Test::B +2008-09-05 18:27:29.111 server[74756:2203] write Test::A +2008-09-05 18:27:29.112 server[74756:2203] write Test::B +2008-09-05 18:27:29.112 server[74756:2203] write Test::A +2008-09-05 18:27:29.113 server[74756:2203] write Test::B +2008-09-05 18:27:29.113 server[74756:2203] write Test::A +2008-09-05 18:27:29.113 server[74756:2203] write Test::B +2008-09-05 18:27:29.114 server[74756:2203] write Test::A +2008-09-05 18:27:29.114 server[74756:2203] write Test::B +2008-09-05 18:27:29.114 server[74756:2203] write Test::A +2008-09-05 18:27:29.115 server[74756:2203] write Test::B +2008-09-05 18:27:29.115 server[74756:2203] write Test::A +2008-09-05 18:27:29.115 server[74756:2203] write Test::B +2008-09-05 18:27:29.116 server[74756:2203] write Test::A +2008-09-05 18:27:29.116 server[74756:2203] write Test::B +2008-09-05 18:27:29.117 server[74756:2203] write Test::A +2008-09-05 18:27:29.117 server[74756:2203] write Test::B +2008-09-05 18:27:29.117 server[74756:2203] write Test::A +2008-09-05 18:27:29.118 server[74756:2203] write Test::B +2008-09-05 18:27:29.118 server[74756:2203] write Test::A +2008-09-05 18:27:29.118 server[74756:2203] write Test::B +2008-09-05 18:27:29.119 server[74756:2203] write Test::A +2008-09-05 18:27:29.119 server[74756:2203] write Test::B +2008-09-05 18:27:29.119 server[74756:2203] write Test::A +2008-09-05 18:27:29.120 server[74756:2203] write Test::B +2008-09-05 18:27:29.120 server[74756:2203] write Test::A +2008-09-05 18:27:29.120 server[74756:2203] write Test::B +2008-09-05 18:27:29.121 server[74756:2203] write Test::A +2008-09-05 18:27:29.121 server[74756:2203] write Test::B +2008-09-05 18:27:29.122 server[74756:2203] write Test::A +2008-09-05 18:27:29.122 server[74756:2203] write Test::B +2008-09-05 18:27:29.122 server[74756:2203] write Test::A +2008-09-05 18:27:29.123 server[74756:2203] write Test::B +2008-09-05 18:27:29.123 server[74756:2203] write Test::A +2008-09-05 18:27:29.123 server[74756:2203] write Test::B +2008-09-05 18:27:29.124 server[74756:2203] write Test::A +2008-09-05 18:27:29.124 server[74756:2203] write Test::B +2008-09-05 18:27:29.124 server[74756:2203] write Test::A +2008-09-05 18:27:29.125 server[74756:2203] write Test::B +2008-09-05 18:27:29.125 server[74756:2203] write Test::A +2008-09-05 18:27:29.126 server[74756:2203] write Test::B +2008-09-05 18:27:29.126 server[74756:2203] write Test::A +2008-09-05 18:27:29.126 server[74756:2203] write Test::B +2008-09-05 18:27:29.127 server[74756:2203] write Test::A +2008-09-05 18:27:29.127 server[74756:2203] write Test::B +2008-09-05 18:27:29.127 server[74756:2203] write Test::A +2008-09-05 18:27:29.128 server[74756:2203] write Test::B +2008-09-05 18:27:29.128 server[74756:2203] write Test::A +2008-09-05 18:27:29.128 server[74756:2203] write Test::B +2008-09-05 18:27:29.129 server[74756:2203] write Test::A +2008-09-05 18:27:29.129 server[74756:2203] write Test::B +2008-09-05 18:27:29.130 server[74756:2203] write Test::A +2008-09-05 18:27:29.130 server[74756:2203] write Test::B +2008-09-05 18:27:29.130 server[74756:2203] write Test::A +2008-09-05 18:27:29.131 server[74756:2203] write Test::B +2008-09-05 18:27:29.131 server[74756:2203] write Test::A +2008-09-05 18:27:29.131 server[74756:2203] write Test::B +2008-09-05 18:27:29.132 server[74756:2203] write Test::A +2008-09-05 18:27:29.132 server[74756:2203] write Test::B +2008-09-05 18:27:29.133 server[74756:2203] write Test::A +2008-09-05 18:27:29.133 server[74756:2203] write Test::B +2008-09-05 18:27:29.133 server[74756:2203] write Test::A +2008-09-05 18:27:29.134 server[74756:2203] write Test::B +2008-09-05 18:27:29.134 server[74756:2203] write Test::A +2008-09-05 18:27:29.134 server[74756:2203] write Test::B +2008-09-05 18:27:29.135 server[74756:2203] write Test::A +2008-09-05 18:27:29.135 server[74756:2203] write Test::B +2008-09-05 18:27:29.135 server[74756:2203] write Test::A +2008-09-05 18:27:29.136 server[74756:2203] write Test::B +2008-09-05 18:27:29.136 server[74756:2203] write Test::A +2008-09-05 18:27:29.137 server[74756:2203] write Test::B +2008-09-05 18:27:29.137 server[74756:2203] write Test::A +2008-09-05 18:27:29.137 server[74756:2203] write Test::B +2008-09-05 18:27:29.138 server[74756:2203] write Test::A +2008-09-05 18:27:29.138 server[74756:2203] write Test::B +2008-09-05 18:27:29.138 server[74756:2203] write Test::A +2008-09-05 18:27:29.139 server[74756:2203] write Test::B +2008-09-05 18:27:29.139 server[74756:2203] write Test::A +2008-09-05 18:27:29.140 server[74756:2203] write Test::B +2008-09-05 18:27:29.140 server[74756:2203] write Test::A +2008-09-05 18:27:29.140 server[74756:2203] write Test::B +2008-09-05 18:27:29.141 server[74756:2203] write Test::A +2008-09-05 18:27:29.141 server[74756:2203] write Test::B +2008-09-05 18:27:29.142 server[74756:2203] write Test::A +2008-09-05 18:27:29.142 server[74756:2203] write Test::B +2008-09-05 18:27:29.142 server[74756:2203] write Test::A +2008-09-05 18:27:29.143 server[74756:2203] write Test::B +2008-09-05 18:27:29.143 server[74756:2203] write Test::A +2008-09-05 18:27:29.144 server[74756:2203] write Test::B +2008-09-05 18:27:29.144 server[74756:2203] write Test::A +2008-09-05 18:27:29.144 server[74756:2203] write Test::B +2008-09-05 18:27:29.145 server[74756:2203] write Test::A +2008-09-05 18:27:29.145 server[74756:2203] write Test::B +2008-09-05 18:27:29.145 server[74756:2203] write Test::A +2008-09-05 18:27:29.146 server[74756:2203] write Test::B +2008-09-05 18:27:29.146 server[74756:2203] write Test::A +2008-09-05 18:27:29.147 server[74756:2203] write Test::B +2008-09-05 18:27:29.147 server[74756:2203] write Test::A +2008-09-05 18:27:29.147 server[74756:2203] write Test::B +2008-09-05 18:27:29.148 server[74756:2203] write Test::A +2008-09-05 18:27:29.148 server[74756:2203] write Test::B +2008-09-05 18:27:29.148 server[74756:2203] write Test::A +2008-09-05 18:27:29.149 server[74756:2203] write Test::B +2008-09-05 18:27:29.149 server[74756:2203] write Test::A +2008-09-05 18:27:29.150 server[74756:2203] write Test::B +2008-09-05 18:27:29.150 server[74756:2203] write Test::A +2008-09-05 18:27:29.150 server[74756:2203] write Test::B +2008-09-05 18:27:29.151 server[74756:2203] write Test::A +2008-09-05 18:27:29.151 server[74756:2203] write Test::B +2008-09-05 18:27:29.151 server[74756:2203] write Test::A +2008-09-05 18:27:29.152 server[74756:2203] write Test::B +2008-09-05 18:27:29.152 server[74756:2203] write Test::A +2008-09-05 18:27:29.152 server[74756:2203] write Test::B +2008-09-05 18:27:29.153 server[74756:2203] write Test::A +2008-09-05 18:27:29.153 server[74756:2203] write Test::B +2008-09-05 18:27:29.153 server[74756:2203] write Test::A +2008-09-05 18:27:29.154 server[74756:2203] write Test::B +2008-09-05 18:27:29.154 server[74756:2203] write Test::A +2008-09-05 18:27:29.155 server[74756:2203] write Test::B +2008-09-05 18:27:29.155 server[74756:2203] write Test::A +2008-09-05 18:27:29.155 server[74756:2203] write Test::B +2008-09-05 18:27:29.156 server[74756:2203] write Test::A +2008-09-05 18:27:29.156 server[74756:2203] write Test::B +2008-09-05 18:27:29.156 server[74756:2203] write Test::A +2008-09-05 18:27:29.157 server[74756:2203] write Test::B +2008-09-05 18:27:29.157 server[74756:2203] write Test::A +2008-09-05 18:27:29.157 server[74756:2203] write Test::B +2008-09-05 18:27:29.158 server[74756:2203] write Test::A +2008-09-05 18:27:29.158 server[74756:2203] write Test::B +2008-09-05 18:27:29.159 server[74756:2203] write Test::A +2008-09-05 18:27:29.159 server[74756:2203] write Test::B +2008-09-05 18:27:29.159 server[74756:2203] write Test::A +2008-09-05 18:27:29.160 server[74756:2203] write Test::B +2008-09-05 18:27:29.160 server[74756:2203] write Test::A +2008-09-05 18:27:29.160 server[74756:2203] write Test::B +2008-09-05 18:27:29.161 server[74756:2203] write Test::A +2008-09-05 18:27:29.161 server[74756:2203] write Test::B +2008-09-05 18:27:29.162 server[74756:2203] write Test::A +2008-09-05 18:27:29.162 server[74756:2203] write Test::B +2008-09-05 18:27:29.162 server[74756:2203] write Test::A +2008-09-05 18:27:29.163 server[74756:2203] write Test::B +2008-09-05 18:27:29.163 server[74756:2203] write Test::A +2008-09-05 18:27:29.164 server[74756:2203] write Test::B +2008-09-05 18:27:29.165 server[74756:2203] write Test::A +2008-09-05 18:27:29.165 server[74756:2203] write Test::B +2008-09-05 18:27:29.166 server[74756:2203] write Test::A +2008-09-05 18:27:29.166 server[74756:2203] write Test::B +2008-09-05 18:27:29.166 server[74756:2203] write Test::A +2008-09-05 18:27:29.167 server[74756:2203] write Test::B +2008-09-05 18:27:29.167 server[74756:2203] write Test::A +2008-09-05 18:27:29.168 server[74756:2203] write Test::B +2008-09-05 18:27:29.170 server[74756:2203] write Test::A +2008-09-05 18:27:29.170 server[74756:2203] write Test::B +2008-09-05 18:27:29.170 server[74756:2203] write Test::A +2008-09-05 18:27:29.171 server[74756:2203] write Test::B +2008-09-05 18:27:29.171 server[74756:2203] write Test::A +2008-09-05 18:27:29.171 server[74756:2203] write Test::B +2008-09-05 18:27:29.172 server[74756:2203] write Test::A +2008-09-05 18:27:29.172 server[74756:2203] write Test::B +2008-09-05 18:27:29.173 server[74756:2203] write Test::A +2008-09-05 18:27:29.173 server[74756:2203] write Test::B +2008-09-05 18:27:29.173 server[74756:2203] write Test::A +2008-09-05 18:27:29.174 server[74756:2203] write Test::B +2008-09-05 18:27:29.174 server[74756:2203] write Test::A +2008-09-05 18:27:29.174 server[74756:2203] write Test::B +2008-09-05 18:27:29.175 server[74756:2203] write Test::A +2008-09-05 18:27:29.175 server[74756:2203] write Test::B +2008-09-05 18:27:29.176 server[74756:2203] write Test::A +2008-09-05 18:27:29.176 server[74756:2203] write Test::B +2008-09-05 18:27:29.176 server[74756:2203] write Test::A +2008-09-05 18:27:29.177 server[74756:2203] write Test::B +2008-09-05 18:27:29.177 server[74756:2203] write Test::A +2008-09-05 18:27:29.178 server[74756:2203] write Test::B +2008-09-05 18:27:29.178 server[74756:2203] write Test::A +2008-09-05 18:27:29.178 server[74756:2203] write Test::B +2008-09-05 18:27:29.179 server[74756:2203] write Test::A +2008-09-05 18:27:29.179 server[74756:2203] write Test::B +2008-09-05 18:27:29.179 server[74756:2203] write Test::A +2008-09-05 18:27:29.180 server[74756:2203] write Test::B +2008-09-05 18:27:29.180 server[74756:2203] write Test::A +2008-09-05 18:27:29.181 server[74756:2203] write Test::B +2008-09-05 18:27:29.181 server[74756:2203] write Test::A +2008-09-05 18:27:29.181 server[74756:2203] write Test::B +2008-09-05 18:27:29.182 server[74756:2203] write Test::A +2008-09-05 18:27:29.182 server[74756:2203] write Test::B +2008-09-05 18:27:29.182 server[74756:2203] write Test::A +2008-09-05 18:27:29.183 server[74756:2203] write Test::B +2008-09-05 18:27:29.183 server[74756:2203] write Test::A +2008-09-05 18:27:29.184 server[74756:2203] write Test::B +2008-09-05 18:27:29.184 server[74756:2203] write Test::A +2008-09-05 18:27:29.184 server[74756:2203] write Test::B +2008-09-05 18:27:29.185 server[74756:2203] write Test::A +2008-09-05 18:27:29.185 server[74756:2203] write Test::B +2008-09-05 18:27:29.186 server[74756:2203] write Test::A +2008-09-05 18:27:29.186 server[74756:2203] write Test::B +2008-09-05 18:27:29.186 server[74756:2203] write Test::A +2008-09-05 18:27:29.187 server[74756:2203] write Test::B +2008-09-05 18:27:29.187 server[74756:2203] write Test::A +2008-09-05 18:27:29.187 server[74756:2203] write Test::B +2008-09-05 18:27:29.188 server[74756:2203] write Test::A +2008-09-05 18:27:29.188 server[74756:2203] write Test::B +2008-09-05 18:27:29.189 server[74756:2203] write Test::A +2008-09-05 18:27:29.189 server[74756:2203] write Test::B +2008-09-05 18:27:29.189 server[74756:2203] write Test::A +2008-09-05 18:27:29.190 server[74756:2203] write Test::B +2008-09-05 18:27:29.190 server[74756:2203] write Test::A +2008-09-05 18:27:29.191 server[74756:2203] write Test::B +2008-09-05 18:27:29.191 server[74756:2203] write Test::A +2008-09-05 18:27:29.191 server[74756:2203] write Test::B +2008-09-05 18:27:29.192 server[74756:2203] write Test::A +2008-09-05 18:27:29.192 server[74756:2203] write Test::B +2008-09-05 18:27:29.192 server[74756:2203] write Test::A +2008-09-05 18:27:29.193 server[74756:2203] write Test::B +2008-09-05 18:27:29.193 server[74756:2203] write Test::A +2008-09-05 18:27:29.194 server[74756:2203] write Test::B +2008-09-05 18:27:29.194 server[74756:2203] write Test::A +2008-09-05 18:27:29.194 server[74756:2203] write Test::B +2008-09-05 18:27:29.195 server[74756:2203] write Test::A +2008-09-05 18:27:29.196 server[74756:2203] write Test::B +2008-09-05 18:27:29.197 server[74756:2203] write Test::A +2008-09-05 18:27:29.198 server[74756:2203] write Test::B +2008-09-05 18:27:29.198 server[74756:2203] write Test::A +2008-09-05 18:27:29.199 server[74756:2203] write Test::B +2008-09-05 18:27:29.199 server[74756:2203] write Test::A +2008-09-05 18:27:29.199 server[74756:2203] write Test::B +2008-09-05 18:27:29.200 server[74756:2203] write Test::A +2008-09-05 18:27:29.200 server[74756:2203] write Test::B +2008-09-05 18:27:29.200 server[74756:2203] write Test::A +2008-09-05 18:27:29.201 server[74756:2203] write Test::B +2008-09-05 18:27:29.201 server[74756:2203] write Test::A +2008-09-05 18:27:29.202 server[74756:2203] write Test::B +2008-09-05 18:27:29.202 server[74756:2203] write Test::A +2008-09-05 18:27:29.202 server[74756:2203] write Test::B +2008-09-05 18:27:29.203 server[74756:2203] write Test::A +2008-09-05 18:27:29.203 server[74756:2203] write Test::B +2008-09-05 18:27:29.204 server[74756:2203] write Test::A +2008-09-05 18:27:29.204 server[74756:2203] write Test::B +2008-09-05 18:27:29.204 server[74756:2203] write Test::A +2008-09-05 18:27:29.205 server[74756:2203] write Test::B +2008-09-05 18:27:29.205 server[74756:2203] write Test::A +2008-09-05 18:27:29.205 server[74756:2203] write Test::B +2008-09-05 18:27:29.206 server[74756:2203] write Test::A +2008-09-05 18:27:29.206 server[74756:2203] write Test::B +2008-09-05 18:27:29.207 server[74756:2203] write Test::A +2008-09-05 18:27:29.207 server[74756:2203] write Test::B +2008-09-05 18:27:29.207 server[74756:2203] write Test::A +2008-09-05 18:27:29.208 server[74756:2203] write Test::B +2008-09-05 18:27:29.208 server[74756:2203] write Test::A +2008-09-05 18:27:29.209 server[74756:2203] write Test::B +2008-09-05 18:27:29.209 server[74756:2203] write Test::A +2008-09-05 18:27:29.209 server[74756:2203] write Test::B +2008-09-05 18:27:29.210 server[74756:2203] write Test::A +2008-09-05 18:27:29.210 server[74756:2203] write Test::B +2008-09-05 18:27:29.211 server[74756:2203] write Test::A +2008-09-05 18:27:29.211 server[74756:2203] write Test::B +2008-09-05 18:27:29.212 server[74756:2203] write Test::A +2008-09-05 18:27:29.213 server[74756:2203] write Test::B +2008-09-05 18:27:29.213 server[74756:2203] write Test::A +2008-09-05 18:27:29.214 server[74756:2203] write Test::B +2008-09-05 18:27:29.214 server[74756:2203] write Test::A +2008-09-05 18:27:29.215 server[74756:2203] write Test::B +2008-09-05 18:27:29.215 server[74756:2203] write Test::A +2008-09-05 18:27:29.216 server[74756:2203] write Test::B +2008-09-05 18:27:29.216 server[74756:2203] write Test::A +2008-09-05 18:27:29.216 server[74756:2203] write Test::B +2008-09-05 18:27:29.217 server[74756:2203] write Test::A +2008-09-05 18:27:29.217 server[74756:2203] write Test::B +2008-09-05 18:27:29.217 server[74756:2203] write Test::A +2008-09-05 18:27:29.218 server[74756:2203] write Test::B +2008-09-05 18:27:29.218 server[74756:2203] write Test::A +2008-09-05 18:27:29.219 server[74756:2203] write Test::B +2008-09-05 18:27:29.219 server[74756:2203] write Test::A +2008-09-05 18:27:29.219 server[74756:2203] write Test::B +2008-09-05 18:27:29.220 server[74756:2203] write Test::A +2008-09-05 18:27:29.220 server[74756:2203] write Test::B +2008-09-05 18:27:29.221 server[74756:2203] write Test::A +2008-09-05 18:27:29.221 server[74756:2203] write Test::B +2008-09-05 18:27:29.221 server[74756:2203] write Test::A +2008-09-05 18:27:29.222 server[74756:2203] write Test::B +2008-09-05 18:27:29.222 server[74756:2203] write Test::A +2008-09-05 18:27:29.222 server[74756:2203] write Test::B +2008-09-05 18:27:29.223 server[74756:2203] write Test::A +2008-09-05 18:27:29.223 server[74756:2203] write Test::B +2008-09-05 18:27:29.224 server[74756:2203] write Test::A +2008-09-05 18:27:29.224 server[74756:2203] write Test::B +2008-09-05 18:27:29.224 server[74756:2203] write Test::A +2008-09-05 18:27:29.225 server[74756:2203] write Test::B +2008-09-05 18:27:29.225 server[74756:2203] write Test::A +2008-09-05 18:27:29.226 server[74756:2203] write Test::B +2008-09-05 18:27:29.226 server[74756:2203] write Test::A +2008-09-05 18:27:29.226 server[74756:2203] write Test::B +2008-09-05 18:27:29.227 server[74756:2203] write Test::A +2008-09-05 18:27:29.227 server[74756:2203] write Test::B +2008-09-05 18:27:29.228 server[74756:2203] write Test::A +2008-09-05 18:27:29.228 server[74756:2203] write Test::B +2008-09-05 18:27:29.228 server[74756:2203] write Test::A +2008-09-05 18:27:29.229 server[74756:2203] write Test::B +2008-09-05 18:27:29.229 server[74756:2203] write Test::A +2008-09-05 18:27:29.230 server[74756:2203] write Test::B +2008-09-05 18:27:29.230 server[74756:2203] write Test::A +2008-09-05 18:27:29.230 server[74756:2203] write Test::B +2008-09-05 18:27:29.231 server[74756:2203] write Test::A +2008-09-05 18:27:29.233 server[74756:2203] write Test::B +2008-09-05 18:27:29.233 server[74756:2203] write Test::A +2008-09-05 18:27:29.233 server[74756:2203] write Test::B +2008-09-05 18:27:29.234 server[74756:2203] write Test::A +2008-09-05 18:27:29.234 server[74756:2203] write Test::B +2008-09-05 18:27:29.235 server[74756:2203] write Test::A +2008-09-05 18:27:29.235 server[74756:2203] write Test::B +2008-09-05 18:27:29.235 server[74756:2203] write Test::A +2008-09-05 18:27:29.236 server[74756:2203] write Test::B +2008-09-05 18:27:29.236 server[74756:2203] write Test::A +2008-09-05 18:27:29.236 server[74756:2203] write Test::B +2008-09-05 18:27:29.237 server[74756:2203] write Test::A +2008-09-05 18:27:29.237 server[74756:2203] write Test::B +2008-09-05 18:27:29.238 server[74756:2203] write Test::A +2008-09-05 18:27:29.238 server[74756:2203] write Test::B +2008-09-05 18:27:29.238 server[74756:2203] write Test::A +2008-09-05 18:27:29.239 server[74756:2203] write Test::B +2008-09-05 18:27:29.239 server[74756:2203] write Test::A +2008-09-05 18:27:29.239 server[74756:2203] write Test::B +2008-09-05 18:27:29.240 server[74756:2203] write Test::A +2008-09-05 18:27:29.240 server[74756:2203] write Test::B +2008-09-05 18:27:29.240 server[74756:2203] write Test::A +2008-09-05 18:27:29.241 server[74756:2203] write Test::B +2008-09-05 18:27:29.241 server[74756:2203] write Test::A +2008-09-05 18:27:29.241 server[74756:2203] write Test::B +2008-09-05 18:27:29.242 server[74756:2203] write Test::A +2008-09-05 18:27:29.242 server[74756:2203] write Test::B +2008-09-05 18:27:29.242 server[74756:2203] write Test::A +2008-09-05 18:27:29.243 server[74756:2203] write Test::B +2008-09-05 18:27:29.243 server[74756:2203] write Test::A +2008-09-05 18:27:29.244 server[74756:2203] write Test::B +2008-09-05 18:27:29.244 server[74756:2203] write Test::A +2008-09-05 18:27:29.244 server[74756:2203] write Test::B +2008-09-05 18:27:29.245 server[74756:2203] write Test::A +2008-09-05 18:27:29.245 server[74756:2203] write Test::B +2008-09-05 18:27:29.246 server[74756:2203] write Test::A +2008-09-05 18:27:29.246 server[74756:2203] write Test::B +2008-09-05 18:27:29.246 server[74756:2203] write Test::A +2008-09-05 18:27:29.247 server[74756:2203] write Test::B +2008-09-05 18:27:29.247 server[74756:2203] write Test::A +2008-09-05 18:27:29.247 server[74756:2203] write Test::B +2008-09-05 18:27:29.248 server[74756:2203] write Test::A +2008-09-05 18:27:29.248 server[74756:2203] write Test::B +2008-09-05 18:27:29.249 server[74756:2203] write Test::A +2008-09-05 18:27:29.249 server[74756:2203] write Test::B +2008-09-05 18:27:29.249 server[74756:2203] write Test::A +2008-09-05 18:27:29.250 server[74756:2203] write Test::B +2008-09-05 18:27:29.250 server[74756:2203] write Test::A +2008-09-05 18:27:29.250 server[74756:2203] write Test::B +2008-09-05 18:27:29.251 server[74756:2203] write Test::A +2008-09-05 18:27:29.251 server[74756:2203] write Test::B +2008-09-05 18:27:29.252 server[74756:2203] write Test::A +2008-09-05 18:27:29.252 server[74756:2203] write Test::B +2008-09-05 18:27:29.252 server[74756:2203] write Test::A +2008-09-05 18:27:29.253 server[74756:2203] write Test::B +2008-09-05 18:27:29.253 server[74756:2203] write Test::A +2008-09-05 18:27:29.254 server[74756:2203] write Test::B +2008-09-05 18:27:29.255 server[74756:2203] write Test::A +2008-09-05 18:27:29.255 server[74756:2203] write Test::B +2008-09-05 18:27:29.255 server[74756:2203] write Test::A +2008-09-05 18:27:29.256 server[74756:2203] write Test::B +2008-09-05 18:27:29.256 server[74756:2203] write Test::A +2008-09-05 18:27:29.257 server[74756:2203] write Test::B +2008-09-05 18:27:29.257 server[74756:2203] write Test::A +2008-09-05 18:27:29.257 server[74756:2203] write Test::B +2008-09-05 18:27:29.258 server[74756:2203] write Test::A +2008-09-05 18:27:29.258 server[74756:2203] write Test::B +2008-09-05 18:27:29.259 server[74756:2203] write Test::A +2008-09-05 18:27:29.259 server[74756:2203] write Test::B +2008-09-05 18:27:29.259 server[74756:2203] write Test::A +2008-09-05 18:27:29.260 server[74756:2203] write Test::B +2008-09-05 18:27:29.260 server[74756:2203] write Test::A +2008-09-05 18:27:29.261 server[74756:2203] write Test::B +2008-09-05 18:27:29.261 server[74756:2203] write Test::A +2008-09-05 18:27:29.261 server[74756:2203] write Test::B +2008-09-05 18:27:29.262 server[74756:2203] write Test::A +2008-09-05 18:27:29.262 server[74756:2203] write Test::B +2008-09-05 18:27:29.263 server[74756:2203] write Test::A +2008-09-05 18:27:29.263 server[74756:2203] write Test::B +2008-09-05 18:27:29.264 server[74756:2203] write Test::A +2008-09-05 18:27:29.264 server[74756:2203] write Test::B +2008-09-05 18:27:29.265 server[74756:2203] write Test::A +2008-09-05 18:27:29.265 server[74756:2203] write Test::B +2008-09-05 18:27:29.265 server[74756:2203] write Test::A +2008-09-05 18:27:29.266 server[74756:2203] write Test::B +2008-09-05 18:27:29.266 server[74756:2203] write Test::A +2008-09-05 18:27:29.267 server[74756:2203] write Test::B +2008-09-05 18:27:29.267 server[74756:2203] write Test::A +2008-09-05 18:27:29.268 server[74756:2203] write Test::B +2008-09-05 18:27:29.268 server[74756:2203] write Test::A +2008-09-05 18:27:29.268 server[74756:2203] write Test::B +2008-09-05 18:27:29.269 server[74756:2203] write Test::A +2008-09-05 18:27:29.270 server[74756:2203] write Test::B +2008-09-05 18:27:29.270 server[74756:2203] write Test::A +2008-09-05 18:27:29.271 server[74756:2203] write Test::B +2008-09-05 18:27:29.271 server[74756:2203] write Test::A +2008-09-05 18:27:29.271 server[74756:2203] write Test::B +2008-09-05 18:27:29.272 server[74756:2203] write Test::A +2008-09-05 18:27:29.272 server[74756:2203] write Test::B +2008-09-05 18:27:29.273 server[74756:2203] write Test::A +2008-09-05 18:27:29.273 server[74756:2203] write Test::B +2008-09-05 18:27:29.273 server[74756:2203] write Test::A +2008-09-05 18:27:29.274 server[74756:2203] write Test::B +2008-09-05 18:27:29.274 server[74756:2203] write Test::A +2008-09-05 18:27:29.275 server[74756:2203] write Test::B +2008-09-05 18:27:29.275 server[74756:2203] write Test::A +2008-09-05 18:27:29.275 server[74756:2203] write Test::B +2008-09-05 18:27:29.276 server[74756:2203] write Test::A +2008-09-05 18:27:29.276 server[74756:2203] write Test::B +2008-09-05 18:27:29.277 server[74756:2203] write Test::A +2008-09-05 18:27:29.277 server[74756:2203] write Test::B +2008-09-05 18:27:29.278 server[74756:2203] write Test::A +2008-09-05 18:27:29.278 server[74756:2203] write Test::B +2008-09-05 18:27:29.278 server[74756:2203] write Test::A +2008-09-05 18:27:29.279 server[74756:2203] write Test::B +2008-09-05 18:27:29.279 server[74756:2203] write Test::A +2008-09-05 18:27:29.281 server[74756:2203] write Test::B +2008-09-05 18:27:29.282 server[74756:2203] write Test::A +2008-09-05 18:27:29.283 server[74756:2203] write Test::B +2008-09-05 18:27:29.283 server[74756:2203] write Test::A +2008-09-05 18:27:29.283 server[74756:2203] write Test::B +2008-09-05 18:27:29.284 server[74756:2203] write Test::A +2008-09-05 18:27:29.284 server[74756:2203] write Test::B +2008-09-05 18:27:29.285 server[74756:2203] write Test::A +2008-09-05 18:27:29.285 server[74756:2203] write Test::B +2008-09-05 18:27:29.286 server[74756:2203] write Test::A +2008-09-05 18:27:29.286 server[74756:2203] write Test::B +2008-09-05 18:27:29.286 server[74756:2203] write Test::A +2008-09-05 18:27:29.287 server[74756:2203] write Test::B +2008-09-05 18:27:29.287 server[74756:2203] write Test::A +2008-09-05 18:27:29.288 server[74756:2203] write Test::B +2008-09-05 18:27:29.288 server[74756:2203] write Test::A +2008-09-05 18:27:29.288 server[74756:2203] write Test::B +2008-09-05 18:27:29.289 server[74756:2203] write Test::A +2008-09-05 18:27:29.289 server[74756:2203] write Test::B +2008-09-05 18:27:29.290 server[74756:2203] write Test::A +2008-09-05 18:27:29.291 server[74756:2203] write Test::B +2008-09-05 18:27:29.291 server[74756:2203] write Test::A +2008-09-05 18:27:29.291 server[74756:2203] write Test::B +2008-09-05 18:27:29.292 server[74756:2203] write Test::A +2008-09-05 18:27:29.292 server[74756:2203] write Test::B +2008-09-05 18:27:29.293 server[74756:2203] write Test::A +2008-09-05 18:27:29.293 server[74756:2203] write Test::B +2008-09-05 18:27:29.293 server[74756:2203] write Test::A +2008-09-05 18:27:29.295 server[74756:2203] write Test::B +2008-09-05 18:27:29.295 server[74756:2203] write Test::A +2008-09-05 18:27:29.295 server[74756:2203] write Test::B +2008-09-05 18:27:29.296 server[74756:2203] write Test::A +2008-09-05 18:27:29.299 server[74756:2203] write Test::B +2008-09-05 18:27:29.299 server[74756:2203] write Test::A +2008-09-05 18:27:29.300 server[74756:2203] write Test::B +2008-09-05 18:27:29.300 server[74756:2203] write Test::A +2008-09-05 18:27:29.300 server[74756:2203] write Test::B +2008-09-05 18:27:29.301 server[74756:2203] write Test::A +2008-09-05 18:27:29.301 server[74756:2203] write Test::B +2008-09-05 18:27:29.301 server[74756:2203] write Test::A +2008-09-05 18:27:29.302 server[74756:2203] write Test::B +2008-09-05 18:27:29.302 server[74756:2203] write Test::A +2008-09-05 18:27:29.302 server[74756:2203] write Test::B +2008-09-05 18:27:29.303 server[74756:2203] write Test::A +2008-09-05 18:27:29.303 server[74756:2203] write Test::B +2008-09-05 18:27:29.303 server[74756:2203] write Test::A +2008-09-05 18:27:29.304 server[74756:2203] write Test::B +2008-09-05 18:27:29.304 server[74756:2203] write Test::A +2008-09-05 18:27:29.305 server[74756:2203] write Test::B +2008-09-05 18:27:29.305 server[74756:2203] write Test::A +2008-09-05 18:27:29.305 server[74756:2203] write Test::B +2008-09-05 18:27:29.306 server[74756:2203] write Test::A +2008-09-05 18:27:29.306 server[74756:2203] write Test::B +2008-09-05 18:27:29.306 server[74756:2203] write Test::A +2008-09-05 18:27:29.307 server[74756:2203] write Test::B +2008-09-05 18:27:29.307 server[74756:2203] write Test::A +2008-09-05 18:27:29.307 server[74756:2203] write Test::B +2008-09-05 18:27:29.308 server[74756:2203] write Test::A +2008-09-05 18:27:29.308 server[74756:2203] write Test::B +2008-09-05 18:27:29.308 server[74756:2203] write Test::A +2008-09-05 18:27:29.309 server[74756:2203] write Test::B +2008-09-05 18:27:29.309 server[74756:2203] write Test::A +2008-09-05 18:27:29.309 server[74756:2203] write Test::B +2008-09-05 18:27:29.310 server[74756:2203] write Test::A +2008-09-05 18:27:29.311 server[74756:2203] write Test::B +2008-09-05 18:27:29.311 server[74756:2203] write Test::A +2008-09-05 18:27:29.311 server[74756:2203] write Test::B +2008-09-05 18:27:29.312 server[74756:2203] write Test::A +2008-09-05 18:27:29.312 server[74756:2203] write Test::B +2008-09-05 18:27:29.312 server[74756:2203] write Test::A +2008-09-05 18:27:29.313 server[74756:2203] write Test::B +2008-09-05 18:27:29.313 server[74756:2203] write Test::A +2008-09-05 18:27:29.314 server[74756:2203] write Test::B +2008-09-05 18:27:29.314 server[74756:2203] write Test::A +2008-09-05 18:27:29.314 server[74756:2203] write Test::B +2008-09-05 18:27:29.315 server[74756:2203] write Test::A +2008-09-05 18:27:29.315 server[74756:2203] write Test::B +2008-09-05 18:27:29.315 server[74756:2203] write Test::A +2008-09-05 18:27:29.316 server[74756:2203] write Test::B +2008-09-05 18:27:29.316 server[74756:2203] write Test::A +2008-09-05 18:27:29.316 server[74756:2203] write Test::B +2008-09-05 18:27:29.317 server[74756:2203] write Test::A +2008-09-05 18:27:29.317 server[74756:2203] write Test::B +2008-09-05 18:27:29.317 server[74756:2203] write Test::A +2008-09-05 18:27:29.318 server[74756:2203] write Test::B +2008-09-05 18:27:29.318 server[74756:2203] write Test::A +2008-09-05 18:27:29.318 server[74756:2203] write Test::B +2008-09-05 18:27:29.319 server[74756:2203] write Test::A +2008-09-05 18:27:29.319 server[74756:2203] write Test::B +2008-09-05 18:27:29.320 server[74756:2203] write Test::A +2008-09-05 18:27:29.320 server[74756:2203] write Test::B +2008-09-05 18:27:29.320 server[74756:2203] write Test::A +2008-09-05 18:27:29.321 server[74756:2203] write Test::B +2008-09-05 18:27:29.321 server[74756:2203] write Test::A +2008-09-05 18:27:29.321 server[74756:2203] write Test::B +2008-09-05 18:27:29.322 server[74756:2203] write Test::A +2008-09-05 18:27:29.322 server[74756:2203] write Test::B +2008-09-05 18:27:29.322 server[74756:2203] write Test::A +2008-09-05 18:27:29.323 server[74756:2203] write Test::B +2008-09-05 18:27:29.323 server[74756:2203] write Test::A +2008-09-05 18:27:29.323 server[74756:2203] write Test::B +2008-09-05 18:27:29.324 server[74756:2203] write Test::A +2008-09-05 18:27:29.324 server[74756:2203] write Test::B +2008-09-05 18:27:29.324 server[74756:2203] write Test::A +2008-09-05 18:27:29.325 server[74756:2203] write Test::B +2008-09-05 18:27:29.325 server[74756:2203] write Test::A +2008-09-05 18:27:29.326 server[74756:2203] write Test::B +2008-09-05 18:27:29.326 server[74756:2203] write Test::A +2008-09-05 18:27:29.326 server[74756:2203] write Test::B +2008-09-05 18:27:29.327 server[74756:2203] write Test::A +2008-09-05 18:27:29.327 server[74756:2203] write Test::B +2008-09-05 18:27:29.327 server[74756:2203] write Test::A +2008-09-05 18:27:29.328 server[74756:2203] write Test::B +2008-09-05 18:27:29.328 server[74756:2203] write Test::A +2008-09-05 18:27:29.328 server[74756:2203] write Test::B +2008-09-05 18:27:29.329 server[74756:2203] write Test::A +2008-09-05 18:27:29.329 server[74756:2203] write Test::B +2008-09-05 18:27:29.329 server[74756:2203] write Test::A +2008-09-05 18:27:29.330 server[74756:2203] write Test::B +2008-09-05 18:27:29.330 server[74756:2203] write Test::A +2008-09-05 18:27:29.331 server[74756:2203] write Test::B +2008-09-05 18:27:29.331 server[74756:2203] write Test::A +2008-09-05 18:27:29.331 server[74756:2203] write Test::B +2008-09-05 18:27:29.332 server[74756:2203] write Test::A +2008-09-05 18:27:29.332 server[74756:2203] write Test::B +2008-09-05 18:27:29.332 server[74756:2203] write Test::A +2008-09-05 18:27:29.333 server[74756:2203] write Test::B +2008-09-05 18:27:29.333 server[74756:2203] write Test::A +2008-09-05 18:27:29.333 server[74756:2203] write Test::B +2008-09-05 18:27:29.334 server[74756:2203] write Test::A +2008-09-05 18:27:29.334 server[74756:2203] write Test::B +2008-09-05 18:27:29.334 server[74756:2203] write Test::A +2008-09-05 18:27:29.335 server[74756:2203] write Test::B +2008-09-05 18:27:29.335 server[74756:2203] write Test::A +2008-09-05 18:27:29.336 server[74756:2203] write Test::B +2008-09-05 18:27:29.336 server[74756:2203] write Test::A +2008-09-05 18:27:29.336 server[74756:2203] write Test::B +2008-09-05 18:27:29.338 server[74756:2203] write Test::A +2008-09-05 18:27:29.339 server[74756:2203] write Test::B +2008-09-05 18:27:29.339 server[74756:2203] write Test::A +2008-09-05 18:27:29.339 server[74756:2203] write Test::B +2008-09-05 18:27:29.340 server[74756:2203] write Test::A +2008-09-05 18:27:29.340 server[74756:2203] write Test::B +2008-09-05 18:27:29.341 server[74756:2203] write Test::A +2008-09-05 18:27:29.341 server[74756:2203] write Test::B +2008-09-05 18:27:29.341 server[74756:2203] write Test::A +2008-09-05 18:27:29.342 server[74756:2203] write Test::B +2008-09-05 18:27:29.342 server[74756:2203] write Test::A +2008-09-05 18:27:29.343 server[74756:2203] write Test::B +2008-09-05 18:27:29.343 server[74756:2203] write Test::A +2008-09-05 18:27:29.343 server[74756:2203] write Test::B +2008-09-05 18:27:29.344 server[74756:2203] write Test::A +2008-09-05 18:27:29.344 server[74756:2203] write Test::B +2008-09-05 18:27:29.344 server[74756:2203] write Test::A +2008-09-05 18:27:29.345 server[74756:2203] write Test::B +2008-09-05 18:27:29.345 server[74756:2203] write Test::A +2008-09-05 18:27:29.346 server[74756:2203] write Test::B +2008-09-05 18:27:29.346 server[74756:2203] write Test::A +2008-09-05 18:27:29.346 server[74756:2203] write Test::B +2008-09-05 18:27:29.347 server[74756:2203] write Test::A +2008-09-05 18:27:29.347 server[74756:2203] write Test::B +2008-09-05 18:27:29.348 server[74756:2203] write Test::A +2008-09-05 18:27:29.348 server[74756:2203] write Test::B +2008-09-05 18:27:29.348 server[74756:2203] write Test::A +2008-09-05 18:27:29.349 server[74756:2203] write Test::B +2008-09-05 18:27:29.349 server[74756:2203] write Test::A +2008-09-05 18:27:29.350 server[74756:2203] write Test::B +2008-09-05 18:27:29.350 server[74756:2203] write Test::A +2008-09-05 18:27:29.350 server[74756:2203] write Test::B +2008-09-05 18:27:29.351 server[74756:2203] write Test::A +2008-09-05 18:27:29.351 server[74756:2203] write Test::B +2008-09-05 18:27:29.352 server[74756:2203] write Test::A +2008-09-05 18:27:29.352 server[74756:2203] write Test::B +2008-09-05 18:27:29.352 server[74756:2203] write Test::A +2008-09-05 18:27:29.353 server[74756:2203] write Test::B +2008-09-05 18:27:29.353 server[74756:2203] write Test::A +2008-09-05 18:27:29.354 server[74756:2203] write Test::B +2008-09-05 18:27:29.354 server[74756:2203] write Test::A +2008-09-05 18:27:29.354 server[74756:2203] write Test::B +2008-09-05 18:27:29.355 server[74756:2203] write Test::A +2008-09-05 18:27:29.355 server[74756:2203] write Test::B +2008-09-05 18:27:29.355 server[74756:2203] write Test::A +2008-09-05 18:27:29.356 server[74756:2203] write Test::B +2008-09-05 18:27:29.356 server[74756:2203] write Test::A +2008-09-05 18:27:29.357 server[74756:2203] write Test::B +2008-09-05 18:27:29.357 server[74756:2203] write Test::A +2008-09-05 18:27:29.357 server[74756:2203] write Test::B +2008-09-05 18:27:29.358 server[74756:2203] write Test::A +2008-09-05 18:27:29.359 server[74756:2203] write Test::B +2008-09-05 18:27:29.359 server[74756:2203] write Test::A +2008-09-05 18:27:29.359 server[74756:2203] write Test::B +2008-09-05 18:27:29.360 server[74756:2203] write Test::A +2008-09-05 18:27:29.360 server[74756:2203] write Test::B +2008-09-05 18:27:29.361 server[74756:2203] write Test::A +2008-09-05 18:27:29.362 server[74756:2203] write Test::B +2008-09-05 18:27:29.362 server[74756:2203] write Test::A +2008-09-05 18:27:29.362 server[74756:2203] write Test::B +2008-09-05 18:27:29.363 server[74756:2203] write Test::A +2008-09-05 18:27:29.363 server[74756:2203] write Test::B +2008-09-05 18:27:29.364 server[74756:2203] write Test::A +2008-09-05 18:27:29.364 server[74756:2203] write Test::B +2008-09-05 18:27:29.364 server[74756:2203] write Test::A +2008-09-05 18:27:29.366 server[74756:2203] write Test::B +2008-09-05 18:27:29.366 server[74756:2203] write Test::A +2008-09-05 18:27:29.367 server[74756:2203] write Test::B +2008-09-05 18:27:29.367 server[74756:2203] write Test::A +2008-09-05 18:27:29.368 server[74756:2203] write Test::B +2008-09-05 18:27:29.368 server[74756:2203] write Test::A +2008-09-05 18:27:29.368 server[74756:2203] write Test::B +2008-09-05 18:27:29.369 server[74756:2203] write Test::A +2008-09-05 18:27:29.369 server[74756:2203] write Test::B +2008-09-05 18:27:29.370 server[74756:2203] write Test::A +2008-09-05 18:27:29.370 server[74756:2203] write Test::B +2008-09-05 18:27:29.370 server[74756:2203] write Test::A +2008-09-05 18:27:29.371 server[74756:2203] write Test::B +2008-09-05 18:27:29.371 server[74756:2203] write Test::A +2008-09-05 18:27:29.371 server[74756:2203] write Test::B +2008-09-05 18:27:29.372 server[74756:2203] write Test::A +2008-09-05 18:27:29.372 server[74756:2203] write Test::B +2008-09-05 18:27:29.373 server[74756:2203] write Test::A +2008-09-05 18:27:29.373 server[74756:2203] write Test::B +2008-09-05 18:27:29.373 server[74756:2203] write Test::A +2008-09-05 18:27:29.374 server[74756:2203] write Test::B +2008-09-05 18:27:29.374 server[74756:2203] write Test::A +2008-09-05 18:27:29.375 server[74756:2203] write Test::B +2008-09-05 18:27:29.375 server[74756:2203] write Test::A +2008-09-05 18:27:29.375 server[74756:2203] write Test::B +2008-09-05 18:27:29.376 server[74756:2203] write Test::A +2008-09-05 18:27:29.376 server[74756:2203] write Test::B +2008-09-05 18:27:29.377 server[74756:2203] write Test::A +2008-09-05 18:27:29.377 server[74756:2203] write Test::B +2008-09-05 18:27:29.377 server[74756:2203] write Test::A +2008-09-05 18:27:29.378 server[74756:2203] write Test::B +2008-09-05 18:27:29.378 server[74756:2203] write Test::A +2008-09-05 18:27:29.379 server[74756:2203] write Test::B +2008-09-05 18:27:29.379 server[74756:2203] write Test::A +2008-09-05 18:27:29.379 server[74756:2203] write Test::B +2008-09-05 18:27:29.380 server[74756:2203] write Test::A +2008-09-05 18:27:29.380 server[74756:2203] write Test::B +2008-09-05 18:27:29.381 server[74756:2203] write Test::A +2008-09-05 18:27:29.381 server[74756:2203] write Test::B +2008-09-05 18:27:29.381 server[74756:2203] write Test::A +2008-09-05 18:27:29.382 server[74756:2203] write Test::B +2008-09-05 18:27:29.382 server[74756:2203] write Test::A +2008-09-05 18:27:29.382 server[74756:2203] write Test::B +2008-09-05 18:27:29.383 server[74756:2203] write Test::A +2008-09-05 18:27:29.383 server[74756:2203] write Test::B +2008-09-05 18:27:29.384 server[74756:2203] write Test::A +2008-09-05 18:27:29.384 server[74756:2203] write Test::B +2008-09-05 18:27:29.384 server[74756:2203] write Test::A +2008-09-05 18:27:29.385 server[74756:2203] write Test::B +2008-09-05 18:27:29.385 server[74756:2203] write Test::A +2008-09-05 18:27:29.386 server[74756:2203] write Test::B +2008-09-05 18:27:29.386 server[74756:2203] write Test::A +2008-09-05 18:27:29.386 server[74756:2203] write Test::B +2008-09-05 18:27:29.387 server[74756:2203] write Test::A +2008-09-05 18:27:29.388 server[74756:2203] write Test::B +2008-09-05 18:27:29.388 server[74756:2203] write Test::A +2008-09-05 18:27:29.388 server[74756:2203] write Test::B +2008-09-05 18:27:29.389 server[74756:2203] write Test::A +2008-09-05 18:27:29.389 server[74756:2203] write Test::B +2008-09-05 18:27:29.389 server[74756:2203] write Test::A +2008-09-05 18:27:29.390 server[74756:2203] write Test::B +2008-09-05 18:27:29.390 server[74756:2203] write Test::A +2008-09-05 18:27:29.391 server[74756:2203] write Test::B +2008-09-05 18:27:29.391 server[74756:2203] write Test::A +2008-09-05 18:27:29.391 server[74756:2203] write Test::B +2008-09-05 18:27:29.392 server[74756:2203] write Test::A +2008-09-05 18:27:29.392 server[74756:2203] write Test::B +2008-09-05 18:27:29.393 server[74756:2203] write Test::A +2008-09-05 18:27:29.393 server[74756:2203] write Test::B +2008-09-05 18:27:29.393 server[74756:2203] write Test::A +2008-09-05 18:27:29.394 server[74756:2203] write Test::B +2008-09-05 18:27:29.394 server[74756:2203] write Test::A +2008-09-05 18:27:29.395 server[74756:2203] write Test::B +2008-09-05 18:27:29.395 server[74756:2203] write Test::A +2008-09-05 18:27:29.395 server[74756:2203] write Test::B +2008-09-05 18:27:29.396 server[74756:2203] write Test::A +2008-09-05 18:27:29.396 server[74756:2203] write Test::B +2008-09-05 18:27:29.396 server[74756:2203] write Test::A +2008-09-05 18:27:29.397 server[74756:2203] write Test::B +2008-09-05 18:27:29.397 server[74756:2203] write Test::A +2008-09-05 18:27:29.398 server[74756:2203] write Test::B +2008-09-05 18:27:29.398 server[74756:2203] write Test::A +2008-09-05 18:27:29.398 server[74756:2203] write Test::B +2008-09-05 18:27:29.399 server[74756:2203] write Test::A +2008-09-05 18:27:29.399 server[74756:2203] write Test::B +2008-09-05 18:27:29.399 server[74756:2203] write Test::A +2008-09-05 18:27:29.400 server[74756:2203] write Test::B +2008-09-05 18:27:29.400 server[74756:2203] write Test::A +2008-09-05 18:27:29.401 server[74756:2203] write Test::B +2008-09-05 18:27:29.401 server[74756:2203] write Test::A +2008-09-05 18:27:29.401 server[74756:2203] write Test::B +2008-09-05 18:27:29.402 server[74756:2203] write Test::A +2008-09-05 18:27:29.402 server[74756:2203] write Test::B +2008-09-05 18:27:29.402 server[74756:2203] write Test::A +2008-09-05 18:27:29.403 server[74756:2203] write Test::B +2008-09-05 18:27:29.403 server[74756:2203] write Test::A +2008-09-05 18:27:29.403 server[74756:2203] write Test::B +2008-09-05 18:27:29.404 server[74756:2203] write Test::A +2008-09-05 18:27:29.404 server[74756:2203] write Test::B +2008-09-05 18:27:29.405 server[74756:2203] write Test::A +2008-09-05 18:27:29.405 server[74756:2203] write Test::B +2008-09-05 18:27:29.405 server[74756:2203] write Test::A +2008-09-05 18:27:29.406 server[74756:2203] write Test::B +2008-09-05 18:27:29.406 server[74756:2203] write Test::A +2008-09-05 18:27:29.406 server[74756:2203] write Test::B +2008-09-05 18:27:29.407 server[74756:2203] write Test::A +2008-09-05 18:27:29.408 server[74756:2203] write Test::B +2008-09-05 18:27:29.408 server[74756:2203] write Test::A +2008-09-05 18:27:29.409 server[74756:2203] write Test::B +2008-09-05 18:27:29.409 server[74756:2203] write Test::A +2008-09-05 18:27:29.409 server[74756:2203] write Test::B +2008-09-05 18:27:29.410 server[74756:2203] write Test::A +2008-09-05 18:27:29.410 server[74756:2203] write Test::B +2008-09-05 18:27:29.411 server[74756:2203] write Test::A +2008-09-05 18:27:29.411 server[74756:2203] write Test::B +2008-09-05 18:27:29.411 server[74756:2203] write Test::A +2008-09-05 18:27:29.412 server[74756:2203] write Test::B +2008-09-05 18:27:29.412 server[74756:2203] write Test::A +2008-09-05 18:27:29.413 server[74756:2203] write Test::B +2008-09-05 18:27:29.413 server[74756:2203] write Test::A +2008-09-05 18:27:29.413 server[74756:2203] write Test::B +2008-09-05 18:27:29.414 server[74756:2203] write Test::A +2008-09-05 18:27:29.414 server[74756:2203] write Test::B +2008-09-05 18:27:29.415 server[74756:2203] write Test::A +2008-09-05 18:27:29.415 server[74756:2203] write Test::B +2008-09-05 18:27:29.415 server[74756:2203] write Test::A +2008-09-05 18:27:29.416 server[74756:2203] write Test::B +2008-09-05 18:27:29.416 server[74756:2203] write Test::A +2008-09-05 18:27:29.416 server[74756:2203] write Test::B +2008-09-05 18:27:29.417 server[74756:2203] write Test::A +2008-09-05 18:27:29.417 server[74756:2203] write Test::B +2008-09-05 18:27:29.418 server[74756:2203] write Test::A +2008-09-05 18:27:29.418 server[74756:2203] write Test::B +2008-09-05 18:27:29.418 server[74756:2203] write Test::A +2008-09-05 18:27:29.419 server[74756:2203] write Test::B +2008-09-05 18:27:29.419 server[74756:2203] write Test::A +2008-09-05 18:27:29.419 server[74756:2203] write Test::B +2008-09-05 18:27:29.420 server[74756:2203] write Test::A +2008-09-05 18:27:29.420 server[74756:2203] write Test::B +2008-09-05 18:27:29.420 server[74756:2203] write Test::A +2008-09-05 18:27:29.421 server[74756:2203] write Test::B +2008-09-05 18:27:29.421 server[74756:2203] write Test::A +2008-09-05 18:27:29.421 server[74756:2203] write Test::B +2008-09-05 18:27:29.422 server[74756:2203] write Test::A +2008-09-05 18:27:29.422 server[74756:2203] write Test::B +2008-09-05 18:27:29.423 server[74756:2203] write Test::A +2008-09-05 18:27:29.423 server[74756:2203] write Test::B +2008-09-05 18:27:29.423 server[74756:2203] write Test::A +2008-09-05 18:27:29.424 server[74756:2203] write Test::B +2008-09-05 18:27:29.424 server[74756:2203] write Test::A +2008-09-05 18:27:29.424 server[74756:2203] write Test::B +2008-09-05 18:27:29.425 server[74756:2203] write Test::A +2008-09-05 18:27:29.425 server[74756:2203] write Test::B +2008-09-05 18:27:29.425 server[74756:2203] write Test::A +2008-09-05 18:27:29.426 server[74756:2203] write Test::B +2008-09-05 18:27:29.426 server[74756:2203] write Test::A +2008-09-05 18:27:29.427 server[74756:2203] write Test::B +2008-09-05 18:27:29.427 server[74756:2203] write Test::A +2008-09-05 18:27:29.427 server[74756:2203] write Test::B +2008-09-05 18:27:29.428 server[74756:2203] write Test::A +2008-09-05 18:27:29.428 server[74756:2203] write Test::B +2008-09-05 18:27:29.428 server[74756:2203] write Test::A +2008-09-05 18:27:29.429 server[74756:2203] write Test::B +2008-09-05 18:27:29.429 server[74756:2203] write Test::A +2008-09-05 18:27:29.430 server[74756:2203] write Test::B +2008-09-05 18:27:29.430 server[74756:2203] write Test::A +2008-09-05 18:27:29.431 server[74756:2203] write Test::B +2008-09-05 18:27:29.431 server[74756:2203] write Test::A +2008-09-05 18:27:29.431 server[74756:2203] write Test::B +2008-09-05 18:27:29.432 server[74756:2203] write Test::A +2008-09-05 18:27:29.432 server[74756:2203] write Test::B +2008-09-05 18:27:29.432 server[74756:2203] write Test::A +2008-09-05 18:27:29.433 server[74756:2203] write Test::B +2008-09-05 18:27:29.433 server[74756:2203] write Test::A +2008-09-05 18:27:29.433 server[74756:2203] write Test::B +2008-09-05 18:27:29.434 server[74756:2203] write Test::A +2008-09-05 18:27:29.434 server[74756:2203] write Test::B +2008-09-05 18:27:29.434 server[74756:2203] write Test::A +2008-09-05 18:27:29.435 server[74756:2203] write Test::B +2008-09-05 18:27:29.435 server[74756:2203] write Test::A +2008-09-05 18:27:29.436 server[74756:2203] write Test::B +2008-09-05 18:27:29.436 server[74756:2203] write Test::A +2008-09-05 18:27:29.436 server[74756:2203] write Test::B +2008-09-05 18:27:29.437 server[74756:2203] write Test::A +2008-09-05 18:27:29.437 server[74756:2203] write Test::B +2008-09-05 18:27:29.438 server[74756:2203] write Test::A +2008-09-05 18:27:29.438 server[74756:2203] write Test::B +2008-09-05 18:27:29.438 server[74756:2203] write Test::A +2008-09-05 18:27:29.439 server[74756:2203] write Test::B +2008-09-05 18:27:29.439 server[74756:2203] write Test::A +2008-09-05 18:27:29.439 server[74756:2203] write Test::B +2008-09-05 18:27:29.440 server[74756:2203] write Test::A +2008-09-05 18:27:29.440 server[74756:2203] write Test::B +2008-09-05 18:27:29.441 server[74756:2203] write Test::A +2008-09-05 18:27:29.441 server[74756:2203] write Test::B +2008-09-05 18:27:29.441 server[74756:2203] write Test::A +2008-09-05 18:27:29.442 server[74756:2203] write Test::B +2008-09-05 18:27:29.442 server[74756:2203] write Test::A +2008-09-05 18:27:29.442 server[74756:2203] write Test::B +2008-09-05 18:27:29.443 server[74756:2203] write Test::A +2008-09-05 18:27:29.443 server[74756:2203] write Test::B +2008-09-05 18:27:29.443 server[74756:2203] write Test::A +2008-09-05 18:27:29.444 server[74756:2203] write Test::B +2008-09-05 18:27:29.444 server[74756:2203] write Test::A +2008-09-05 18:27:29.445 server[74756:2203] write Test::B +2008-09-05 18:27:29.445 server[74756:2203] write Test::A +2008-09-05 18:27:29.445 server[74756:2203] write Test::B +2008-09-05 18:27:29.446 server[74756:2203] write Test::A +2008-09-05 18:27:29.446 server[74756:2203] write Test::B +2008-09-05 18:27:29.446 server[74756:2203] write Test::A +2008-09-05 18:27:29.447 server[74756:2203] write Test::B +2008-09-05 18:27:29.447 server[74756:2203] write Test::A +2008-09-05 18:27:29.448 server[74756:2203] write Test::B +2008-09-05 18:27:29.448 server[74756:2203] write Test::A +2008-09-05 18:27:29.448 server[74756:2203] write Test::B +2008-09-05 18:27:29.449 server[74756:2203] write Test::A +2008-09-05 18:27:29.449 server[74756:2203] write Test::B +2008-09-05 18:27:29.449 server[74756:2203] write Test::A +2008-09-05 18:27:29.450 server[74756:2203] write Test::B +2008-09-05 18:27:29.450 server[74756:2203] write Test::A +2008-09-05 18:27:29.450 server[74756:2203] write Test::B +2008-09-05 18:27:29.451 server[74756:2203] write Test::A +2008-09-05 18:27:29.451 server[74756:2203] write Test::B +2008-09-05 18:27:29.452 server[74756:2203] write Test::A +2008-09-05 18:27:29.452 server[74756:2203] write Test::B +2008-09-05 18:27:29.452 server[74756:2203] write Test::A +2008-09-05 18:27:29.453 server[74756:2203] write Test::B +2008-09-05 18:27:29.453 server[74756:2203] write Test::A +2008-09-05 18:27:29.453 server[74756:2203] write Test::B +2008-09-05 18:27:29.454 server[74756:2203] write Test::A +2008-09-05 18:27:29.454 server[74756:2203] write Test::B +2008-09-05 18:27:29.454 server[74756:2203] write Test::A +2008-09-05 18:27:29.455 server[74756:2203] write Test::B +2008-09-05 18:27:29.455 server[74756:2203] write Test::A +2008-09-05 18:27:29.456 server[74756:2203] write Test::B +2008-09-05 18:27:29.456 server[74756:2203] write Test::A +2008-09-05 18:27:29.457 server[74756:2203] write Test::B +2008-09-05 18:27:29.457 server[74756:2203] write Test::A +2008-09-05 18:27:29.457 server[74756:2203] write Test::B +2008-09-05 18:27:29.458 server[74756:2203] write Test::A +2008-09-05 18:27:29.458 server[74756:2203] write Test::B +2008-09-05 18:27:29.460 server[74756:2203] write Test::A +2008-09-05 18:27:29.460 server[74756:2203] write Test::B +2008-09-05 18:27:29.461 server[74756:2203] write Test::A +2008-09-05 18:27:29.461 server[74756:2203] write Test::B +2008-09-05 18:27:29.462 server[74756:2203] write Test::A +2008-09-05 18:27:29.462 server[74756:2203] write Test::B +2008-09-05 18:27:29.462 server[74756:2203] write Test::A +2008-09-05 18:27:29.463 server[74756:2203] write Test::B +2008-09-05 18:27:29.463 server[74756:2203] write Test::A +2008-09-05 18:27:29.463 server[74756:2203] write Test::B +2008-09-05 18:27:29.464 server[74756:2203] write Test::A +2008-09-05 18:27:29.464 server[74756:2203] write Test::B +2008-09-05 18:27:29.465 server[74756:2203] write Test::A +2008-09-05 18:27:29.465 server[74756:2203] write Test::B +2008-09-05 18:27:29.465 server[74756:2203] write Test::A +2008-09-05 18:27:29.466 server[74756:2203] write Test::B +2008-09-05 18:27:29.466 server[74756:2203] write Test::A +2008-09-05 18:27:29.467 server[74756:2203] write Test::B +2008-09-05 18:27:29.467 server[74756:2203] write Test::A +2008-09-05 18:27:29.467 server[74756:2203] write Test::B +2008-09-05 18:27:29.468 server[74756:2203] write Test::A +2008-09-05 18:27:29.468 server[74756:2203] write Test::B +2008-09-05 18:27:29.468 server[74756:2203] write Test::A +2008-09-05 18:27:29.469 server[74756:2203] write Test::B +2008-09-05 18:27:29.469 server[74756:2203] write Test::A +2008-09-05 18:27:29.470 server[74756:2203] write Test::B +2008-09-05 18:27:29.470 server[74756:2203] write Test::A +2008-09-05 18:27:29.470 server[74756:2203] write Test::B +2008-09-05 18:27:29.471 server[74756:2203] write Test::A +2008-09-05 18:27:29.471 server[74756:2203] write Test::B +2008-09-05 18:27:29.472 server[74756:2203] write Test::A +2008-09-05 18:27:29.472 server[74756:2203] write Test::B +2008-09-05 18:27:29.472 server[74756:2203] write Test::A +2008-09-05 18:27:29.473 server[74756:2203] write Test::B +2008-09-05 18:27:29.473 server[74756:2203] write Test::A +2008-09-05 18:27:29.473 server[74756:2203] write Test::B +2008-09-05 18:27:29.474 server[74756:2203] write Test::A +2008-09-05 18:27:29.474 server[74756:2203] write Test::B +2008-09-05 18:27:29.475 server[74756:2203] write Test::A +2008-09-05 18:27:29.475 server[74756:2203] write Test::B +2008-09-05 18:27:29.475 server[74756:2203] write Test::A +2008-09-05 18:27:29.476 server[74756:2203] write Test::B +2008-09-05 18:27:29.476 server[74756:2203] write Test::A +2008-09-05 18:27:29.476 server[74756:2203] write Test::B +2008-09-05 18:27:29.477 server[74756:2203] write Test::A +2008-09-05 18:27:29.477 server[74756:2203] write Test::B +2008-09-05 18:27:29.478 server[74756:2203] write Test::A +2008-09-05 18:27:29.478 server[74756:2203] write Test::B +2008-09-05 18:27:29.479 server[74756:2203] write Test::A +2008-09-05 18:27:29.479 server[74756:2203] write Test::B +2008-09-05 18:27:29.479 server[74756:2203] write Test::A +2008-09-05 18:27:29.480 server[74756:2203] write Test::B +2008-09-05 18:27:29.480 server[74756:2203] write Test::A +2008-09-05 18:27:29.480 server[74756:2203] write Test::B +2008-09-05 18:27:29.481 server[74756:2203] write Test::A +2008-09-05 18:27:29.481 server[74756:2203] write Test::B +2008-09-05 18:27:29.482 server[74756:2203] write Test::A +2008-09-05 18:27:29.482 server[74756:2203] write Test::B +2008-09-05 18:27:29.482 server[74756:2203] write Test::A +2008-09-05 18:27:29.483 server[74756:2203] write Test::B +2008-09-05 18:27:29.483 server[74756:2203] write Test::A +2008-09-05 18:27:29.483 server[74756:2203] write Test::B +2008-09-05 18:27:29.484 server[74756:2203] write Test::A +2008-09-05 18:27:29.484 server[74756:2203] write Test::B +2008-09-05 18:27:29.485 server[74756:2203] write Test::A +2008-09-05 18:27:29.485 server[74756:2203] write Test::B +2008-09-05 18:27:29.485 server[74756:2203] write Test::A +2008-09-05 18:27:29.486 server[74756:2203] write Test::B +2008-09-05 18:27:29.486 server[74756:2203] write Test::A +2008-09-05 18:27:29.486 server[74756:2203] write Test::B +2008-09-05 18:27:29.487 server[74756:2203] write Test::A +2008-09-05 18:27:29.487 server[74756:2203] write Test::B +2008-09-05 18:27:29.488 server[74756:2203] write Test::A +2008-09-05 18:27:29.488 server[74756:2203] write Test::B +2008-09-05 18:27:29.488 server[74756:2203] write Test::A +2008-09-05 18:27:29.489 server[74756:2203] write Test::B +2008-09-05 18:27:29.489 server[74756:2203] write Test::A +2008-09-05 18:27:29.490 server[74756:2203] write Test::B +2008-09-05 18:27:29.491 server[74756:2203] write Test::A +2008-09-05 18:27:29.491 server[74756:2203] write Test::B +2008-09-05 18:27:29.491 server[74756:2203] write Test::A +2008-09-05 18:27:29.492 server[74756:2203] write Test::B +2008-09-05 18:27:29.492 server[74756:2203] write Test::A +2008-09-05 18:27:29.492 server[74756:2203] write Test::B +2008-09-05 18:27:29.493 server[74756:2203] write Test::A +2008-09-05 18:27:29.493 server[74756:2203] write Test::B +2008-09-05 18:27:29.494 server[74756:2203] write Test::A +2008-09-05 18:27:29.494 server[74756:2203] write Test::B +2008-09-05 18:27:29.494 server[74756:2203] write Test::A +2008-09-05 18:27:29.495 server[74756:2203] write Test::B +2008-09-05 18:27:29.495 server[74756:2203] write Test::A +2008-09-05 18:27:29.496 server[74756:2203] write Test::B +2008-09-05 18:27:29.496 server[74756:2203] write Test::A +2008-09-05 18:27:29.496 server[74756:2203] write Test::B +2008-09-05 18:27:29.497 server[74756:2203] write Test::A +2008-09-05 18:27:29.497 server[74756:2203] write Test::B +2008-09-05 18:27:29.497 server[74756:2203] write Test::A +2008-09-05 18:27:29.498 server[74756:2203] write Test::B +2008-09-05 18:27:29.498 server[74756:2203] write Test::A +2008-09-05 18:27:29.499 server[74756:2203] write Test::B +2008-09-05 18:27:29.499 server[74756:2203] write Test::A +2008-09-05 18:27:29.499 server[74756:2203] write Test::B +2008-09-05 18:27:29.500 server[74756:2203] write Test::A +2008-09-05 18:27:29.500 server[74756:2203] write Test::B +2008-09-05 18:27:29.501 server[74756:2203] write Test::A +2008-09-05 18:27:29.501 server[74756:2203] write Test::B +2008-09-05 18:27:29.501 server[74756:2203] write Test::A +2008-09-05 18:27:29.502 server[74756:2203] write Test::B +2008-09-05 18:27:29.502 server[74756:2203] write Test::A +2008-09-05 18:27:29.502 server[74756:2203] write Test::B +2008-09-05 18:27:29.503 server[74756:2203] write Test::A +2008-09-05 18:27:29.503 server[74756:2203] write Test::B +2008-09-05 18:27:29.504 server[74756:2203] write Test::A +2008-09-05 18:27:29.504 server[74756:2203] write Test::B +2008-09-05 18:27:29.504 server[74756:2203] write Test::A +2008-09-05 18:27:29.505 server[74756:2203] write Test::B +2008-09-05 18:27:29.505 server[74756:2203] write Test::A +2008-09-05 18:27:29.505 server[74756:2203] write Test::B +2008-09-05 18:27:29.506 server[74756:2203] write Test::A +2008-09-05 18:27:29.506 server[74756:2203] write Test::B +2008-09-05 18:27:29.507 server[74756:2203] write Test::A +2008-09-05 18:27:29.507 server[74756:2203] write Test::B +2008-09-05 18:27:29.507 server[74756:2203] write Test::A +2008-09-05 18:27:29.509 server[74756:2203] write Test::B +2008-09-05 18:27:29.511 server[74756:2203] write Test::A +2008-09-05 18:27:29.512 server[74756:2203] write Test::B +2008-09-05 18:27:29.512 server[74756:2203] write Test::A +2008-09-05 18:27:29.513 server[74756:2203] write Test::B +2008-09-05 18:27:29.513 server[74756:2203] write Test::A +2008-09-05 18:27:29.516 server[74756:2203] write Test::B +2008-09-05 18:27:29.518 server[74756:2203] write Test::A +2008-09-05 18:27:29.520 server[74756:2203] write Test::B +2008-09-05 18:27:29.523 server[74756:2203] write Test::A +2008-09-05 18:27:29.524 server[74756:2203] write Test::B +2008-09-05 18:27:29.526 server[74756:2203] write Test::A +2008-09-05 18:27:29.528 server[74756:2203] write Test::B +2008-09-05 18:27:29.528 server[74756:2203] write Test::A +2008-09-05 18:27:29.530 server[74756:2203] write Test::B +2008-09-05 18:27:29.530 server[74756:2203] write Test::A +2008-09-05 18:27:29.531 server[74756:2203] write Test::B +2008-09-05 18:27:29.531 server[74756:2203] write Test::A +2008-09-05 18:27:29.532 server[74756:2203] write Test::B +2008-09-05 18:27:29.532 server[74756:2203] write Test::A +2008-09-05 18:27:29.533 server[74756:2203] write Test::B +2008-09-05 18:27:29.534 server[74756:2203] write Test::A +2008-09-05 18:27:29.535 server[74756:2203] write Test::B +2008-09-05 18:27:29.538 server[74756:2203] write Test::A +2008-09-05 18:27:29.540 server[74756:2203] write Test::B +2008-09-05 18:27:29.540 server[74756:2203] write Test::A +2008-09-05 18:27:29.540 server[74756:2203] write Test::B +2008-09-05 18:27:29.541 server[74756:2203] write Test::A +2008-09-05 18:27:29.541 server[74756:2203] write Test::B +2008-09-05 18:27:29.541 server[74756:2203] write Test::A +2008-09-05 18:27:29.542 server[74756:2203] write Test::B +2008-09-05 18:27:29.543 server[74756:2203] write Test::A +2008-09-05 18:27:29.544 server[74756:2203] write Test::B +2008-09-05 18:27:29.544 server[74756:2203] write Test::A +2008-09-05 18:27:29.546 server[74756:2203] write Test::B +2008-09-05 18:27:29.546 server[74756:2203] write Test::A +2008-09-05 18:27:29.548 server[74756:2203] write Test::B +2008-09-05 18:27:29.549 server[74756:2203] write Test::A +2008-09-05 18:27:29.549 server[74756:2203] write Test::B +2008-09-05 18:27:29.549 server[74756:2203] write Test::A +2008-09-05 18:27:29.550 server[74756:2203] write Test::B +2008-09-05 18:27:29.550 server[74756:2203] write Test::A +2008-09-05 18:27:29.551 server[74756:2203] write Test::B +2008-09-05 18:27:29.551 server[74756:2203] write Test::A +2008-09-05 18:27:29.552 server[74756:2203] write Test::B +2008-09-05 18:27:29.553 server[74756:2203] write Test::A +2008-09-05 18:27:29.553 server[74756:2203] write Test::B +2008-09-05 18:27:29.554 server[74756:2203] write Test::A +2008-09-05 18:27:29.555 server[74756:2203] write Test::B +2008-09-05 18:27:29.556 server[74756:2203] write Test::A +2008-09-05 18:27:29.558 server[74756:2203] write Test::B +2008-09-05 18:27:29.558 server[74756:2203] write Test::A +2008-09-05 18:27:29.558 server[74756:2203] write Test::B +2008-09-05 18:27:29.559 server[74756:2203] write Test::A +2008-09-05 18:27:29.559 server[74756:2203] write Test::B +2008-09-05 18:27:29.560 server[74756:2203] write Test::A +2008-09-05 18:27:29.562 server[74756:2203] write Test::B +2008-09-05 18:27:29.562 server[74756:2203] write Test::A +2008-09-05 18:27:29.563 server[74756:2203] write Test::B +2008-09-05 18:27:29.563 server[74756:2203] write Test::A +2008-09-05 18:27:29.564 server[74756:2203] write Test::B +2008-09-05 18:27:29.564 server[74756:2203] write Test::A +2008-09-05 18:27:29.565 server[74756:2203] write Test::B +2008-09-05 18:27:29.566 server[74756:2203] write Test::A +2008-09-05 18:27:29.567 server[74756:2203] write Test::B +2008-09-05 18:27:29.567 server[74756:2203] write Test::A +2008-09-05 18:27:29.568 server[74756:2203] write Test::B +2008-09-05 18:27:29.570 server[74756:2203] write Test::A +2008-09-05 18:27:29.570 server[74756:2203] write Test::B +2008-09-05 18:27:29.571 server[74756:2203] write Test::A +2008-09-05 18:27:29.571 server[74756:2203] write Test::B +2008-09-05 18:27:29.571 server[74756:2203] write Test::A +2008-09-05 18:27:29.572 server[74756:2203] write Test::B +2008-09-05 18:27:29.573 server[74756:2203] write Test::A +2008-09-05 18:27:29.573 server[74756:2203] write Test::B +2008-09-05 18:27:29.573 server[74756:2203] write Test::A +2008-09-05 18:27:29.574 server[74756:2203] write Test::B +2008-09-05 18:27:29.574 server[74756:2203] write Test::A +2008-09-05 18:27:29.575 server[74756:2203] write Test::B +2008-09-05 18:27:29.576 server[74756:2203] write Test::A +2008-09-05 18:27:29.576 server[74756:2203] write Test::B +2008-09-05 18:27:29.577 server[74756:2203] write Test::A +2008-09-05 18:27:29.578 server[74756:2203] write Test::B +2008-09-05 18:27:29.578 server[74756:2203] write Test::A +2008-09-05 18:27:29.579 server[74756:2203] write Test::B +2008-09-05 18:27:29.580 server[74756:2203] write Test::A +2008-09-05 18:27:29.581 server[74756:2203] write Test::B +2008-09-05 18:27:29.581 server[74756:2203] write Test::A +2008-09-05 18:27:29.582 server[74756:2203] write Test::B +2008-09-05 18:27:29.582 server[74756:2203] write Test::A +2008-09-05 18:27:29.583 server[74756:2203] write Test::B +2008-09-05 18:27:29.583 server[74756:2203] write Test::A +2008-09-05 18:27:29.584 server[74756:2203] write Test::B +2008-09-05 18:27:29.584 server[74756:2203] write Test::A +2008-09-05 18:27:29.585 server[74756:2203] write Test::B +2008-09-05 18:27:29.585 server[74756:2203] write Test::A +2008-09-05 18:27:29.586 server[74756:2203] write Test::B +2008-09-05 18:27:29.587 server[74756:2203] write Test::A +2008-09-05 18:27:29.587 server[74756:2203] write Test::B +2008-09-05 18:27:29.588 server[74756:2203] write Test::A +2008-09-05 18:27:29.588 server[74756:2203] write Test::B +2008-09-05 18:27:29.589 server[74756:2203] write Test::A +2008-09-05 18:27:29.589 server[74756:2203] write Test::B +2008-09-05 18:27:29.590 server[74756:2203] write Test::A +2008-09-05 18:27:29.590 server[74756:2203] write Test::B +2008-09-05 18:27:29.591 server[74756:2203] write Test::A +2008-09-05 18:27:29.591 server[74756:2203] write Test::B +2008-09-05 18:27:29.592 server[74756:2203] write Test::A +2008-09-05 18:27:29.592 server[74756:2203] write Test::B +2008-09-05 18:27:29.593 server[74756:2203] write Test::A +2008-09-05 18:27:29.593 server[74756:2203] write Test::B +2008-09-05 18:27:29.594 server[74756:2203] write Test::A +2008-09-05 18:27:29.594 server[74756:2203] write Test::B +2008-09-05 18:27:29.595 server[74756:2203] write Test::A +2008-09-05 18:27:29.595 server[74756:2203] write Test::B +2008-09-05 18:27:29.596 server[74756:2203] write Test::A +2008-09-05 18:27:29.596 server[74756:2203] write Test::B +2008-09-05 18:27:29.597 server[74756:2203] write Test::A +2008-09-05 18:27:29.597 server[74756:2203] write Test::B +2008-09-05 18:27:29.598 server[74756:2203] write Test::A +2008-09-05 18:27:29.598 server[74756:2203] write Test::B +2008-09-05 18:27:29.599 server[74756:2203] write Test::A +2008-09-05 18:27:29.599 server[74756:2203] write Test::B +2008-09-05 18:27:29.600 server[74756:2203] write Test::A +2008-09-05 18:27:29.600 server[74756:2203] write Test::B +2008-09-05 18:27:29.601 server[74756:2203] write Test::A +2008-09-05 18:27:29.601 server[74756:2203] write Test::B +2008-09-05 18:27:29.602 server[74756:2203] write Test::A +2008-09-05 18:27:29.602 server[74756:2203] write Test::B +2008-09-05 18:27:29.603 server[74756:2203] write Test::A +2008-09-05 18:27:29.603 server[74756:2203] write Test::B +2008-09-05 18:27:29.604 server[74756:2203] write Test::A +2008-09-05 18:27:29.604 server[74756:2203] write Test::B +2008-09-05 18:27:29.605 server[74756:2203] write Test::A +2008-09-05 18:27:29.605 server[74756:2203] write Test::B +2008-09-05 18:27:29.606 server[74756:2203] write Test::A +2008-09-05 18:27:29.607 server[74756:2203] write Test::B +2008-09-05 18:27:29.607 server[74756:2203] write Test::A +2008-09-05 18:27:29.608 server[74756:2203] write Test::B +2008-09-05 18:27:29.608 server[74756:2203] write Test::A +2008-09-05 18:27:29.609 server[74756:2203] write Test::B +2008-09-05 18:27:29.609 server[74756:2203] write Test::A +2008-09-05 18:27:29.610 server[74756:2203] write Test::B +2008-09-05 18:27:29.611 server[74756:2203] write Test::A +2008-09-05 18:27:29.611 server[74756:2203] write Test::B +2008-09-05 18:27:29.612 server[74756:2203] write Test::A +2008-09-05 18:27:29.612 server[74756:2203] write Test::B +2008-09-05 18:27:29.613 server[74756:2203] write Test::A +2008-09-05 18:27:29.613 server[74756:2203] write Test::B +2008-09-05 18:27:29.614 server[74756:2203] write Test::A +2008-09-05 18:27:29.614 server[74756:2203] write Test::B +2008-09-05 18:27:29.615 server[74756:2203] write Test::A +2008-09-05 18:27:29.615 server[74756:2203] write Test::B +2008-09-05 18:27:29.616 server[74756:2203] write Test::A +2008-09-05 18:27:29.616 server[74756:2203] write Test::B +2008-09-05 18:27:29.617 server[74756:2203] write Test::A +2008-09-05 18:27:29.617 server[74756:2203] write Test::B +2008-09-05 18:27:29.618 server[74756:2203] write Test::A +2008-09-05 18:27:29.618 server[74756:2203] write Test::B +2008-09-05 18:27:29.619 server[74756:2203] write Test::A +2008-09-05 18:27:29.619 server[74756:2203] write Test::B +2008-09-05 18:27:29.620 server[74756:2203] write Test::A +2008-09-05 18:27:29.620 server[74756:2203] write Test::B +2008-09-05 18:27:29.621 server[74756:2203] write Test::A +2008-09-05 18:27:29.621 server[74756:2203] write Test::B +2008-09-05 18:27:29.622 server[74756:2203] write Test::A +2008-09-05 18:27:29.622 server[74756:2203] write Test::B +2008-09-05 18:27:29.623 server[74756:2203] write Test::A +2008-09-05 18:27:29.623 server[74756:2203] write Test::B +2008-09-05 18:27:29.624 server[74756:2203] write Test::A +2008-09-05 18:27:29.624 server[74756:2203] write Test::B +2008-09-05 18:27:29.625 server[74756:2203] write Test::A +2008-09-05 18:27:29.625 server[74756:2203] write Test::B +2008-09-05 18:27:29.626 server[74756:2203] write Test::A +2008-09-05 18:27:29.626 server[74756:2203] write Test::B +2008-09-05 18:27:29.627 server[74756:2203] write Test::A +2008-09-05 18:27:29.627 server[74756:2203] write Test::B +2008-09-05 18:27:29.628 server[74756:2203] write Test::A +2008-09-05 18:27:29.628 server[74756:2203] write Test::B +2008-09-05 18:27:29.629 server[74756:2203] write Test::A +2008-09-05 18:27:29.629 server[74756:2203] write Test::B +2008-09-05 18:27:29.630 server[74756:2203] write Test::A +2008-09-05 18:27:29.630 server[74756:2203] write Test::B +2008-09-05 18:27:29.631 server[74756:2203] write Test::A +2008-09-05 18:27:29.631 server[74756:2203] write Test::B +2008-09-05 18:27:29.632 server[74756:2203] write Test::A +2008-09-05 18:27:29.632 server[74756:2203] write Test::B +2008-09-05 18:27:29.633 server[74756:2203] write Test::A +2008-09-05 18:27:29.633 server[74756:2203] write Test::B +2008-09-05 18:27:29.634 server[74756:2203] write Test::A +2008-09-05 18:27:29.635 server[74756:2203] write Test::B +2008-09-05 18:27:29.635 server[74756:2203] write Test::A +2008-09-05 18:27:29.636 server[74756:2203] write Test::B +2008-09-05 18:27:29.636 server[74756:2203] write Test::A +2008-09-05 18:27:29.637 server[74756:2203] write Test::B +2008-09-05 18:27:29.637 server[74756:2203] write Test::A +2008-09-05 18:27:29.638 server[74756:2203] write Test::B +2008-09-05 18:27:29.638 server[74756:2203] write Test::A +2008-09-05 18:27:29.639 server[74756:2203] write Test::B +2008-09-05 18:27:29.639 server[74756:2203] write Test::A +2008-09-05 18:27:29.640 server[74756:2203] write Test::B +2008-09-05 18:27:29.640 server[74756:2203] write Test::A +2008-09-05 18:27:29.641 server[74756:2203] write Test::B +2008-09-05 18:27:29.641 server[74756:2203] write Test::A +2008-09-05 18:27:29.642 server[74756:2203] write Test::B +2008-09-05 18:27:29.642 server[74756:2203] write Test::A +2008-09-05 18:27:29.642 server[74756:2203] write Test::B +2008-09-05 18:27:29.643 server[74756:2203] write Test::A +2008-09-05 18:27:29.645 server[74756:2203] write Test::B +2008-09-05 18:27:29.645 server[74756:2203] write Test::A +2008-09-05 18:27:29.646 server[74756:2203] write Test::B +2008-09-05 18:27:29.646 server[74756:2203] write Test::A +2008-09-05 18:27:29.647 server[74756:2203] write Test::B +2008-09-05 18:27:29.647 server[74756:2203] write Test::A +2008-09-05 18:27:29.648 server[74756:2203] write Test::B +2008-09-05 18:27:29.648 server[74756:2203] write Test::A +2008-09-05 18:27:29.649 server[74756:2203] write Test::B +2008-09-05 18:27:29.649 server[74756:2203] write Test::A +2008-09-05 18:27:29.650 server[74756:2203] write Test::B +2008-09-05 18:27:29.650 server[74756:2203] write Test::A +2008-09-05 18:27:29.651 server[74756:2203] write Test::B +2008-09-05 18:27:29.651 server[74756:2203] write Test::A +2008-09-05 18:27:29.651 server[74756:2203] write Test::B +2008-09-05 18:27:29.652 server[74756:2203] write Test::A +2008-09-05 18:27:29.652 server[74756:2203] write Test::B +2008-09-05 18:27:29.653 server[74756:2203] write Test::A +2008-09-05 18:27:29.653 server[74756:2203] write Test::B +2008-09-05 18:27:29.654 server[74756:2203] write Test::A +2008-09-05 18:27:29.654 server[74756:2203] write Test::B +2008-09-05 18:27:29.655 server[74756:2203] write Test::A +2008-09-05 18:27:29.655 server[74756:2203] write Test::B +2008-09-05 18:27:29.656 server[74756:2203] write Test::A +2008-09-05 18:27:29.656 server[74756:2203] write Test::B +2008-09-05 18:27:29.657 server[74756:2203] write Test::A +2008-09-05 18:27:29.657 server[74756:2203] write Test::B +2008-09-05 18:27:29.658 server[74756:2203] write Test::A +2008-09-05 18:27:29.658 server[74756:2203] write Test::B +2008-09-05 18:27:29.659 server[74756:2203] write Test::A +2008-09-05 18:27:29.659 server[74756:2203] write Test::B +2008-09-05 18:27:29.660 server[74756:2203] write Test::A +2008-09-05 18:27:29.660 server[74756:2203] write Test::B +2008-09-05 18:27:29.661 server[74756:2203] write Test::A +2008-09-05 18:27:29.661 server[74756:2203] write Test::B +2008-09-05 18:27:29.662 server[74756:2203] write Test::A +2008-09-05 18:27:29.662 server[74756:2203] write Test::B +2008-09-05 18:27:29.663 server[74756:2203] write Test::A +2008-09-05 18:27:29.663 server[74756:2203] write Test::B +2008-09-05 18:27:29.664 server[74756:2203] write Test::A +2008-09-05 18:27:29.664 server[74756:2203] write Test::B +2008-09-05 18:27:29.664 server[74756:2203] write Test::A +2008-09-05 18:27:29.665 server[74756:2203] write Test::B +2008-09-05 18:27:29.665 server[74756:2203] write Test::A +2008-09-05 18:27:29.666 server[74756:2203] write Test::B +2008-09-05 18:27:29.666 server[74756:2203] write Test::A +2008-09-05 18:27:29.667 server[74756:2203] write Test::B +2008-09-05 18:27:29.667 server[74756:2203] write Test::A +2008-09-05 18:27:29.668 server[74756:2203] write Test::B +2008-09-05 18:27:29.668 server[74756:2203] write Test::A +2008-09-05 18:27:29.669 server[74756:2203] write Test::B +2008-09-05 18:27:29.669 server[74756:2203] write Test::A +2008-09-05 18:27:29.670 server[74756:2203] write Test::B +2008-09-05 18:27:29.670 server[74756:2203] write Test::A +2008-09-05 18:27:29.671 server[74756:2203] write Test::B +2008-09-05 18:27:29.671 server[74756:2203] write Test::A +2008-09-05 18:27:29.672 server[74756:2203] write Test::B +2008-09-05 18:27:29.672 server[74756:2203] write Test::A +2008-09-05 18:27:29.673 server[74756:2203] write Test::B +2008-09-05 18:27:29.673 server[74756:2203] write Test::A +2008-09-05 18:27:29.674 server[74756:2203] write Test::B +2008-09-05 18:27:29.674 server[74756:2203] write Test::A +2008-09-05 18:27:29.675 server[74756:2203] write Test::B +2008-09-05 18:27:29.675 server[74756:2203] write Test::A +2008-09-05 18:27:29.675 server[74756:2203] write Test::B +2008-09-05 18:27:29.676 server[74756:2203] write Test::A +2008-09-05 18:27:29.676 server[74756:2203] write Test::B +2008-09-05 18:27:29.677 server[74756:2203] write Test::A +2008-09-05 18:27:29.677 server[74756:2203] write Test::B +2008-09-05 18:27:29.678 server[74756:2203] write Test::A +2008-09-05 18:27:29.678 server[74756:2203] write Test::B +2008-09-05 18:27:29.679 server[74756:2203] write Test::A +2008-09-05 18:27:29.680 server[74756:2203] write Test::B +2008-09-05 18:27:29.680 server[74756:2203] write Test::A +2008-09-05 18:27:29.681 server[74756:2203] write Test::B +2008-09-05 18:27:29.681 server[74756:2203] write Test::A +2008-09-05 18:27:29.682 server[74756:2203] write Test::B +2008-09-05 18:27:29.682 server[74756:2203] write Test::A +2008-09-05 18:27:29.683 server[74756:2203] write Test::B +2008-09-05 18:27:29.683 server[74756:2203] write Test::A +2008-09-05 18:27:29.684 server[74756:2203] write Test::B +2008-09-05 18:27:29.684 server[74756:2203] write Test::A +2008-09-05 18:27:29.685 server[74756:2203] write Test::B +2008-09-05 18:27:29.685 server[74756:2203] write Test::A +2008-09-05 18:27:29.686 server[74756:2203] write Test::B +2008-09-05 18:27:29.686 server[74756:2203] write Test::A +2008-09-05 18:27:29.687 server[74756:2203] write Test::B +2008-09-05 18:27:29.688 server[74756:2203] write Test::A +2008-09-05 18:27:29.688 server[74756:2203] write Test::B +2008-09-05 18:27:29.689 server[74756:2203] write Test::A +2008-09-05 18:27:29.689 server[74756:2203] write Test::B +2008-09-05 18:27:29.690 server[74756:2203] write Test::A +2008-09-05 18:27:29.690 server[74756:2203] write Test::B +2008-09-05 18:27:29.691 server[74756:2203] write Test::A +2008-09-05 18:27:29.691 server[74756:2203] write Test::B +2008-09-05 18:27:29.692 server[74756:2203] write Test::A +2008-09-05 18:27:29.693 server[74756:2203] write Test::B +2008-09-05 18:27:29.693 server[74756:2203] write Test::A +2008-09-05 18:27:29.694 server[74756:2203] write Test::B +2008-09-05 18:27:29.694 server[74756:2203] write Test::A +2008-09-05 18:27:29.695 server[74756:2203] write Test::B +2008-09-05 18:27:29.695 server[74756:2203] write Test::A +2008-09-05 18:27:29.696 server[74756:2203] write Test::B +2008-09-05 18:27:29.696 server[74756:2203] write Test::A +2008-09-05 18:27:29.697 server[74756:2203] write Test::B +2008-09-05 18:27:29.697 server[74756:2203] write Test::A +2008-09-05 18:27:29.698 server[74756:2203] write Test::B +2008-09-05 18:27:29.698 server[74756:2203] write Test::A +2008-09-05 18:27:29.699 server[74756:2203] write Test::B +2008-09-05 18:27:29.699 server[74756:2203] write Test::A +2008-09-05 18:27:29.700 server[74756:2203] write Test::B +2008-09-05 18:27:29.700 server[74756:2203] write Test::A +2008-09-05 18:27:29.701 server[74756:2203] write Test::B +2008-09-05 18:27:29.701 server[74756:2203] write Test::A +2008-09-05 18:27:29.702 server[74756:2203] write Test::B +2008-09-05 18:27:29.702 server[74756:2203] write Test::A +2008-09-05 18:27:29.702 server[74756:2203] write Test::B +2008-09-05 18:27:29.703 server[74756:2203] write Test::A +2008-09-05 18:27:29.703 server[74756:2203] write Test::B +2008-09-05 18:27:29.704 server[74756:2203] write Test::A +2008-09-05 18:27:29.704 server[74756:2203] write Test::B +2008-09-05 18:27:29.705 server[74756:2203] write Test::A +2008-09-05 18:27:29.705 server[74756:2203] write Test::B +2008-09-05 18:27:29.706 server[74756:2203] write Test::A +2008-09-05 18:27:29.706 server[74756:2203] write Test::B +2008-09-05 18:27:29.707 server[74756:2203] write Test::A +2008-09-05 18:27:29.707 server[74756:2203] write Test::B +2008-09-05 18:27:29.708 server[74756:2203] write Test::A +2008-09-05 18:27:29.708 server[74756:2203] write Test::B +2008-09-05 18:27:29.709 server[74756:2203] write Test::A +2008-09-05 18:27:29.709 server[74756:2203] write Test::B +2008-09-05 18:27:29.710 server[74756:2203] write Test::A +2008-09-05 18:27:29.710 server[74756:2203] write Test::B +2008-09-05 18:27:29.711 server[74756:2203] write Test::A +2008-09-05 18:27:29.711 server[74756:2203] write Test::B +2008-09-05 18:27:29.712 server[74756:2203] write Test::A +2008-09-05 18:27:29.712 server[74756:2203] write Test::B +2008-09-05 18:27:29.712 server[74756:2203] write Test::A +2008-09-05 18:27:29.713 server[74756:2203] write Test::B +2008-09-05 18:27:29.713 server[74756:2203] write Test::A +2008-09-05 18:27:29.714 server[74756:2203] write Test::B +2008-09-05 18:27:29.714 server[74756:2203] write Test::A +2008-09-05 18:27:29.715 server[74756:2203] write Test::B +2008-09-05 18:27:29.715 server[74756:2203] write Test::A +2008-09-05 18:27:29.716 server[74756:2203] write Test::B +2008-09-05 18:27:29.716 server[74756:2203] write Test::A +2008-09-05 18:27:29.717 server[74756:2203] write Test::B +2008-09-05 18:27:29.717 server[74756:2203] write Test::A +2008-09-05 18:27:29.718 server[74756:2203] write Test::B +2008-09-05 18:27:29.718 server[74756:2203] write Test::A +2008-09-05 18:27:29.719 server[74756:2203] write Test::B +2008-09-05 18:27:29.719 server[74756:2203] write Test::A +2008-09-05 18:27:29.720 server[74756:2203] write Test::B +2008-09-05 18:27:29.721 server[74756:2203] write Test::A +2008-09-05 18:27:29.721 server[74756:2203] write Test::B +2008-09-05 18:27:29.722 server[74756:2203] write Test::A +Traceback (most recent call last): + File "./run.py", line 26, in <module> + TestUtil.clientServerTest(name) + File "../../../../config/TestUtil.py", line 1067, in clientServerTest + clientServerTestWithOptions(name, "", "") + File "../../../../config/TestUtil.py", line 1063, in clientServerTestWithOptions + getDefaultClientFile()) + File "../../../../config/TestUtil.py", line 1044, in clientServerTestWithOptionsAndNames + printOutputFromPipe(clientPipe) + File "../../../../config/TestUtil.py", line 657, in printOutputFromPipe + c = pipe.read(1) +KeyboardInterrupt +2008-09-05 18:27:29.722 server[74756:2203] write Test::B +2008-09-05 18:27:29.724 server[74756:2203] write Test::A +2008-09-05 18:27:29.725 server[74756:2203] write Test::B +2008-09-05 18:27:29.725 server[74756:2203] write Test::A diff --git a/objc/test/Ice/operations/.gitignore b/objc/test/Ice/operations/.gitignore new file mode 100644 index 00000000000..cf5529b05c8 --- /dev/null +++ b/objc/test/Ice/operations/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +OperationsTest.m +OperationsTest.h diff --git a/objc/test/Ice/operations/AllTests.m b/objc/test/Ice/operations/AllTests.m new file mode 100644 index 00000000000..6313aec5f18 --- /dev/null +++ b/objc/test/Ice/operations/AllTests.m @@ -0,0 +1,52 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <OperationsTest.h> + +id<TestOperationsMyClassPrx> +operationsAllTests(id<ICECommunicator> communicator, BOOL collocated) +{ + NSString* ref = @"test:default -p 12010"; + id<ICEObjectPrx> base = [communicator stringToProxy:(ref)]; + id<TestOperationsMyClassPrx> cl = [TestOperationsMyClassPrx checkedCast:base]; + id<TestOperationsMyDerivedClassPrx> derived = [TestOperationsMyDerivedClassPrx checkedCast:cl]; + + tprintf("testing twoway operations... "); + void twoways(id<ICECommunicator>, id<TestOperationsMyClassPrx>); + twoways(communicator, cl); + twoways(communicator, derived); + [derived opDerived]; + tprintf("ok\n"); + + tprintf("testing oneway operations... "); + void oneways(id<ICECommunicator>, id<TestOperationsMyClassPrx>); + oneways(communicator, cl); + tprintf("ok\n"); + + tprintf("testing twoway operations with AMI... "); + void twowaysNewAMI(id<ICECommunicator>, id<TestOperationsMyClassPrx>); + twowaysNewAMI(communicator, cl); + twowaysNewAMI(communicator, derived); + tprintf("ok\n"); + + tprintf("testing oneway operations with AMI... "); + void onewaysNewAMI(id<ICECommunicator>, id<TestOperationsMyClassPrx>); + onewaysNewAMI(communicator, cl); + tprintf("ok\n"); + + tprintf("testing batch oneway operations... "); + void batchOneways(id<TestOperationsMyClassPrx>); + batchOneways(cl); + batchOneways(derived); + tprintf("ok\n"); + + return cl; +} diff --git a/objc/test/Ice/operations/BatchOneways.m b/objc/test/Ice/operations/BatchOneways.m new file mode 100644 index 00000000000..8c7aa0185ec --- /dev/null +++ b/objc/test/Ice/operations/BatchOneways.m @@ -0,0 +1,58 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <OperationsTest.h> + +void +batchOneways(id<TestOperationsMyClassPrx> p) +{ + ICEByte buf1[10 * 1024]; + ICEByte buf2[99 * 1024]; + TestOperationsMutableByteS *bs1 = [TestOperationsMutableByteS dataWithBytes:buf1 length:sizeof(buf1)]; + TestOperationsMutableByteS *bs2 = [TestOperationsMutableByteS dataWithBytes:buf2 length:sizeof(buf2)]; + + @try + { + [p opByteSOneway:bs1]; + } + @catch(ICEMemoryLimitException*) + { + test(NO); + } + + @try + { + [p opByteSOneway:bs2]; + } + @catch(ICEMemoryLimitException*) + { + test(NO); + } + + id<TestOperationsMyClassPrx> batch = [TestOperationsMyClassPrx uncheckedCast:[p ice_batchOneway]]; + int i; + + for(i = 0 ; i < 30 ; ++i) + { + @try + { + [batch opByteSOneway:bs1]; + } + @catch(ICEMemoryLimitException*) + { + test(NO); + } + } + + // TODO: XXX: port 3.6b changes + + [[batch ice_getConnection] flushBatchRequests]; +} diff --git a/objc/test/Ice/operations/Client.m b/objc/test/Ice/operations/Client.m new file mode 100644 index 00000000000..9d9b81fd2d1 --- /dev/null +++ b/objc/test/Ice/operations/Client.m @@ -0,0 +1,102 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <OperationsTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + id<TestOperationsMyClassPrx> operationsAllTests(id<ICECommunicator>, BOOL); + id<TestOperationsMyClassPrx> myClass = operationsAllTests(communicator, NO); + tprintf("testing server shutdown... "); + [myClass shutdown]; + @try + { + [myClass opVoid]; + test(false); + } + @catch(ICELocalException*) + { + tprintf("ok\n"); + } + + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main operationsClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); + // + // In this test, we need at least two threads in the + // client side thread pool for nested AMI. + // + [initData.properties setProperty:@"Ice.ThreadPool.Client.Size" value:@"2"]; + [initData.properties setProperty:@"Ice.ThreadPool.Client.SizeWarn" value:@"0"]; + + // + // We must set MessageSizeMax to an explicit values, because + // we run tests to check whether Ice.MemoryLimitException is + // raised as expected. + // + [initData.properties setProperty:@"Ice.MessageSizeMax" value:@"100"]; + +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestOperations", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/operations/Makefile b/objc/test/Ice/operations/Makefile new file mode 100644 index 00000000000..525dc8b30c7 --- /dev/null +++ b/objc/test/Ice/operations/Makefile @@ -0,0 +1,42 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = OperationsTest.o + +COBJS = Client.o \ + AllTests.o \ + Twoways.o \ + TwowaysNewAMI.o \ + Oneways.o \ + OnewaysNewAMI.o \ + BatchOneways.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/operations/Oneways.m b/objc/test/Ice/operations/Oneways.m new file mode 100644 index 00000000000..68957ea6f0d --- /dev/null +++ b/objc/test/Ice/operations/Oneways.m @@ -0,0 +1,37 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <OperationsTest.h> + +void +oneways(id<ICECommunicator> communicator, id<TestOperationsMyClassPrx> proxy) +{ + id<TestOperationsMyClassPrx> p = [TestOperationsMyClassPrx uncheckedCast:[proxy ice_oneway]]; + + { + [p opVoid]; + } + + { + ICEByte b; + ICEByte r; + + @try + { + r = [p opByte:(ICEByte)0xff p2:(ICEByte)0x0f p3:&b]; + test(NO); + } + @catch(ICETwowayOnlyException*) + { + } + } + +} diff --git a/objc/test/Ice/operations/OnewaysNewAMI.m b/objc/test/Ice/operations/OnewaysNewAMI.m new file mode 100644 index 00000000000..dfd2c476d01 --- /dev/null +++ b/objc/test/Ice/operations/OnewaysNewAMI.m @@ -0,0 +1,125 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <OperationsTest.h> + +#import <Foundation/Foundation.h> + +@interface OnewayNewAMICallback : NSObject +{ + BOOL called; + NSCondition* cond; +} +-(void) check; +-(void) called; +@end + +@implementation OnewayNewAMICallback +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + cond = [[NSCondition alloc] init]; + return self; +} + ++(id) create +{ +#if defined(__clang__) && __has_feature(objc_arc) + return [[OnewayNewAMICallback alloc] init]; +#else + return [[[OnewayNewAMICallback alloc] init] autorelease]; +#endif +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [super dealloc]; +} +#endif + +-(void) check +{ + [cond lock]; + while(!called) + { + [cond wait]; + } + called = NO; + [cond unlock]; +} +-(void) called +{ + [cond lock]; + called = YES; + [cond signal]; + [cond unlock]; +} +-(void) opVoidResponse +{ + [self called]; +} +-(void) opVoidException:(ICEException*)ex +{ + test(NO); +} +-(void) opVoidExResponse +{ + test(NO); +} +-(void) opVoidExException:(ICEException*)ex +{ + test([ex isKindOfClass:[ICENoEndpointException class]]); + [self called]; +} +-(void) opByteExResponse +{ + test(NO); +} +-(void) opByteEx:(ICEException*)ex +{ + test(NO); +} +-(void) opByteExException:(ICEException*)ex +{ + test([ex isKindOfClass:[ICETwowayOnlyException class]]); + [self called]; +} +@end + +void +onewaysNewAMI(id<ICECommunicator> communicator, id<TestOperationsMyClassPrx> proxy) +{ + id<TestOperationsMyClassPrx> p = [TestOperationsMyClassPrx uncheckedCast:[proxy ice_oneway]]; + + { + OnewayNewAMICallback* cb = [OnewayNewAMICallback create]; + [p begin_opVoid:^() { [cb opVoidResponse]; } exception:^(ICEException* ex) { [cb opVoidException:ex]; }]; + } + + { + OnewayNewAMICallback* cb = [OnewayNewAMICallback create]; + @try + { + [p begin_opByte:0 p2:0 response:^(ICEByte r, ICEByte p3) { [cb opByteExResponse]; } exception:^(ICEException* ex) { [cb opByteExException:ex]; }]; + [cb check]; + } + @catch(NSException* ex) + { + test([ex name] == NSInvalidArgumentException); + } + } +} diff --git a/objc/test/Ice/operations/OperationsTest.ice b/objc/test/Ice/operations/OperationsTest.ice new file mode 100644 index 00000000000..51e2df76ab6 --- /dev/null +++ b/objc/test/Ice/operations/OperationsTest.ice @@ -0,0 +1,221 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Ice/Current.ice> + +["objc:prefix:TestOperations"] +module Test +{ + +enum MyEnum +{ + enum1, + enum2, + enum3 +}; + +class MyClass; + +struct AnotherStruct +{ + string s; +}; + +struct Structure +{ + MyClass* p; + MyEnum e; + AnotherStruct s; +}; + +sequence<byte> ByteS; +sequence<bool> BoolS; +sequence<short> ShortS; +sequence<int> IntS; +sequence<long> LongS; +sequence<float> FloatS; +sequence<double> DoubleS; +sequence<string> StringS; +sequence<MyEnum> MyEnumS; +sequence<MyClass*> MyClassS; + +sequence<ByteS> ByteSS; +sequence<BoolS> BoolSS; +sequence<ShortS> ShortSS; +sequence<IntS> IntSS; +sequence<LongS> LongSS; +sequence<FloatS> FloatSS; +sequence<DoubleS> DoubleSS; +sequence<StringS> StringSS; +sequence<MyEnumS> MyEnumSS; +sequence<MyClassS> MyClassSS; + +sequence<StringSS> StringSSS; + +struct MyStruct +{ + int i; + int j; +}; + +dictionary<byte, bool> ByteBoolD; +dictionary<short, int> ShortIntD; +dictionary<long, float> LongFloatD; +dictionary<string, string> StringStringD; +dictionary<string, MyEnum> StringMyEnumD; +dictionary<MyEnum, string> MyEnumStringD; +dictionary<MyStruct, MyEnum> MyStructMyEnumD; + +sequence<Structure> StructS; // Used by Objective-C test only. + +struct Struct2 // Ensures the generated code for this struct compiles +{ + bool b; + int i; + float f; + double d; + byte by; + short sh; + long l; + StructS ss; + ByteBoolD dict; + MyEnumSS seq; +}; + +class A // Used Objective-C test only. +{ + int i; +}; + +sequence<A> AS; // Used by Objective-C test only. + +class MyClass +{ + void shutdown(); + + void opVoid(); + + byte opByte(byte p1, byte p2, + out byte p3); + + bool opBool(bool p1, bool p2, + out bool p3); + + long opShortIntLong(short p1, int p2, long p3, + out short p4, out int p5, out long p6); + + double opFloatDouble(float p1, double p2, + out float p3, out double p4); + + string opString(string p1, string p2, + out string p3); + + MyEnum opMyEnum(MyEnum p1, out MyEnum p2); + + MyClass* opMyClass(MyClass* p1, out MyClass* p2, out MyClass* p3); + + Structure opStruct(Structure p1, Structure p2, + out Structure p3); + + ByteS opByteS(ByteS p1, ByteS p2, + out ByteS p3); + + BoolS opBoolS(BoolS p1, BoolS p2, + out BoolS p3); + + LongS opShortIntLongS(Test::ShortS p1, IntS p2, LongS p3, + out ::Test::ShortS p4, out IntS p5, out LongS p6); + + DoubleS opFloatDoubleS(FloatS p1, DoubleS p2, + out FloatS p3, out DoubleS p4); + + StringS opStringS(StringS p1, StringS p2, + out StringS p3); + + MyEnumS opMyEnumS(MyEnumS p1, MyEnumS p2, + out MyEnumS p3); + + MyClassS opMyClassS(MyClassS p1, MyClassS p2, + out MyClassS p3); + + ByteSS opByteSS(ByteSS p1, ByteSS p2, + out ByteSS p3); + + BoolSS opBoolSS(BoolSS p1, BoolSS p2, + out BoolSS p3); + + LongSS opShortIntLongSS(ShortSS p1, IntSS p2, LongSS p3, + out ShortSS p4, out IntSS p5, out LongSS p6); + + + DoubleSS opFloatDoubleSS(FloatSS p1, DoubleSS p2, + out FloatSS p3, out DoubleSS p4); + + StringSS opStringSS(StringSS p1, StringSS p2, + out StringSS p3); + + StringSSS opStringSSS(StringSSS p1, StringSSS p2, + out StringSSS p3); + + ByteBoolD opByteBoolD(ByteBoolD p1, ByteBoolD p2, + out ByteBoolD p3); + + ShortIntD opShortIntD(ShortIntD p1, ShortIntD p2, + out ShortIntD p3); + + LongFloatD opLongFloatD(LongFloatD p1, LongFloatD p2, + out LongFloatD p3); + + StringStringD opStringStringD(StringStringD p1, StringStringD p2, + out StringStringD p3); + + StringMyEnumD opStringMyEnumD(StringMyEnumD p1, StringMyEnumD p2, + out StringMyEnumD p3); + + MyEnumStringD opMyEnumStringD(MyEnumStringD p1, MyEnumStringD p2, + out MyEnumStringD p3); + + MyStructMyEnumD opMyStructMyEnumD(MyStructMyEnumD p1, MyStructMyEnumD p2, + out MyStructMyEnumD p3); + + IntS opIntS(IntS s); + + void opByteSOneway(ByteS s); + + Ice::Context opContext(); + + void opDoubleMarshaling(double p1, DoubleS p2); + + idempotent void opIdempotent(); + + ["nonmutating"] idempotent void opNonmutating(); + + // + // Operations below are specific to Objective-C + // + + StringS getNSNullStringSeq(); + AS getNSNullASeq(); + StructS getNSNullStructSeq(); + StringSS getNSNullStringSeqSeq(); + + StringStringD getNSNullStringStringDict(); + void putNSNullStringStringDict(StringStringD d); + void putNSNullShortIntDict(ShortIntD d); + void putNSNullStringMyEnumDict(StringMyEnumD d); +}; + +class MyDerivedClass extends MyClass +{ + void opDerived(); +}; + +}; diff --git a/objc/test/Ice/operations/Server.m b/objc/test/Ice/operations/Server.m new file mode 100644 index 00000000000..48bd4314ba5 --- /dev/null +++ b/objc/test/Ice/operations/Server.m @@ -0,0 +1,93 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <operations/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestOperationsAdapter.Endpoints" value:@"default -p 12010:udp"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestOperationsAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + [adapter add:[[[TestOperationsMyDerivedClassI alloc] init] autorelease] + identity:[communicator stringToIdentity:@"test"]]; +#else + [adapter add:[[TestOperationsMyDerivedClassI alloc] init] + identity:[communicator stringToIdentity:@"test"]]; + +#endif + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main operationsServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); + + // + // Its possible to have batch oneway requests dispatched after + // the adapter is deactivated due to thread scheduling so we + // supress this warning. + // + [initData.properties setProperty:@"Ice.Warn.Dispatch" value:@"0"]; +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestOperations", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } + +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/operations/TestI.h b/objc/test/Ice/operations/TestI.h new file mode 100644 index 00000000000..9dad65b8578 --- /dev/null +++ b/objc/test/Ice/operations/TestI.h @@ -0,0 +1,16 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <OperationsTest.h> + +// +// Servant implementation +// +@interface TestOperationsMyDerivedClassI : TestOperationsMyDerivedClass<TestOperationsMyDerivedClass> +@end diff --git a/objc/test/Ice/operations/TestI.m b/objc/test/Ice/operations/TestI.m new file mode 100644 index 00000000000..58ae709ae10 --- /dev/null +++ b/objc/test/Ice/operations/TestI.m @@ -0,0 +1,470 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> + +#import <operations/TestI.h> +#import <TestCommon.h> + +@implementation TestOperationsMyDerivedClassI +-(void) opVoid:(ICECurrent*)current +{ +} + +-(void) opDerived:(ICECurrent*)current +{ +} + +-(ICEByte) opByte:(ICEByte)p1 p2:(ICEByte)p2 p3:(ICEByte *)p3 current:(ICECurrent *)current +{ + *p3 = p1 ^ p2; + return p1; +} + +-(BOOL) opBool:(BOOL)p1 p2:(BOOL)p2 p3:(BOOL *)p3 current:(ICECurrent*)current +{ + *p3 = p1; + return p2; +} + +-(ICELong) opShortIntLong:(ICEShort)p1 p2:(ICEInt)p2 p3:(ICELong)p3 + p4:(ICEShort *)p4 p5:(ICEInt *)p5 p6:(ICELong *)p6 + current:(ICECurrent *)current +{ + *p4 = p1; + *p5 = p2; + *p6 = p3; + return p3; +} + +-(ICEDouble) opFloatDouble:(ICEFloat)p1 p2:(ICEDouble)p2 p3:(ICEFloat *)p3 p4:(ICEDouble *)p4 + current:(ICECurrent *)current +{ + *p3 = p1; + *p4 = p2; + return p2; +} + +-(NSString *) opString:(NSMutableString *)p1 p2:(NSMutableString *)p2 p3:(NSString **)p3 current:(ICECurrent *)current +{ + NSMutableString *sout = [NSMutableString stringWithCapacity:([p2 length] + 1 + [p1 length])]; + [sout appendString:p2]; + [sout appendString:@" "]; + [sout appendString:p1]; + *p3 = sout; + + NSMutableString *ret = [NSMutableString stringWithCapacity:([p1 length] + 1 + [p2 length])]; + [ret appendString:p1]; + [ret appendString:@" "]; + [ret appendString:p2]; + return ret; +} + +-(TestOperationsMyEnum) opMyEnum:(TestOperationsMyEnum)p1 p2:(TestOperationsMyEnum *)p2 current:(ICECurrent *)current +{ + *p2 = p1; + return TestOperationsenum3; +} + +-(id<TestOperationsMyClassPrx>) opMyClass:(id<TestOperationsMyClassPrx>)p1 p2:(id<TestOperationsMyClassPrx> *)p2 p3:(id<TestOperationsMyClassPrx> *)p3 + current:(ICECurrent *)current +{ + *p2 = p1; + *p3 = [TestOperationsMyClassPrx uncheckedCast:[current.adapter + createProxy:[[current.adapter getCommunicator] + stringToIdentity:@"noSuchIdentity"]]]; + return [TestOperationsMyClassPrx uncheckedCast:[current.adapter createProxy:[current id_]]]; +} + +-(TestOperationsStructure *) opStruct:(TestOperationsStructure *)p1 p2:(TestOperationsStructure *)p2 p3:(TestOperationsStructure **)p3 + current:(ICECurrent *)current; +{ +#if defined(__clang__) && !__has_feature(objc_arc) + *p3 = [[p1 copy] autorelease]; +#else + *p3 = [p1 copy]; +#endif + (*p3).s.s = @"a new string"; + return p2; +} + +-(TestOperationsByteS *) opByteS:(TestOperationsMutableByteS *)p1 p2:(TestOperationsMutableByteS *)p2 p3:(TestOperationsByteS **)p3 + current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableByteS dataWithLength:[p1 length]]; + ICEByte *target = (ICEByte *)[*p3 bytes]; + ICEByte *src = (ICEByte *)[p1 bytes] + [p1 length]; + int i; + for(i = 0; i != [p1 length]; ++i) + { + *target++ = *--src; + } + TestOperationsMutableByteS *r = [TestOperationsMutableByteS dataWithData:p1]; + [r appendData:p2]; + return r; +} + +-(TestOperationsBoolS *) opBoolS:(TestOperationsMutableBoolS *)p1 p2:(TestOperationsMutableBoolS *)p2 p3:(TestOperationsBoolS **)p3 + current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableBoolS dataWithData:p1]; + [(TestOperationsMutableBoolS *)*p3 appendData:p2]; + + TestOperationsMutableBoolS *r = [TestOperationsMutableBoolS dataWithLength:[p1 length] * sizeof(BOOL)]; + BOOL *target = (BOOL *)[r bytes]; + BOOL *src = (BOOL *)([p1 bytes] + [p1 length]); + int i; + for(i = 0; i != [p1 length]; ++i) + { + *target++ = *--src; + } + return r; +} + +-(TestOperationsLongS *) opShortIntLongS:(TestOperationsMutableShortS *)p1 p2:(TestOperationsMutableIntS *)p2 p3:(TestOperationsMutableLongS *)p3 + p4:(TestOperationsShortS **)p4 p5:(TestOperationsIntS **)p5 p6:(TestOperationsLongS **)p6 + current:(ICECurrent *)current +{ + *p4 = [TestOperationsMutableShortS dataWithData:p1]; + *p5 = [TestOperationsMutableIntS dataWithLength:[p2 length]]; + ICEInt *target = (ICEInt *)[*p5 bytes]; + ICEInt *src = (ICEInt *)([p2 bytes] + [p2 length]); + int i; + for(i = 0; i != [p2 length] / sizeof(ICEInt); ++i) + { + *target++ = *--src; + } + *p6 = [TestOperationsMutableLongS dataWithData:p3]; + [(TestOperationsMutableLongS *)*p6 appendData:p3]; + return p3; +} + +-(TestOperationsDoubleS *) opFloatDoubleS:(TestOperationsMutableFloatS *)p1 p2:(TestOperationsMutableDoubleS *)p2 + p3:(TestOperationsFloatS **)p3 p4:(TestOperationsDoubleS **)p4 current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableFloatS dataWithData:p1]; + *p4 = [TestOperationsMutableDoubleS dataWithLength:[p2 length]]; + ICEDouble *target = (ICEDouble *)[*p4 bytes]; + ICEDouble *src = (ICEDouble *)([p2 bytes] + [p2 length]); + int i; + for(i = 0; i != [p2 length] / sizeof(ICEDouble); ++i) + { + *target++ = *--src; + } + TestOperationsDoubleS *r = [TestOperationsMutableDoubleS dataWithLength:([p2 length] + + ([p1 length] / sizeof(ICEFloat) * sizeof(ICEDouble)))]; + ICEDouble *rp = (ICEDouble *)[r bytes]; + ICEDouble *p2p = (ICEDouble *)[p2 bytes]; + for(i = 0; i < [p2 length] / sizeof(ICEDouble); ++i) + { + *rp++ = *p2p++; + } + ICEFloat *bp1 = (ICEFloat *)[p1 bytes]; + for(i = 0; i < [p1 length] / sizeof(ICEFloat); ++i) + { + *rp++ = bp1[i]; + } + return r; +} + +-(TestOperationsStringS *) opStringS:(TestOperationsMutableStringS *)p1 p2:(TestOperationsMutableStringS *)p2 + p3:(TestOperationsStringS **)p3 current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableStringS arrayWithArray:p1]; + [(TestOperationsMutableStringS *)*p3 addObjectsFromArray:p2]; + TestOperationsMutableStringS *r = [TestOperationsMutableStringS arrayWithCapacity:[p1 count]]; + NSEnumerator *enumerator = [p1 reverseObjectEnumerator]; + for(NSString *element in enumerator) + { + [r addObject:element]; + } + return r; +} + +-(TestOperationsMyEnumS *) opMyEnumS:(TestOperationsMutableMyEnumS *)p1 p2:(TestOperationsMutableMyEnumS *)p2 + p3:(TestOperationsMyEnumS **)p3 current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableMyEnumS dataWithLength:[p1 length]]; + TestOperationsMyEnum *target = (TestOperationsMyEnum *)[*p3 bytes]; + TestOperationsMyEnum *src = (TestOperationsMyEnum *)([p1 bytes] + [p1 length]); + int i; + for(i = 0; i != [p1 length] / sizeof(TestOperationsMyEnum); ++i) + { + *target++ = *--src; + } + TestOperationsMutableMyEnumS *r = [TestOperationsMutableMyEnumS dataWithData:p1]; + [r appendData:p2]; + return r; +} + +-(TestOperationsMyClassS *) opMyClassS:(TestOperationsMutableMyClassS *)p1 p2:(TestOperationsMutableMyClassS *)p2 + p3:(TestOperationsMyClassS **)p3 current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableMyClassS arrayWithArray:p1]; + [(TestOperationsMutableMyClassS *)*p3 addObjectsFromArray:p2]; + TestOperationsMutableMyClassS *r = [TestOperationsMutableMyClassS arrayWithCapacity:[p1 count]]; + NSEnumerator *enumerator = [p1 reverseObjectEnumerator]; + for(NSString *element in enumerator) + { + [r addObject:element]; + } + return r; +} + +-(TestOperationsByteSS *) opByteSS:(TestOperationsMutableByteSS *)p1 p2:(TestOperationsMutableByteSS *)p2 p3:(TestOperationsByteSS * *)p3 + current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableByteSS array]; + NSEnumerator *enumerator = [p1 reverseObjectEnumerator]; + for(TestOperationsByteS *element in enumerator) + { + [(TestOperationsMutableByteSS *)*p3 addObject:element]; + } + + TestOperationsMutableByteSS *r = [TestOperationsMutableByteSS arrayWithArray:p1]; + [r addObjectsFromArray:p2]; + return r; +} + +-(TestOperationsBoolSS *) opBoolSS:(TestOperationsMutableBoolSS *)p1 p2:(TestOperationsMutableBoolSS *)p2 p3:(TestOperationsBoolSS * *)p3 + current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableBoolSS arrayWithArray:p1]; + [(TestOperationsMutableBoolSS *)*p3 addObjectsFromArray:p2]; + + TestOperationsMutableBoolSS *r = [TestOperationsMutableBoolSS array]; + NSEnumerator *enumerator = [p1 reverseObjectEnumerator]; + for(TestOperationsBoolS *element in enumerator) + { + [r addObject:element]; + } + return r; +} + +-(TestOperationsLongSS *) opShortIntLongSS:(TestOperationsMutableShortSS *)p1 p2:(TestOperationsMutableIntSS *)p2 p3:(TestOperationsMutableLongSS *)p3 + p4:(TestOperationsShortSS **)p4 p5:(TestOperationsIntSS **)p5 p6:(TestOperationsLongSS **)p6 + current:(ICECurrent *)current +{ + *p4 = [TestOperationsShortSS arrayWithArray:p1]; + *p5 = [TestOperationsMutableIntSS array]; + NSEnumerator *enumerator = [p2 reverseObjectEnumerator]; + for(TestOperationsIntS *element in enumerator) + { + [(TestOperationsMutableIntSS *)*p5 addObject:element]; + } + *p6 = [TestOperationsMutableLongSS arrayWithArray:p3]; + [(TestOperationsMutableLongSS *)*p6 addObjectsFromArray:p3]; + return p3; +} + +-(TestOperationsDoubleSS *) opFloatDoubleSS:(TestOperationsMutableFloatSS *)p1 p2:(TestOperationsMutableDoubleSS *)p2 + p3:(TestOperationsFloatSS **)p3 p4:(TestOperationsDoubleSS **)p4 current:(ICECurrent *)current +{ + *p3 = [TestOperationsFloatSS arrayWithArray:p1]; + *p4 = [TestOperationsMutableDoubleSS array]; + NSEnumerator *enumerator = [p2 reverseObjectEnumerator]; + for(TestOperationsDoubleS *element in enumerator) + { + [(TestOperationsMutableDoubleSS *)*p4 addObject:element]; + } + TestOperationsMutableDoubleSS *r = [TestOperationsMutableDoubleSS arrayWithArray:p2]; + [r addObjectsFromArray:p2]; + return r; +} + +-(TestOperationsStringSS *) opStringSS:(TestOperationsMutableStringSS *)p1 p2:(TestOperationsMutableStringSS *)p2 p3:(TestOperationsStringSS **)p3 + current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableStringSS arrayWithArray:p1]; + [(TestOperationsMutableStringSS *)*p3 addObjectsFromArray:p2]; + TestOperationsMutableStringSS *r = [TestOperationsMutableStringSS array]; + NSEnumerator *enumerator = [p2 reverseObjectEnumerator]; + for(TestOperationsStringS *element in enumerator) + { + [r addObject:element]; + } + return r; +} + +-(TestOperationsStringSSS *) opStringSSS:(TestOperationsMutableStringSSS *)p1 p2:(TestOperationsMutableStringSSS *)p2 p3:(TestOperationsStringSSS **)p3 + current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableStringSSS arrayWithArray:p1]; + [(TestOperationsMutableStringSSS *)*p3 addObjectsFromArray:p2]; + TestOperationsMutableStringSSS *r = [TestOperationsMutableStringSSS array]; + NSEnumerator *enumerator = [p2 reverseObjectEnumerator]; + for(TestOperationsStringSS *element in enumerator) + { + [r addObject:element]; + } + return r; +} + +-(TestOperationsByteBoolD *) opByteBoolD:(TestOperationsMutableByteBoolD *)p1 p2:(TestOperationsMutableByteBoolD *)p2 p3:(TestOperationsByteBoolD **)p3 + current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableByteBoolD dictionaryWithDictionary:p1]; + TestOperationsMutableByteBoolD *r = [TestOperationsMutableByteBoolD dictionaryWithDictionary:p1]; + [r addEntriesFromDictionary:p2]; + return r; +} + +-(TestOperationsShortIntD *) opShortIntD:(TestOperationsMutableShortIntD *)p1 p2:(TestOperationsMutableShortIntD *)p2 p3:(TestOperationsShortIntD **)p3 + current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableShortIntD dictionaryWithDictionary:p1]; + TestOperationsMutableShortIntD *r = [TestOperationsMutableShortIntD dictionaryWithDictionary:p1]; + [r addEntriesFromDictionary:p2]; + return r; +} + +-(TestOperationsLongFloatD *) opLongFloatD:(TestOperationsMutableLongFloatD *)p1 p2:(TestOperationsMutableLongFloatD *)p2 p3:(TestOperationsLongFloatD **)p3 + current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableLongFloatD dictionaryWithDictionary:p1]; + TestOperationsMutableLongFloatD *r = [TestOperationsMutableLongFloatD dictionaryWithDictionary:p1]; + [r addEntriesFromDictionary:p2]; + return r; +} + +-(TestOperationsStringStringD *) opStringStringD:(TestOperationsMutableStringStringD *)p1 p2:(TestOperationsMutableStringStringD *)p2 + p3:(TestOperationsStringStringD **)p3 current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableStringStringD dictionaryWithDictionary:p1]; + TestOperationsMutableStringStringD *r = [TestOperationsMutableStringStringD dictionaryWithDictionary:p1]; + [r addEntriesFromDictionary:p2]; + return r; +} + +-(TestOperationsStringMyEnumD *) opStringMyEnumD:(TestOperationsMutableStringMyEnumD *)p1 + p2:(TestOperationsMutableStringMyEnumD *)p2 + p3:(TestOperationsStringMyEnumD **)p3 current:(ICECurrent *)current +{ + *p3 = [TestOperationsMutableStringMyEnumD dictionaryWithDictionary:p1]; + TestOperationsMutableStringMyEnumD *r = [TestOperationsMutableStringMyEnumD dictionaryWithDictionary:p1]; + [r addEntriesFromDictionary:p2]; + return r; +} + +-(TestOperationsMyEnumStringD *) opMyEnumStringD:(TestOperationsMyEnumStringD*)p1 + p2:(TestOperationsMyEnumStringD*)p2 + p3:(TestOperationsMyEnumStringD**)p3 + current:(ICECurrent*)current +{ + *p3 = [TestOperationsMutableMyEnumStringD dictionaryWithDictionary:p1]; + TestOperationsMutableMyEnumStringD *r = [TestOperationsMutableMyEnumStringD dictionaryWithDictionary:p1]; + [r addEntriesFromDictionary:p2]; + return r; +} + +-(TestOperationsMyStructMyEnumD *) opMyStructMyEnumD:(TestOperationsMyStructMyEnumD*)p1 + p2:(TestOperationsMyStructMyEnumD*)p2 + p3:(TestOperationsMyStructMyEnumD**)p3 + current:(ICECurrent*)current +{ + *p3 = [TestOperationsMutableMyStructMyEnumD dictionaryWithDictionary:p1]; + TestOperationsMutableMyStructMyEnumD *r = [TestOperationsMutableMyStructMyEnumD dictionaryWithDictionary:p1]; + [r addEntriesFromDictionary:p2]; + return r; +} + +-(TestOperationsIntS *) opIntS:(TestOperationsMutableIntS *)p1 current:(ICECurrent *)current +{ + NSUInteger count = [p1 length] / sizeof(ICEInt); + TestOperationsMutableIntS *r = [TestOperationsMutableIntS dataWithLength:[p1 length]]; + const int *src = [p1 bytes]; + int *target = (int *)[r bytes]; + while(count-- > 0) + { + *target++ = -*src++; + } + return r; +} + +-(void) opByteSOneway:(TestOperationsMutableByteS *)p1 current:(ICECurrent *)current +{ +} + +-(ICEContext *) opContext:(ICECurrent *)current +{ + return current.ctx; +} + +-(void) opDoubleMarshaling:(ICEDouble)p1 p2:(TestOperationsMutableDoubleS *)p2 current:(ICECurrent *)current +{ + ICEDouble d = 1278312346.0 / 13.0; + test(p1 == d); + const ICEDouble *p = [p2 bytes]; + int i; + for(i = 0; i < [p2 length] / sizeof(ICEDouble); ++i) + { + test(p[i] == d); + } +} + +-(void) opIdempotent:(ICECurrent*)current +{ + test([current mode] == ICEIdempotent); +} + +-(void) opNonmutating:(ICECurrent*)current +{ + test([current mode] == ICENonmutating); +} + +-(TestOperationsStringS *) getNSNullStringSeq:(ICECurrent *)current +{ + return [NSArray arrayWithObjects:@"first", [NSNull null], nil]; +} + +-(TestOperationsMyClassS *) getNSNullASeq:(ICECurrent *)current +{ + return [NSArray arrayWithObjects:[TestOperationsA a:99], [NSNull null], nil]; +} + +-(TestOperationsStructS *) getNSNullStructSeq:(ICECurrent *)current +{ + TestOperationsStructure *s = [TestOperationsStructure structure:nil e:TestOperationsenum2 s:[TestOperationsAnotherStruct anotherStruct:@"Hello"]]; + return [NSArray arrayWithObjects:s, [NSNull null], nil]; +} + +-(TestOperationsStringSS *) getNSNullStringSeqSeq:(ICECurrent *)current +{ + TestOperationsStringSS *s = [NSArray arrayWithObjects:@"first", nil]; + return [NSArray arrayWithObjects:s, [NSNull null], nil]; +} + +-(TestOperationsStringStringD *) getNSNullStringStringDict:(ICECurrent *)current +{ + TestOperationsMutableStringStringD *d = [TestOperationsMutableStringStringD dictionary]; + [d setObject:@"ONE" forKey:@"one"]; + [d setObject:[NSNull null] forKey:@"two"]; + return d; +} + +-(void) putNSNullStringStringDict:(TestOperationsMutableStringStringD *)d current:(ICECurrent *)current +{ + // Nothing to do because this tests that an exception is thrown on the client side. +} + +-(void) putNSNullShortIntDict:(TestOperationsMutableShortIntD *)d current:(ICECurrent *)current +{ + // Nothing to do because this tests that an exception is thrown on the client side. +} + +-(void) putNSNullStringMyEnumDict:(TestOperationsMutableStringMyEnumD *)d current:(ICECurrent *)current +{ + // Nothing to do because this tests that an exception is thrown on the client side. +} + +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} +@end diff --git a/objc/test/Ice/operations/Twoways.m b/objc/test/Ice/operations/Twoways.m new file mode 100644 index 00000000000..8eddf1ab753 --- /dev/null +++ b/objc/test/Ice/operations/Twoways.m @@ -0,0 +1,1094 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <OperationsTest.h> +#import <limits.h> +#import <float.h> + +#import <Foundation/Foundation.h> + +@interface PerThreadContextInvokeThread : NSThread +{ + id<TestOperationsMyClassPrx> proxy; + NSCondition* cond; + BOOL called; +} +-(id) init:(id<TestOperationsMyClassPrx>)proxy_; ++(id) create:(id<TestOperationsMyClassPrx>)proxy_; +-(void) join; +-(void) run; +@end + +@implementation PerThreadContextInvokeThread +-(id) init:(id<TestOperationsMyClassPrx>)proxy_ +{ + self = [super initWithTarget:self selector:@selector(run) object:nil]; + if(self) + { + self->called = NO; +#if defined(__clang__) && !__has_feature(objc_arc) + self->proxy = [proxy_ retain]; +#else + self->proxy = proxy_; +#endif + cond = [[NSCondition alloc] init]; + } + return self; +} + ++(id) create:(id<TestOperationsMyClassPrx>)proxy_ +{ +#if defined(__clang__) && __has_feature(objc_arc) + return [[PerThreadContextInvokeThread alloc] init:proxy_]; +#else + return [[[PerThreadContextInvokeThread alloc] init:proxy_] autorelease]; +#endif +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [proxy release]; + [cond release]; + [super dealloc]; +} +#endif + +-(void) run +{ + [cond lock]; + ICEMutableContext* ctx = [[[proxy ice_getCommunicator] getImplicitContext] getContext]; + test([ctx count] == 0); + [ctx setObject:@"UN" forKey:@"one" ]; + [[[proxy ice_getCommunicator] getImplicitContext] setContext:ctx]; + called = YES; + [cond signal]; + [cond unlock]; +} + +-(void) join +{ + [cond lock]; + while(!called) + { + [cond wait]; + } + [cond unlock]; +} +@end + +void +twoways(id<ICECommunicator> communicator, id<TestOperationsMyClassPrx> p) +{ + { + [p opVoid]; + } + + { + ICEByte b; + ICEByte r; + + r = [p opByte:(ICEByte)0xff p2:(ICEByte)0x0f p3:&b]; + test(b == (ICEByte)0xf0); + test(r == (ICEByte)0xff); + } + + { + BOOL b; + BOOL r; + + r = [p opBool:YES p2:NO p3:&b]; + test(b); + test(!r); + } + + { + ICEShort s; + ICEInt i; + ICELong l; + ICELong r; + + r = [p opShortIntLong:10 p2:11 p3:12 p4:&s p5:&i p6:&l]; + test(s == 10); + test(i == 11); + test(l == 12); + test(r == 12); + +#ifndef SHORT_MIN +#define SHORT_MIN (-0x7fff) +#endif + r = [p opShortIntLong:SHORT_MIN p2:INT_MIN p3:LONG_MIN p4:&s p5:&i p6:&l]; + test(s == SHORT_MIN); + test(i == INT_MIN); + test(l == LONG_MIN); + test(r == LONG_MIN); + +#ifndef SHORT_MAX +#define SHORT_MAX 0x7fff +#endif + r = [p opShortIntLong:SHORT_MAX p2:INT_MAX p3:LONG_MAX p4:&s p5:&i p6:&l]; + test(s == SHORT_MAX); + test(i == INT_MAX); + test(l == LONG_MAX); + test(r == LONG_MAX); + } + + { + ICEFloat f; + ICEDouble d; + ICEDouble r; + + r = [p opFloatDouble:3.14f p2:1.1E10 p3:&f p4:&d]; + test(f == 3.14f); + test(d == 1.1E10); + test(r == 1.1E10); + + r = [p opFloatDouble:FLT_MIN p2:DBL_MIN p3:&f p4:&d]; + test(f == FLT_MIN); + test(d == DBL_MIN); + test(r == DBL_MIN); + + r = [p opFloatDouble:FLT_MAX p2:DBL_MAX p3:&f p4:&d]; + test(f == FLT_MAX); + test(d == DBL_MAX); + test(r == DBL_MAX); + } + + { + NSMutableString *s = nil; + NSMutableString *r; + + r = [p opString:@"hello" p2:@"world" p3:&s]; + r = [p opString:@"hello" p2:@"world" p3:&s]; + r = [p opString:@"hello" p2:@"world" p3:&s]; + r = [p opString:@"hello" p2:@"world" p3:&s]; + test([s isEqualToString:@"world hello"]); + test([r isEqualToString:@"hello world"]); + } + + { + TestOperationsMyEnum e; + TestOperationsMyEnum r; + + r = [p opMyEnum:TestOperationsenum2 p2:&e]; + test(e == TestOperationsenum2); + test(r == TestOperationsenum3); + } + + { + id<TestOperationsMyClassPrx> c1; + id<TestOperationsMyClassPrx> c2; + id<TestOperationsMyClassPrx> r; + + r = [p opMyClass:p p2:&c1 p3:&c2]; + test([c1 compareIdentityAndFacet:p] == NSOrderedSame); + test([c2 compareIdentityAndFacet:p] != NSOrderedSame); + test([r compareIdentityAndFacet:p] == NSOrderedSame); + test([[c1 ice_getIdentity] isEqual:[communicator stringToIdentity:@"test"]]); + test([[c2 ice_getIdentity]isEqual:[communicator stringToIdentity:@"noSuchIdentity"]]); + test([[r ice_getIdentity] isEqual:[communicator stringToIdentity:@"test"]]); + [r opVoid]; + [c1 opVoid]; + @try + { + [c2 opVoid]; + test(NO); + } + @catch(ICEObjectNotExistException*) + { + } + + r = [p opMyClass:0 p2:&c1 p3:&c2]; + test(c1 == nil); + test(c2 != nil); + test([r compareIdentityAndFacet:p] == NSOrderedSame); + [r opVoid]; + } + + { + TestOperationsStructure *si1 = [TestOperationsStructure structure]; + si1.p = p; + si1.e = TestOperationsenum3; + si1.s = [TestOperationsAnotherStruct anotherStruct]; + si1.s.s = @"abc"; + TestOperationsStructure *si2 = [TestOperationsStructure structure]; + si2.p = nil; + si2.e = TestOperationsenum2; + si2.s = [TestOperationsAnotherStruct anotherStruct]; + si2.s.s = @"def"; + + TestOperationsStructure *so; + TestOperationsStructure *rso = [p opStruct:si1 p2:si2 p3:&so]; + + test(rso.p == nil); + test(rso.e == TestOperationsenum2); + test([rso.s.s isEqualToString:@"def"]); + test(so.p != nil); + test([so.p isEqual:p]); + test(so.e == TestOperationsenum3); + test([so.s.s isEqualToString:@"a new string"]); + [so.p opVoid]; + } + + { + ICEByte buf1[] = { 0x01, 0x11, 0x12, 0x22 }; + ICEByte buf2[] = { 0xf1, 0xf2, 0xf3, 0xf4 }; + + TestOperationsMutableByteS *bsi1 = [TestOperationsMutableByteS data]; + TestOperationsMutableByteS *bsi2 = [TestOperationsMutableByteS data]; + + [bsi1 appendBytes:buf1 length:sizeof(buf1)]; + [bsi2 appendBytes:buf2 length:sizeof(buf2)]; + + TestOperationsMutableByteS *bso; + TestOperationsByteS *rso; + + rso = [p opByteS:bsi1 p2:bsi2 p3:&bso]; + + test([bso length] == 4); + ICEByte *bbso = (ICEByte *)[bso bytes]; + test(bbso[0] == 0x22); + test(bbso[1] == 0x12); + test(bbso[2] == 0x11); + test(bbso[3] == 0x01); + test([rso length] == 8); + ICEByte *brso = (ICEByte *)[rso bytes]; + test(brso[0] == 0x01); + test(brso[1] == 0x11); + test(brso[2] == 0x12); + test(brso[3] == 0x22); + test(brso[4] == 0xf1); + test(brso[5] == 0xf2); + test(brso[6] == 0xf3); + test(brso[7] == 0xf4); + } + + { + BOOL buf1[] = { YES, YES, NO }; + BOOL buf2[] = { NO }; + + TestOperationsMutableBoolS *bsi1 = [TestOperationsMutableBoolS data]; + TestOperationsMutableBoolS *bsi2 = [TestOperationsMutableBoolS data]; + + [bsi1 appendBytes:buf1 length:sizeof(buf1)]; + [bsi2 appendBytes:buf2 length:sizeof(buf2)]; + + TestOperationsMutableBoolS *bso; + TestOperationsBoolS *rso; + + rso = [p opBoolS:bsi1 p2:bsi2 p3:&bso]; + + test([bso length] == 4 * sizeof(BOOL)); + BOOL *bbso = (BOOL *)[bso bytes]; + test(bbso[0]); + test(bbso[1]); + test(!bbso[2]); + test(!bbso[3]); + test([rso length] == 3 * sizeof(BOOL)); + BOOL *brso = (BOOL *)[rso bytes]; + test(!brso[0]); + test(brso[1]); + test(brso[2]); + } + + { + ICEShort buf1[] = { 1, 2, 3 }; + ICEInt buf2[] = { 5, 6, 7, 8 }; + ICELong buf3[] = { 10, 30, 20 }; + + TestOperationsMutableShortS *ssi = [TestOperationsMutableShortS data]; + TestOperationsMutableIntS *isi = [TestOperationsMutableIntS data]; + TestOperationsMutableLongS *lsi = [TestOperationsMutableLongS data]; + + [ssi appendBytes:buf1 length:sizeof(buf1)]; + [isi appendBytes:buf2 length:sizeof(buf2)]; + [lsi appendBytes:buf3 length:sizeof(buf3)]; + + TestOperationsMutableShortS *sso; + TestOperationsMutableIntS *iso; + TestOperationsMutableLongS *lso; + TestOperationsLongS *rso; + + rso = [p opShortIntLongS:ssi p2:isi p3:lsi p4:&sso p5:&iso p6:&lso]; + + test([sso length] == 3 * sizeof(ICEShort)); + ICEShort *bsso = (ICEShort *)[sso bytes]; + test(bsso[0] == 1); + test(bsso[1] == 2); + test(bsso[2] == 3); + test([iso length] == 4 * sizeof(ICEInt)); + ICEInt *biso = (ICEInt *)[iso bytes]; + test(biso[0] == 8); + test(biso[1] == 7); + test(biso[2] == 6); + test(biso[3] == 5); + test([lso length] == 6 * sizeof(ICELong)); + ICELong *blso = (ICELong *)[lso bytes]; + test(blso[0] == 10); + test(blso[1] == 30); + test(blso[2] == 20); + test(blso[3] == 10); + test(blso[4] == 30); + test(blso[5] == 20); + test([rso length] == 3 * sizeof(ICELong)); + ICELong *brso = (ICELong *)[rso bytes]; + test(brso[0] == 10); + test(brso[1] == 30); + test(brso[2] == 20); + } + + { + ICEFloat buf1[] = { 3.14f, 1.11f }; + ICEDouble buf2[] = { 1.1E10, 1.2E10, 1.3E10 }; + + TestOperationsMutableFloatS *fsi = [TestOperationsMutableFloatS data]; + TestOperationsMutableDoubleS *dsi = [TestOperationsMutableDoubleS data]; + + [fsi appendBytes:buf1 length:sizeof(buf1)]; + [dsi appendBytes:buf2 length:sizeof(buf2)]; + + TestOperationsMutableFloatS *fso; + TestOperationsMutableDoubleS *dso; + TestOperationsDoubleS *rso; + + rso = [p opFloatDoubleS:fsi p2:dsi p3:&fso p4:&dso]; + + test([fso length] == 2 * sizeof(ICEFloat)); + ICEFloat *bfso = (ICEFloat *)[fso bytes]; + test(bfso[0] == 3.14f); + test(bfso[1] == 1.11f); + test([dso length] == 3 * sizeof(ICEDouble)); + ICEDouble *bdso = (ICEDouble *)[dso bytes]; + test(bdso[0] == 1.3E10); + test(bdso[1] == 1.2E10); + test(bdso[2] == 1.1E10); + test([rso length] == 5 * sizeof(ICEDouble)); + ICEDouble *brso = (ICEDouble *)[rso bytes]; + test(brso[0] == 1.1E10); + test(brso[1] == 1.2E10); + test(brso[2] == 1.3E10); + test((ICEFloat)brso[3] == 3.14f); + test((ICEFloat)brso[4] == 1.11f); + } + + { + TestOperationsMutableStringS *ssi1 = [TestOperationsMutableStringS arrayWithCapacity:3]; + TestOperationsMutableStringS *ssi2 = [TestOperationsMutableStringS arrayWithCapacity:1]; + + [ssi1 addObject:@"abc"]; + [ssi1 addObject:@"de"]; + [ssi1 addObject:@"fghi"]; + + [ssi2 addObject:@"xyz"]; + + TestOperationsMutableStringS *sso; + TestOperationsStringS *rso; + + rso = [p opStringS:ssi1 p2:ssi2 p3:&sso]; + + test([sso count] == 4); + test([[sso objectAtIndex:0] isEqualToString:@"abc"]); + test([[sso objectAtIndex:1] isEqualToString:@"de"]); + test([[sso objectAtIndex:2] isEqualToString:@"fghi"]); + test([[sso objectAtIndex:3] isEqualToString:@"xyz"]); + test([rso count] == 3); + test([[rso objectAtIndex:0] isEqualToString:@"fghi"]); + test([[rso objectAtIndex:1] isEqualToString:@"de"]); + test([[rso objectAtIndex:2] isEqualToString:@"abc"]); + } + + @try + { + TestOperationsMutableMyClassS *ssi1 = [TestOperationsMutableMyClassS arrayWithCapacity:3]; + TestOperationsMutableMyClassS *ssi2 = [TestOperationsMutableMyClassS arrayWithCapacity:1]; + + ICEIdentity *i1 = [ICEIdentity identity:@"abc" category:@""]; + ICEIdentity *i2 = [ICEIdentity identity:@"de" category:@""]; + ICEIdentity *i3 = [ICEIdentity identity:@"fhgi" category:@""]; + ICEIdentity *i4 = [ICEIdentity identity:@"xyz" category:@""]; + + [ssi1 addObject:[p ice_identity:i1]]; + [ssi1 addObject:[p ice_identity:i2]]; + [ssi1 addObject:[p ice_identity:i3]]; + + [ssi2 addObject:[p ice_identity:i4]]; + + TestOperationsMutableMyClassS *sso; + TestOperationsMyClassS *rso; + + rso = [p opMyClassS:ssi1 p2:ssi2 p3:&sso]; + + test([sso count] == 4); + test([[[sso objectAtIndex:0] ice_getIdentity] isEqual:i1]); + test([[[sso objectAtIndex:1] ice_getIdentity] isEqual:i2]); + test([[[sso objectAtIndex:2] ice_getIdentity] isEqual:i3]); + test([[[sso objectAtIndex:3] ice_getIdentity] isEqual:i4]); + test([rso count] == 3); + test([[[rso objectAtIndex:0] ice_getIdentity] isEqual:i3]); + test([[[rso objectAtIndex:1] ice_getIdentity] isEqual:i2]); + test([[[rso objectAtIndex:2] ice_getIdentity] isEqual:i1]); + } + @catch(ICEOperationNotExistException*) + { + // Some mapping don't implement this method. + } + + @try + { + TestOperationsMyEnum buf1[] = { TestOperationsenum2, TestOperationsenum3, TestOperationsenum3 }; + TestOperationsMyEnum buf2[] = { TestOperationsenum1 }; + + TestOperationsMutableMyEnumS *esi1 = [TestOperationsMutableMyEnumS data]; + TestOperationsMutableMyEnumS *esi2 = [TestOperationsMutableMyEnumS data]; + + [esi1 appendBytes:buf1 length:sizeof(buf1)]; + [esi2 appendBytes:buf2 length:sizeof(buf2)]; + + TestOperationsMutableMyEnumS *eso; + TestOperationsMyEnumS *rso; + + rso = [p opMyEnumS:esi1 p2:esi2 p3:&eso]; + + test([eso length] / sizeof(TestOperationsMyEnum) == 3); + const TestOperationsMyEnum *beso = (const TestOperationsMyEnum *)[eso bytes]; + test(beso[0] == TestOperationsenum3); + test(beso[1] == TestOperationsenum3); + test(beso[2] == TestOperationsenum2); + test([rso length] / sizeof(TestOperationsMyEnum) == 4); + const TestOperationsMyEnum *brso = (const TestOperationsMyEnum *)[rso bytes]; + test(brso[0] == TestOperationsenum2); + test(brso[1] == TestOperationsenum3); + test(brso[2] == TestOperationsenum3); + test(brso[3] == TestOperationsenum1); + } + @catch(ICEOperationNotExistException*) + { + // Some mapping don't implement this method. + } + + { + TestOperationsMutableByteSS *bsi1 = [TestOperationsMutableByteSS array]; + TestOperationsMutableByteSS *bsi2 = [TestOperationsMutableByteSS array]; + + ICEByte b; + TestOperationsMutableByteS *tmp = [TestOperationsMutableByteS data]; + + b = 0x01; + [tmp appendBytes:&b length:sizeof(b)]; + b = 0x11; + [tmp appendBytes:&b length:sizeof(b)]; + b = 0x12; + [tmp appendBytes:&b length:sizeof(b)]; + [bsi1 addObject:tmp]; + + tmp = [TestOperationsMutableByteS data]; + b = 0xff; + [tmp appendBytes:&b length:sizeof(b)]; + [bsi1 addObject:tmp]; + + tmp = [TestOperationsMutableByteS data]; + b = 0x0e; + [tmp appendBytes:&b length:sizeof(b)]; + [bsi2 addObject:tmp]; + + tmp = [TestOperationsMutableByteS data]; + b = 0xf2; + [tmp appendBytes:&b length:sizeof(b)]; + b = 0xf1; + [tmp appendBytes:&b length:sizeof(b)]; + [bsi2 addObject:tmp]; + + TestOperationsMutableByteSS *bso; + TestOperationsByteSS *rso; + + rso = [p opByteSS:bsi1 p2:bsi2 p3:&bso]; + + const ICEByte *p; + test([bso count] == 2); + test([[bso objectAtIndex:0] length] / sizeof(ICEByte) == 1); + p = [[bso objectAtIndex:0] bytes]; + test(p[0] == (ICEByte)0x0ff); + test([[bso objectAtIndex:1] length] / sizeof(ICEByte) == 3); + p = [[bso objectAtIndex:1] bytes]; + test(p[0] == (ICEByte)0x01); + test(p[1] == (ICEByte)0x11); + test(p[2] == (ICEByte)0x12); + test([rso count] == 4); + test([[rso objectAtIndex:0] length] / sizeof(ICEByte) == 3); + p = [[rso objectAtIndex:0] bytes]; + test(p[0] == (ICEByte)0x01); + test(p[1] == (ICEByte)0x11); + test(p[2] == (ICEByte)0x12); + test([[rso objectAtIndex:1] length] / sizeof(ICEByte) == 1); + p = [[rso objectAtIndex:1] bytes]; + test(p[0] == (ICEByte)0xff); + test([[rso objectAtIndex:2] length] / sizeof(ICEByte) == 1); + p = [[rso objectAtIndex:2] bytes]; + test(p[0] == (ICEByte)0x0e); + test([[rso objectAtIndex:3] length] / sizeof(ICEByte) == 2); + p = [[rso objectAtIndex:3] bytes]; + test(p[0] == (ICEByte)0xf2); + test(p[1] == (ICEByte)0xf1); + } + + { + TestOperationsMutableFloatSS *fsi = [TestOperationsMutableFloatSS array]; + TestOperationsMutableDoubleSS *dsi = [TestOperationsMutableDoubleSS array]; + + ICEFloat f; + TestOperationsMutableFloatS *ftmp; + + ftmp = [TestOperationsMutableFloatS data]; + f = 3.14f; + [ftmp appendBytes:&f length:sizeof(f)]; + [fsi addObject:ftmp]; + ftmp = [TestOperationsMutableFloatS data]; + f = 1.11f; + [ftmp appendBytes:&f length:sizeof(f)]; + [fsi addObject:ftmp]; + ftmp = [TestOperationsMutableFloatS data]; + [fsi addObject:ftmp]; + + ICEDouble d; + TestOperationsMutableDoubleS *dtmp; + + dtmp = [TestOperationsMutableDoubleS data]; + d = 1.1E10; + [dtmp appendBytes:&d length:sizeof(d)]; + d = 1.2E10; + [dtmp appendBytes:&d length:sizeof(d)]; + d = 1.3E10; + [dtmp appendBytes:&d length:sizeof(d)]; + [dsi addObject:dtmp]; + + TestOperationsMutableFloatSS *fso; + TestOperationsMutableDoubleSS *dso; + TestOperationsDoubleSS *rso; + + rso = [p opFloatDoubleSS:fsi p2:dsi p3:&fso p4:&dso]; + + const ICEFloat *fp; + const ICEDouble *dp; + + test([fso count] == 3); + test([[fso objectAtIndex:0] length] / sizeof(ICEFloat) == 1); + fp = [[fso objectAtIndex:0] bytes]; + test(fp[0] == 3.14f); + test([[fso objectAtIndex:1] length] / sizeof(ICEFloat) == 1); + fp = [[fso objectAtIndex:1] bytes]; + test(fp[0] == 1.11f); + test([[fso objectAtIndex:2] length] / sizeof(ICEFloat) == 0); + test([dso count] == 1); + test([[dso objectAtIndex:0] length] / sizeof(ICEDouble) == 3); + dp = [[dso objectAtIndex:0] bytes]; + test(dp[0] == 1.1E10); + test(dp[1] == 1.2E10); + test(dp[2] == 1.3E10); + test([rso count] == 2); + test([[rso objectAtIndex:0] length] / sizeof(ICEDouble) == 3); + dp = [[rso objectAtIndex:0] bytes]; + test(dp[0] == 1.1E10); + test(dp[1] == 1.2E10); + test(dp[2] == 1.3E10); + test([[rso objectAtIndex:1] length] / sizeof(ICEDouble) == 3); + dp = [[rso objectAtIndex:1] bytes]; + test(dp[0] == 1.1E10); + test(dp[1] == 1.2E10); + test(dp[2] == 1.3E10); + } + + { + TestOperationsMutableStringSS * ssi1 = [TestOperationsMutableStringSS array]; + TestOperationsMutableStringSS * ssi2 = [TestOperationsMutableStringSS array]; + + TestOperationsMutableStringS *tmp; + + tmp = [TestOperationsMutableStringS array]; + [tmp addObject:@"abc"]; + [ssi1 addObject:tmp]; + tmp = [TestOperationsMutableStringS array]; + [tmp addObject:@"de"]; + [tmp addObject:@"fghi"]; + [ssi1 addObject:tmp]; + + [ssi2 addObject:[TestOperationsStringS array]]; + [ssi2 addObject:[TestOperationsStringS array]]; + tmp = [TestOperationsMutableStringS array]; + [tmp addObject:@"xyz"]; + [ssi2 addObject:tmp]; + + TestOperationsMutableStringSS *sso; + TestOperationsStringSS *rso; + + rso = [p opStringSS:ssi1 p2:ssi2 p3:&sso]; + + test([sso count] == 5); + test([[sso objectAtIndex:0] count] == 1); + test([[[sso objectAtIndex:0] objectAtIndex:0] isEqualToString:@"abc"]); + test([[sso objectAtIndex:1] count] == 2); + test([[[sso objectAtIndex:1] objectAtIndex:0] isEqualToString:@"de"]); + test([[[sso objectAtIndex:1] objectAtIndex:1] isEqualToString:@"fghi"]); + test([[sso objectAtIndex:2] count] == 0); + test([[sso objectAtIndex:3] count] == 0); + test([[sso objectAtIndex:4] count] == 1); + test([[[sso objectAtIndex:4] objectAtIndex:0] isEqualToString:@"xyz"]); + test([rso count] == 3); + test([[rso objectAtIndex:0] count] == 1); + test([[[rso objectAtIndex:0] objectAtIndex:0] isEqualToString:@"xyz"]); + test([[rso objectAtIndex:1] count] == 0); + test([[rso objectAtIndex:2] count] == 0); + } + + { + TestOperationsMutableStringSSS *sssi1 = [TestOperationsMutableStringSSS array]; + TestOperationsMutableStringSSS *sssi2 = [TestOperationsMutableStringSSS array]; + + TestOperationsMutableStringSS *tmpss; + TestOperationsMutableStringS *tmps; + + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@"abc"]; + [tmps addObject:@"de"]; + tmpss = [TestOperationsMutableStringSS array]; + [tmpss addObject:tmps]; + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@"xyz"]; + [tmpss addObject:tmps]; + [sssi1 addObject:tmpss]; + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@"hello"]; + tmpss = [TestOperationsMutableStringSS array]; + [tmpss addObject:tmps]; + [sssi1 addObject:tmpss]; + + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@""]; + [tmps addObject:@""]; + tmpss = [TestOperationsMutableStringSS array]; + [tmpss addObject:tmps]; + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@"abcd"]; + [tmpss addObject:tmps]; + [sssi2 addObject:tmpss]; + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@""]; + tmpss = [TestOperationsMutableStringSS array]; + [tmpss addObject:tmps]; + [sssi2 addObject:tmpss]; + tmpss = [TestOperationsMutableStringSS array]; + [sssi2 addObject:tmpss]; + + TestOperationsMutableStringSSS *ssso; + TestOperationsStringSSS *rsso; + + rsso = [p opStringSSS:sssi1 p2:sssi2 p3:&ssso]; + + test([ssso count] == 5); + test([[ssso objectAtIndex:0] count] == 2); + test([[[ssso objectAtIndex:0] objectAtIndex:0] count] == 2); + test([[[ssso objectAtIndex:0] objectAtIndex:1] count] == 1); + test([[ssso objectAtIndex:1] count] == 1); + test([[[ssso objectAtIndex:1] objectAtIndex:0] count] == 1); + test([[ssso objectAtIndex:2] count] == 2); + test([[[ssso objectAtIndex:2] objectAtIndex:0] count] == 2); + test([[[ssso objectAtIndex:2] objectAtIndex:1] count] == 1); + test([[ssso objectAtIndex:3] count] == 1); + test([[[ssso objectAtIndex:3] objectAtIndex:0] count] == 1); + test([[ssso objectAtIndex:4] count] == 0); + test([[[[ssso objectAtIndex:0] objectAtIndex:0] objectAtIndex:0] isEqualToString:@"abc"]); + test([[[[ssso objectAtIndex:0] objectAtIndex:0] objectAtIndex:1] isEqualToString:@"de"]); + test([[[[ssso objectAtIndex:0] objectAtIndex:1] objectAtIndex:0] isEqualToString:@"xyz"]); + test([[[[ssso objectAtIndex:1] objectAtIndex:0] objectAtIndex:0] isEqualToString:@"hello"]); + test([[[[ssso objectAtIndex:2] objectAtIndex:0] objectAtIndex:0] isEqualToString:@""]); + test([[[[ssso objectAtIndex:2] objectAtIndex:0] objectAtIndex:1] isEqualToString:@""]); + test([[[[ssso objectAtIndex:2] objectAtIndex:1] objectAtIndex:0] isEqualToString:@"abcd"]); + test([[[[ssso objectAtIndex:3] objectAtIndex:0] objectAtIndex:0] isEqualToString:@""]); + + test([rsso count] == 3); + test([[rsso objectAtIndex:0] count] == 0); + test([[rsso objectAtIndex:1] count] == 1); + test([[[rsso objectAtIndex:1] objectAtIndex:0] count] == 1); + test([[rsso objectAtIndex:2] count] == 2); + test([[[rsso objectAtIndex:2] objectAtIndex:0] count] == 2); + test([[[rsso objectAtIndex:2] objectAtIndex:1] count] == 1); + test([[[[rsso objectAtIndex:1] objectAtIndex:0] objectAtIndex:0] isEqualToString:@""]); + test([[[[rsso objectAtIndex:2] objectAtIndex:0] objectAtIndex:0] isEqualToString:@""]); + test([[[[rsso objectAtIndex:2] objectAtIndex:0] objectAtIndex:1] isEqualToString:@""]); + test([[[[rsso objectAtIndex:2] objectAtIndex:1] objectAtIndex:0] isEqualToString:@"abcd"]); + } + + { + TestOperationsMutableByteBoolD *di1 = [TestOperationsMutableByteBoolD dictionary]; + [di1 setObject:[NSNumber numberWithBool:YES] forKey:[NSNumber numberWithUnsignedChar:10]]; + [di1 setObject:[NSNumber numberWithBool:NO] forKey:[NSNumber numberWithUnsignedChar:100]]; + TestOperationsMutableByteBoolD *di2 = [TestOperationsMutableByteBoolD dictionary]; + [di2 setObject:[NSNumber numberWithBool:YES] forKey:[NSNumber numberWithUnsignedChar:10]]; + [di2 setObject:[NSNumber numberWithBool:NO] forKey:[NSNumber numberWithUnsignedChar:11]]; + [di2 setObject:[NSNumber numberWithBool:TRUE] forKey:[NSNumber numberWithUnsignedChar:101]]; + + TestOperationsMutableByteBoolD *_do; + TestOperationsMutableByteBoolD *ro = [p opByteBoolD:di1 p2:di2 p3:&_do]; + + test([_do isEqualToDictionary:di1]); + test([ro count] == 4); + test([[ro objectForKey:[NSNumber numberWithUnsignedChar:10]] boolValue] == YES); + test([[ro objectForKey:[NSNumber numberWithUnsignedChar:11]] boolValue] == NO); + test([[ro objectForKey:[NSNumber numberWithUnsignedChar:100]] boolValue] == NO); + test([[ro objectForKey:[NSNumber numberWithUnsignedChar:101]] boolValue] == YES); + } + + { + TestOperationsMutableShortIntD *di1 = [TestOperationsMutableShortIntD dictionary]; + [di1 setObject:[NSNumber numberWithInt:-1] forKey:[NSNumber numberWithShort:110]]; + [di1 setObject:[NSNumber numberWithInt:123123] forKey:[NSNumber numberWithShort:1100]]; + TestOperationsMutableShortIntD *di2 = [TestOperationsMutableShortIntD dictionary]; + [di2 setObject:[NSNumber numberWithInt:-1] forKey:[NSNumber numberWithShort:110]]; + [di2 setObject:[NSNumber numberWithInt:-100] forKey:[NSNumber numberWithShort:111]]; + [di2 setObject:[NSNumber numberWithInt:0] forKey:[NSNumber numberWithShort:1101]]; + + TestOperationsMutableShortIntD *_do; + TestOperationsMutableShortIntD *ro = [p opShortIntD:di1 p2:di2 p3:&_do]; + + test([_do isEqualToDictionary:di1]); + test([ro count] == 4); + test([[ro objectForKey:[NSNumber numberWithShort:110]] intValue] == -1); + test([[ro objectForKey:[NSNumber numberWithShort:111]] intValue] == -100); + test([[ro objectForKey:[NSNumber numberWithShort:1100]] intValue] == 123123); + test([[ro objectForKey:[NSNumber numberWithShort:1101]] intValue] == 0); + } + + { + TestOperationsMutableLongFloatD *di1 = [TestOperationsMutableLongFloatD dictionary]; + [di1 setObject:[NSNumber numberWithFloat:-1.1f] forKey:[NSNumber numberWithLong:999999110]]; + [di1 setObject:[NSNumber numberWithFloat:123123.2f] forKey:[NSNumber numberWithLong:999999111]]; + TestOperationsMutableLongFloatD *di2 = [TestOperationsMutableLongFloatD dictionary]; + [di2 setObject:[NSNumber numberWithFloat:-1.1f] forKey:[NSNumber numberWithLong:999999110]]; + [di2 setObject:[NSNumber numberWithFloat:-100.4f] forKey:[NSNumber numberWithLong:999999120]]; + [di2 setObject:[NSNumber numberWithFloat:0.5f] forKey:[NSNumber numberWithLong:999999130]]; + + TestOperationsMutableLongFloatD *_do; + TestOperationsMutableLongFloatD *ro = [p opLongFloatD:di1 p2:di2 p3:&_do]; + + test([_do isEqualToDictionary:di1]); + test([ro count] == 4); + test((ICEFloat)[[ro objectForKey:[NSNumber numberWithLong:999999110]] floatValue] == -1.1f); + test((ICEFloat)[[ro objectForKey:[NSNumber numberWithLong:999999120]] floatValue] == -100.4f); + test((ICEFloat)[[ro objectForKey:[NSNumber numberWithLong:999999111]] floatValue] == 123123.2f); + test((ICEFloat)[[ro objectForKey:[NSNumber numberWithLong:999999130]] floatValue] == 0.5f); + } + + { + TestOperationsMutableStringStringD *di1 = [TestOperationsMutableStringStringD dictionary]; + [di1 setObject:@"abc -1.1" forKey:@"foo"]; + [di1 setObject:@"abc 123123.2" forKey:@"bar"]; + TestOperationsMutableStringStringD *di2 = [TestOperationsMutableStringStringD dictionary]; + [di2 setObject:@"abc -1.1" forKey:@"foo"]; + [di2 setObject:@"abc -100.4" forKey:@"FOO"]; + [di2 setObject:@"abc 0.5" forKey:@"BAR"]; + + TestOperationsMutableStringStringD *_do; + TestOperationsMutableStringStringD *ro = [p opStringStringD:di1 p2:di2 p3:&_do]; + + test([_do isEqualToDictionary:di1]); + test([ro count] == 4); + test([[ro objectForKey:@"foo"] isEqualToString:@"abc -1.1"]); + test([[ro objectForKey:@"FOO"] isEqualToString:@"abc -100.4"]); + test([[ro objectForKey:@"bar"] isEqualToString:@"abc 123123.2"]); + test([[ro objectForKey:@"BAR"] isEqualToString:@"abc 0.5"]); + } + + { + TestOperationsMutableStringMyEnumD *di1 = [TestOperationsMutableStringMyEnumD dictionary]; + [di1 setObject:[NSNumber numberWithInt:TestOperationsenum1] forKey:@"abc"]; + [di1 setObject:[NSNumber numberWithInt:TestOperationsenum2] forKey:@""]; + TestOperationsMutableStringMyEnumD *di2 = [TestOperationsMutableStringMyEnumD dictionary]; + [di2 setObject:[NSNumber numberWithInt:TestOperationsenum1] forKey:@"abc"]; + [di2 setObject:[NSNumber numberWithInt:TestOperationsenum3] forKey:@"querty"]; + [di2 setObject:[NSNumber numberWithInt:TestOperationsenum2] forKey:@"Hello!!"]; + + TestOperationsMutableStringMyEnumD *_do; + TestOperationsMutableStringMyEnumD *ro = [p opStringMyEnumD:di1 p2:di2 p3:&_do]; + + test([_do isEqualToDictionary:di1]); + test([ro count] == 4); + test([[ro objectForKey:@"abc"] intValue] == TestOperationsenum1); + test([[ro objectForKey:@"querty"] intValue] == TestOperationsenum3); + test([[ro objectForKey:@""] intValue] == TestOperationsenum2); + test([[ro objectForKey:@"Hello!!"] intValue] == TestOperationsenum2); + } + + { + TestOperationsMutableMyEnumStringD *di1 = [TestOperationsMutableMyEnumStringD dictionary]; + [di1 setObject:@"abc" forKey:@(TestOperationsenum1)]; + TestOperationsMutableMyEnumStringD *di2 = [TestOperationsMutableMyEnumStringD dictionary]; + [di2 setObject:@"Hello!!" forKey:@(TestOperationsenum2)]; + [di2 setObject:@"querty" forKey:@(TestOperationsenum3)]; + + TestOperationsMutableMyEnumStringD *_do; + TestOperationsMutableMyEnumStringD *ro = [p opMyEnumStringD:di1 p2:di2 p3:&_do]; + + test([_do isEqualToDictionary:di1]); + test([ro count] == 3); + test([[ro objectForKey:@(TestOperationsenum1)] isEqualToString:@"abc"]); + test([[ro objectForKey:@(TestOperationsenum3)] isEqualToString:@"querty"]); + test([[ro objectForKey:@(TestOperationsenum2)] isEqualToString:@"Hello!!"]); + } + + { + TestOperationsMyStruct* s11 = [TestOperationsMyStruct myStruct:1 j:1]; + TestOperationsMyStruct* s12 = [TestOperationsMyStruct myStruct:1 j:2]; + TestOperationsMutableMyStructMyEnumD* di1 = [TestOperationsMutableMyStructMyEnumD dictionary]; + [di1 setObject:@(TestOperationsenum1) forKey:s11]; + [di1 setObject:@(TestOperationsenum2) forKey:s12]; + + TestOperationsMyStruct* s22 = [TestOperationsMyStruct myStruct:2 j:2]; + TestOperationsMyStruct* s23 = [TestOperationsMyStruct myStruct:2 j:3]; + TestOperationsMutableMyStructMyEnumD* di2 = [TestOperationsMutableMyStructMyEnumD dictionary]; + [di2 setObject:@(TestOperationsenum1) forKey:s11]; + [di2 setObject:@(TestOperationsenum3) forKey:s22]; + [di2 setObject:@(TestOperationsenum2) forKey:s23]; + + TestOperationsMutableMyStructMyEnumD* _do; + TestOperationsMyStructMyEnumD* ro = [p opMyStructMyEnumD:di1 p2:di2 p3:&_do]; + + test([_do isEqual:di1]); + test([ro count] == 4); + test([[ro objectForKey:s11] isEqual:@(TestOperationsenum1)]); + test([[ro objectForKey:s12] isEqual:@(TestOperationsenum2)]); + test([[ro objectForKey:s22] isEqual:@(TestOperationsenum3)]); + test([[ro objectForKey:s23] isEqual:@(TestOperationsenum2)]); + } + + { + const int lengths[] = { 0, 1, 2, 126, 127, 128, 129, 253, 254, 255, 256, 257, 1000 }; + + int l; + for(l = 0; l != sizeof(lengths) / sizeof(*lengths); ++l) + { + TestOperationsMutableIntS *s = [TestOperationsMutableIntS dataWithLength:(lengths[l] * sizeof(ICEInt))]; + ICEInt *ip = (ICEInt *)[s bytes]; + int i; + for(i = 0; i < lengths[l]; ++i) + { + *ip++ = i; + } + TestOperationsIntS *r = [p opIntS:s]; + test([r length] == lengths[l] * sizeof(ICEInt)); + const ICEInt *rp = [r bytes]; + int j; + for(j = 0; j < [r length] / sizeof(ICEInt); ++j) + { + test(rp[j] == -j); + } + } + } + + { + ICEMutableContext *ctx = [ICEMutableContext dictionary]; + [ctx setObject:@"ONE" forKey:@"one"]; + [ctx setObject:@"TWO" forKey:@"two"]; + [ctx setObject:@"THREE" forKey:@"three"]; + { + ICEContext *r = [p opContext]; + test([[p ice_getContext] count] == 0); + test(![r isEqual:ctx]); + } + { + ICEContext *r = [p opContext:ctx]; + test([[p ice_getContext] count] == 0); + test([r isEqual:ctx]); + } + { + id<TestOperationsMyClassPrx> p2 = [TestOperationsMyClassPrx checkedCast:[p ice_context:ctx]]; + test([[p2 ice_getContext] isEqual:ctx]); + ICEContext *r = [p2 opContext]; + test([r isEqual:ctx]); + r = [p2 opContext:ctx]; + test([r isEqual:ctx]); + } + } + + + { + // + // TestOperations implicit context propagation + // + NSString *impls[] = { @"Shared", @"PerThread" }; + int i; + for(i = 0; i < 2; i++) + { + ICEInitializationData *initData = [ICEInitializationData initializationData]; + initData.properties = [[communicator getProperties] clone]; + [initData.properties setProperty:@"Ice.ImplicitContext" value:impls[i]]; + + id<ICECommunicator> ic = [ICEUtil createCommunicator:initData]; + + ICEMutableContext *ctx = [ICEMutableContext dictionary]; + [ctx setObject:@"ONE" forKey:@"one" ]; + [ctx setObject:@"TWO" forKey:@"two" ]; + [ctx setObject:@"THREE" forKey:@"three"]; + + id<TestOperationsMyClassPrx> p = [TestOperationsMyClassPrx uncheckedCast:[ic stringToProxy:@"test:default -p 12010"]]; + + [[ic getImplicitContext] setContext:ctx]; + test([[[ic getImplicitContext] getContext] isEqual:ctx]); + test([[p opContext] isEqual:ctx]); + + test([[ic getImplicitContext] get:@"zero"] == nil); + [[ic getImplicitContext] put:@"zero" value:@"ZERO"]; + test([[[ic getImplicitContext] get:@"zero"] isEqualToString:@"ZERO"]); + + ctx = [[ic getImplicitContext] getContext]; + test([[p opContext] isEqual:ctx]); + + ICEMutableContext *prxContext = [ICEMutableContext dictionary]; + [prxContext setObject:@"UN" forKey:@"one"]; + [prxContext setObject:@"QUATRE" forKey:@"four"]; + + ICEMutableContext *combined = [ICEMutableContext dictionaryWithDictionary:ctx]; + [combined addEntriesFromDictionary:prxContext]; + + p = [TestOperationsMyClassPrx uncheckedCast:[p ice_context:prxContext]]; + + [[ic getImplicitContext] setContext:[ICEContext dictionary]]; + test([[p opContext] isEqualToDictionary:prxContext]); + + [[ic getImplicitContext] setContext:ctx]; + test([[p opContext] isEqualToDictionary:combined]); + + test([[[ic getImplicitContext] get:@"one"] isEqualToString:@"ONE"]); + [[ic getImplicitContext] remove:@"one"]; + + if([impls[i] isEqualToString:@"PerThread"]) + { + PerThreadContextInvokeThread* thread = [PerThreadContextInvokeThread create:[p ice_context:[ICEMutableContext dictionary]]]; + [thread start]; + [thread join]; + } + + [[ic getImplicitContext] setContext:[ICEContext dictionary]]; + [ic destroy]; + } + } + + { + ICEDouble d = 1278312346.0 / 13.0; + TestOperationsMutableDoubleS *ds = [TestOperationsMutableDoubleS dataWithLength:(5 * sizeof(ICEDouble))]; + ICEDouble *pb = (ICEDouble *)[ds bytes]; + int i = 5; + while(i-- > 0) + { + *pb++ = d; + } + [p opDoubleMarshaling:d p2:ds]; + } + + [p opIdempotent]; + + [p opNonmutating]; + + // + // TestOperationss below are for Objective-C only. They test that we do the right thing if NSNull + // is passed as part of the sequence or dictionary. + // + @try + { + { + TestOperationsStringS *s = [p getNSNullStringSeq]; + test([s count] == 2); + test([[s objectAtIndex:0] isEqualToString:@"first"]); + test([[s objectAtIndex:1] isEqualToString:@""]); + } + + { + TestOperationsAS *s = [p getNSNullASeq]; + test([s count] == 2); + test(((TestOperationsA *)[s objectAtIndex:0]).i == 99); + test([s objectAtIndex:1] == [NSNull null]); + } + + { + TestOperationsStructS *seq = [p getNSNullStructSeq]; + test([seq count] == 2); + TestOperationsStructure *s = [seq objectAtIndex:0]; + test(s.p == nil); + test(s.e == TestOperationsenum2); + test([s.s.s isEqualToString:@"Hello"]); + s = [seq objectAtIndex:1]; + test(s.p == nil); + test(s.e == TestOperationsenum1); + test([s.s.s isEqualToString:@""]); + } + + { + TestOperationsStringSS *seq = [p getNSNullStringSeqSeq]; + test([seq count] == 2); + TestOperationsStringS *s = [seq objectAtIndex:0]; + test([s count] == 1); + test([(NSString *)[s objectAtIndex:0] isEqualToString:@"first"]); + s = [seq objectAtIndex:1]; + test([s count] == 0); + } + + { + TestOperationsStringStringD *d = [p getNSNullStringStringDict]; + test([d count] == 2); + test([(NSString *)[d objectForKey:@"one"] isEqualToString:@"ONE"]); + test([(NSString *)[d objectForKey:@"two"] isEqualToString:@""]); + } + + { + @try + { + TestOperationsMutableStringStringD *d = [TestOperationsMutableStringStringD dictionary]; + [d setObject:@"bad key" forKey:[NSNull null]]; + [p putNSNullStringStringDict:d]; + test(NO); + } + @catch(ICEMarshalException *) + { + // Expected + } + } + + { + @try + { + TestOperationsMutableShortIntD *d = [TestOperationsMutableShortIntD dictionary]; + [d setObject:[NSNull null] forKey:[NSNumber numberWithInt:1]]; + [p putNSNullShortIntDict:d]; + test(NO); + } + @catch(ICEMarshalException *) + { + // Expected + } + } + + { + @try + { + TestOperationsMutableStringMyEnumD *d = [TestOperationsMutableStringMyEnumD dictionary]; + [d setObject:[NSNull null] forKey:@"key"]; + [p putNSNullStringMyEnumDict:d]; + test(NO); + } + @catch(ICEMarshalException *) + { + // Expected + } + } + } + @catch(ICEOperationNotExistException *) + { + // Client is talking to non-Objective-C server. + } +} diff --git a/objc/test/Ice/operations/TwowaysNewAMI.m b/objc/test/Ice/operations/TwowaysNewAMI.m new file mode 100644 index 00000000000..4a097985de3 --- /dev/null +++ b/objc/test/Ice/operations/TwowaysNewAMI.m @@ -0,0 +1,1186 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <OperationsTest.h> +#import <limits.h> +#import <float.h> + +#import <Foundation/Foundation.h> + +@interface TestNewAMIOperationsCallback : NSObject +{ + BOOL called; + NSCondition* cond; +} +-(BOOL) check; +-(void) called; +@end + +@implementation TestNewAMIOperationsCallback +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + cond = [[NSCondition alloc] init]; + return self; +} + ++(id) create +{ +#if defined(__clang__) && __has_feature(objc_arc) + return [[TestNewAMIOperationsCallback alloc] init]; +#else + return [[[TestNewAMIOperationsCallback alloc] init] autorelease]; +#endif +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [super dealloc]; +} +#endif + +-(BOOL) check +{ + [cond lock]; + while(!called) + { + if(![cond waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:50]]) + { + return NO; + } + } + called = NO; + [cond unlock]; + return YES; +} +-(void) called +{ + [cond lock]; + called = YES; + [cond signal]; + [cond unlock]; +} +-(void) opVoidExResponse +{ + test(NO); +} +-(void) opVoidExException:(ICEException*)ex +{ + test([ex isKindOfClass:[ICENoEndpointException class]]); + [self called]; +} +-(void) opVoidResponse +{ + [self called]; +} +-(void) opVoidException:(ICEException*)ex +{ + test(NO); +} +-(void) opByteExResponse:(ICEByte)ret p3:(ICEByte)p3 +{ + test(NO); +} +-(void) opByteExException:(ICEException*)ex +{ + test([ex isKindOfClass:[ICENoEndpointException class]]); + [self called]; +} +-(void) opByteResponse:(ICEByte)ret p3:(ICEByte)p3 +{ + [self called]; +} +-(void) opByteException:(ICEException*)ex +{ + test(NO); +} +-(void) opBoolResponse:(BOOL)r p3:(BOOL)b +{ + test(b); + test(!r); + [self called]; +} +-(void) opBoolException:(ICEException*)ex +{ + test(NO); +} +-(void) opShortIntLongResponse:(ICELong)r p4:(ICEShort)s p5:(ICEInt)i p6:(ICELong)l +{ + test(s == 10); + test(i == 11); + test(l == 12); + test(r == 12); + [self called]; +} +-(void) opShortIntLongException:(ICEException*)ex +{ + test(NO); +} +-(void) opFloatDoubleResponse:(ICEDouble)r p3:(ICEFloat)f p4:(ICEDouble)d +{ + test(f == 3.14f); + test(d == 1.1E10); + test(r == 1.1E10); + [self called]; +} +-(void) opFloatDoubleException:(ICEException*)ex +{ + test(NO); +} +-(void) opStringResponse:(NSString*)r p3:(NSString*)s +{ + test([s isEqualToString:@"world hello"]); + test([r isEqualToString:@"hello world"]); + [self called]; +} + +-(void) opStringException:(ICEException*)ex +{ + test(NO); +}; + +-(void) opMyEnumResponse:(TestOperationsMyEnum)r p2:(TestOperationsMyEnum)e +{ + test(e == TestOperationsenum2); + test(r == TestOperationsenum3); + [self called]; +} + +-(void) opMyEnumException:(ICEException*)ex +{ + test(NO); +} + +-(void) opMyClassResponse:(id<TestOperationsMyClassPrx>)r p2:(id<TestOperationsMyClassPrx>)c1 p3:(id<TestOperationsMyClassPrx>)c2 +{ + test([[c1 ice_getIdentity] isEqual:[[c1 ice_getCommunicator] stringToIdentity:@"test"]]); + test([[c2 ice_getIdentity] isEqual:[[c1 ice_getCommunicator] stringToIdentity:@"noSuchIdentity"]]); + test([[r ice_getIdentity] isEqual:[[c1 ice_getCommunicator] stringToIdentity:@"test"]]); + // We can't do the callbacks below in connection serialization mode. + if([[[c1 ice_getCommunicator] getProperties] getPropertyAsInt:@"Ice.ThreadPool.Client.Serialize"]) + { + [r opVoid]; + [c1 opVoid]; + @try + { + [c2 opVoid]; + test(NO); + } + @catch(ICEObjectNotExistException*) + { + } + } + [self called]; +} + +-(void) opMyClassException:(ICEException*)ex +{ + test(NO); +} + +-(void) opStructResponse:(TestOperationsStructure*)rso p3:(TestOperationsStructure*)so +{ + test(rso.p == nil); + test(rso.e == TestOperationsenum2); + test([rso.s.s isEqualToString:@"def"]); + test([so e] == TestOperationsenum3); + test(so.p != nil); + test([so.s.s isEqualToString:@"a new string"]); + // We can't do the callbacks below in connection serialization mode. + if([[[so.p ice_getCommunicator] getProperties] getPropertyAsInt:@"Ice.ThreadPool.Client.Serialize"]) + { + [so.p opVoid]; + } + [self called]; +} + +-(void) opStructException:(ICEException*)ex +{ + test(NO); +} + +-(void) opByteSResponse:(TestOperationsByteS*)rso p3:(TestOperationsByteS*)bso +{ + test([bso length] == 4); + ICEByte *bbso = (ICEByte *)[bso bytes]; + test(bbso[0] == 0x22); + test(bbso[1] == 0x12); + test(bbso[2] == 0x11); + test(bbso[3] == 0x01); + test([rso length] == 8); + ICEByte *brso = (ICEByte *)[rso bytes]; + test(brso[0] == 0x01); + test(brso[1] == 0x11); + test(brso[2] == 0x12); + test(brso[3] == 0x22); + test(brso[4] == 0xf1); + test(brso[5] == 0xf2); + test(brso[6] == 0xf3); + test(brso[7] == 0xf4); + [self called]; +} + +-(void) opByteSException:(ICEException*)ex +{ + test(NO); +} + +-(void) opBoolSResponse:(TestOperationsBoolS*)rso p3:(TestOperationsBoolS*)bso +{ + test([bso length] == 4 * sizeof(BOOL)); + BOOL *bbso = (BOOL *)[bso bytes]; + test(bbso[0]); + test(bbso[1]); + test(!bbso[2]); + test(!bbso[3]); + test([rso length] == 3 * sizeof(BOOL)); + BOOL *brso = (BOOL *)[rso bytes]; + test(!brso[0]); + test(brso[1]); + test(brso[2]); + [self called]; +} + +-(void) opBoolSException:(ICEException*)ex +{ + test(NO); +} + +-(void) opShortIntLongSResponse:(TestOperationsLongS*)rso p4:(TestOperationsShortS*)sso p5:(TestOperationsIntS*)iso p6:(TestOperationsLongS*)lso +{ + test([sso length] == 3 * sizeof(ICEShort)); + ICEShort *bsso = (ICEShort *)[sso bytes]; + test(bsso[0] == 1); + test(bsso[1] == 2); + test(bsso[2] == 3); + test([iso length] == 4 * sizeof(ICEInt)); + ICEInt *biso = (ICEInt *)[iso bytes]; + test(biso[0] == 8); + test(biso[1] == 7); + test(biso[2] == 6); + test(biso[3] == 5); + test([lso length] == 6 * sizeof(ICELong)); + ICELong *blso = (ICELong *)[lso bytes]; + test(blso[0] == 10); + test(blso[1] == 30); + test(blso[2] == 20); + test(blso[3] == 10); + test(blso[4] == 30); + test(blso[5] == 20); + test([rso length] == 3 * sizeof(ICELong)); + ICELong *brso = (ICELong *)[rso bytes]; + test(brso[0] == 10); + test(brso[1] == 30); + test(brso[2] == 20); + [self called]; +} + +-(void) opShortIntLongSException:(ICEException*)ex +{ + test(NO); +} + +-(void) opFloatDoubleSResponse:(TestOperationsDoubleS*)rso p3:(TestOperationsFloatS*)fso p4:(TestOperationsDoubleS*)dso +{ + test([fso length] == 2 * sizeof(ICEFloat)); + ICEFloat *bfso = (ICEFloat *)[fso bytes]; + test(bfso[0] == 3.14f); + test(bfso[1] == 1.11f); + test([dso length] == 3 * sizeof(ICEDouble)); + ICEDouble *bdso = (ICEDouble *)[dso bytes]; + test(bdso[0] == 1.3E10); + test(bdso[1] == 1.2E10); + test(bdso[2] == 1.1E10); + test([rso length] == 5 * sizeof(ICEDouble)); + ICEDouble *brso = (ICEDouble *)[rso bytes]; + test(brso[0] == 1.1E10); + test(brso[1] == 1.2E10); + test(brso[2] == 1.3E10); + test((ICEFloat)brso[3] == 3.14f); + test((ICEFloat)brso[4] == 1.11f); + [self called]; +} + +-(void) opFloatDoubleSException:(ICEException*)ex +{ + test(NO); +} + +-(void) opStringSResponse:(TestOperationsStringS*)rso p3:(TestOperationsStringS*)sso +{ + test([sso count] == 4); + test([[sso objectAtIndex:0] isEqualToString:@"abc"]); + test([[sso objectAtIndex:1] isEqualToString:@"de"]); + test([[sso objectAtIndex:2] isEqualToString:@"fghi"]); + test([[sso objectAtIndex:3] isEqualToString:@"xyz"]); + test([rso count] == 3); + test([[rso objectAtIndex:0] isEqualToString:@"fghi"]); + test([[rso objectAtIndex:1] isEqualToString:@"de"]); + test([[rso objectAtIndex:2] isEqualToString:@"abc"]); + [self called]; +} + +-(void) opStringSException:(ICEException*)ex +{ + test(NO); +} + +-(void) opByteSSResponse:(TestOperationsByteSS*)rso p3:(TestOperationsByteSS*)bso +{ + const ICEByte *p; + test([bso count] == 2); + test([[bso objectAtIndex:0] length] / sizeof(ICEByte) == 1); + p = [[bso objectAtIndex:0] bytes]; + test(p[0] == (ICEByte)0x0ff); + test([[bso objectAtIndex:1] length] / sizeof(ICEByte) == 3); + p = [[bso objectAtIndex:1] bytes]; + test(p[0] == (ICEByte)0x01); + test(p[1] == (ICEByte)0x11); + test(p[2] == (ICEByte)0x12); + test([rso count] == 4); + test([[rso objectAtIndex:0] length] / sizeof(ICEByte) == 3); + p = [[rso objectAtIndex:0] bytes]; + test(p[0] == (ICEByte)0x01); + test(p[1] == (ICEByte)0x11); + test(p[2] == (ICEByte)0x12); + test([[rso objectAtIndex:1] length] / sizeof(ICEByte) == 1); + p = [[rso objectAtIndex:1] bytes]; + test(p[0] == (ICEByte)0xff); + test([[rso objectAtIndex:2] length] / sizeof(ICEByte) == 1); + p = [[rso objectAtIndex:2] bytes]; + test(p[0] == (ICEByte)0x0e); + test([[rso objectAtIndex:3] length] / sizeof(ICEByte) == 2); + p = [[rso objectAtIndex:3] bytes]; + test(p[0] == (ICEByte)0xf2); + test(p[1] == (ICEByte)0xf1); + [self called]; +} + +-(void) opByteSSException:(ICEException*)ex +{ + test(NO); +} + +-(void) opBoolSSResponse:(TestOperationsBoolSS*)sso p3:(TestOperationsBoolSS*)bso +{ + [self called]; +} + +-(void) opBoolSSException:(ICEException*)ex +{ + test(NO); +} + +-(void) opShortIntLongSSResponse:(TestOperationsLongSS*)a p4:(TestOperationsShortSS*)p4 p5:(TestOperationsIntSS*)p5 p6:(TestOperationsLongSS*)p6 +{ + [self called]; +} + +-(void) opShortIntLongSSException:(ICEException*)ex +{ + test(NO); +} + +-(void) opFloatDoubleSSResponse:(TestOperationsDoubleSS*)rso p3:(TestOperationsFloatSS*)fso p4:(TestOperationsDoubleSS*)dso +{ + const ICEFloat *fp; + const ICEDouble *dp; + + test([fso count] == 3); + test([[fso objectAtIndex:0] length] / sizeof(ICEFloat) == 1); + fp = [[fso objectAtIndex:0] bytes]; + test(fp[0] == 3.14f); + test([[fso objectAtIndex:1] length] / sizeof(ICEFloat) == 1); + fp = [[fso objectAtIndex:1] bytes]; + test(fp[0] == 1.11f); + test([[fso objectAtIndex:2] length] / sizeof(ICEFloat) == 0); + test([dso count] == 1); + test([[dso objectAtIndex:0] length] / sizeof(ICEDouble) == 3); + dp = [[dso objectAtIndex:0] bytes]; + test(dp[0] == 1.1E10); + test(dp[1] == 1.2E10); + test(dp[2] == 1.3E10); + test([rso count] == 2); + test([[rso objectAtIndex:0] length] / sizeof(ICEDouble) == 3); + dp = [[rso objectAtIndex:0] bytes]; + test(dp[0] == 1.1E10); + test(dp[1] == 1.2E10); + test(dp[2] == 1.3E10); + test([[rso objectAtIndex:1] length] / sizeof(ICEDouble) == 3); + dp = [[rso objectAtIndex:1] bytes]; + test(dp[0] == 1.1E10); + test(dp[1] == 1.2E10); + test(dp[2] == 1.3E10); + [self called]; +} + +-(void) opFloatDoubleSSException:(ICEException*)ex +{ + test(NO); +} + +-(void) opStringSSResponse:(TestOperationsStringSS*)rso p3:(TestOperationsStringSS*)sso +{ + test([sso count] == 5); + test([[sso objectAtIndex:0] count] == 1); + test([[[sso objectAtIndex:0] objectAtIndex:0] isEqualToString:@"abc"]); + test([[sso objectAtIndex:1] count] == 2); + test([[[sso objectAtIndex:1] objectAtIndex:0] isEqualToString:@"de"]); + test([[[sso objectAtIndex:1] objectAtIndex:1] isEqualToString:@"fghi"]); + test([[sso objectAtIndex:2] count] == 0); + test([[sso objectAtIndex:3] count] == 0); + test([[sso objectAtIndex:4] count] == 1); + test([[[sso objectAtIndex:4] objectAtIndex:0] isEqualToString:@"xyz"]); + test([rso count] == 3); + test([[rso objectAtIndex:0] count] == 1); + test([[[rso objectAtIndex:0] objectAtIndex:0] isEqualToString:@"xyz"]); + test([[rso objectAtIndex:1] count] == 0); + test([[rso objectAtIndex:2] count] == 0); + [self called]; +} + +-(void) opStringSSException:(ICEException*)ex +{ + test(NO); +} + +-(void) opStringSSSResponse:(TestOperationsStringSS*)rsso p3:(TestOperationsStringSS*)ssso +{ + test([ssso count] == 5); + test([[ssso objectAtIndex:0] count] == 2); + test([[[ssso objectAtIndex:0] objectAtIndex:0] count] == 2); + test([[[ssso objectAtIndex:0] objectAtIndex:1] count] == 1); + test([[ssso objectAtIndex:1] count] == 1); + test([[[ssso objectAtIndex:1] objectAtIndex:0] count] == 1); + test([[ssso objectAtIndex:2] count] == 2); + test([[[ssso objectAtIndex:2] objectAtIndex:0] count] == 2); + test([[[ssso objectAtIndex:2] objectAtIndex:1] count] == 1); + test([[ssso objectAtIndex:3] count] == 1); + test([[[ssso objectAtIndex:3] objectAtIndex:0] count] == 1); + test([[ssso objectAtIndex:4] count] == 0); + test([[[[ssso objectAtIndex:0] objectAtIndex:0] objectAtIndex:0] isEqualToString:@"abc"]); + test([[[[ssso objectAtIndex:0] objectAtIndex:0] objectAtIndex:1] isEqualToString:@"de"]); + test([[[[ssso objectAtIndex:0] objectAtIndex:1] objectAtIndex:0] isEqualToString:@"xyz"]); + test([[[[ssso objectAtIndex:1] objectAtIndex:0] objectAtIndex:0] isEqualToString:@"hello"]); + test([[[[ssso objectAtIndex:2] objectAtIndex:0] objectAtIndex:0] isEqualToString:@""]); + test([[[[ssso objectAtIndex:2] objectAtIndex:0] objectAtIndex:1] isEqualToString:@""]); + test([[[[ssso objectAtIndex:2] objectAtIndex:1] objectAtIndex:0] isEqualToString:@"abcd"]); + test([[[[ssso objectAtIndex:3] objectAtIndex:0] objectAtIndex:0] isEqualToString:@""]); + + test([rsso count] == 3); + test([[rsso objectAtIndex:0] count] == 0); + test([[rsso objectAtIndex:1] count] == 1); + test([[[rsso objectAtIndex:1] objectAtIndex:0] count] == 1); + test([[rsso objectAtIndex:2] count] == 2); + test([[[rsso objectAtIndex:2] objectAtIndex:0] count] == 2); + test([[[rsso objectAtIndex:2] objectAtIndex:1] count] == 1); + test([[[[rsso objectAtIndex:1] objectAtIndex:0] objectAtIndex:0] isEqualToString:@""]); + test([[[[rsso objectAtIndex:2] objectAtIndex:0] objectAtIndex:0] isEqualToString:@""]); + test([[[[rsso objectAtIndex:2] objectAtIndex:0] objectAtIndex:1] isEqualToString:@""]); + test([[[[rsso objectAtIndex:2] objectAtIndex:1] objectAtIndex:0] isEqualToString:@"abcd"]); + [self called]; +} +-(void) opStringSSSException:(ICEException*)ex +{ + test(NO); +} +-(void) opByteBoolDResponse:(TestOperationsMutableByteBoolD*)ro p3:(TestOperationsMutableByteBoolD*)_do +{ + test([_do count] == 2); + test([[_do objectForKey:[NSNumber numberWithUnsignedChar:10]] boolValue] == YES); + test([[_do objectForKey:[NSNumber numberWithUnsignedChar:100]] boolValue] == NO); + test([ro count] == 4); + test([[ro objectForKey:[NSNumber numberWithUnsignedChar:10]] boolValue] == YES); + test([[ro objectForKey:[NSNumber numberWithUnsignedChar:11]] boolValue] == NO); + test([[ro objectForKey:[NSNumber numberWithUnsignedChar:100]] boolValue] == NO); + test([[ro objectForKey:[NSNumber numberWithUnsignedChar:101]] boolValue] == YES); + [self called]; +} +-(void) opByteBoolDException:(ICEException*)ex +{ + test(NO); +} +-(void) opShortIntDResponse:(TestOperationsShortIntD*)ro p3:(TestOperationsShortIntD*)_do +{ + test([_do count] == 2); + test([[_do objectForKey:[NSNumber numberWithShort:110]] intValue] == -1); + test([[_do objectForKey:[NSNumber numberWithShort:1100]] intValue] == 123123); + test([ro count] == 4); + test([[ro objectForKey:[NSNumber numberWithShort:110]] intValue] == -1); + test([[ro objectForKey:[NSNumber numberWithShort:111]] intValue] == -100); + test([[ro objectForKey:[NSNumber numberWithShort:1100]] intValue] == 123123); + test([[ro objectForKey:[NSNumber numberWithShort:1101]] intValue] == 0); + [self called]; +} +-(void) opShortIntDException:(ICEException*)ex +{ + test(NO); +} +-(void) opLongFloatDResponse:(TestOperationsLongFloatD*)ro p3:(TestOperationsLongFloatD*)_do +{ + test([_do count] == 2); + test((ICEFloat)[[_do objectForKey:[NSNumber numberWithLong:999999110]] floatValue] == -1.1f); + test((ICEFloat)[[_do objectForKey:[NSNumber numberWithLong:999999111]] floatValue] == 123123.2f); + test([ro count] == 4); + test((ICEFloat)[[ro objectForKey:[NSNumber numberWithLong:999999110]] floatValue] == -1.1f); + test((ICEFloat)[[ro objectForKey:[NSNumber numberWithLong:999999120]] floatValue] == -100.4f); + test((ICEFloat)[[ro objectForKey:[NSNumber numberWithLong:999999111]] floatValue] == 123123.2f); + test((ICEFloat)[[ro objectForKey:[NSNumber numberWithLong:999999130]] floatValue] == 0.5f); + [self called]; +} +-(void) opLongFloatDException:(ICEException*)ex +{ + test(NO); +} +-(void) opStringStringDResponse:(TestOperationsStringStringD*)ro p3:(TestOperationsStringStringD*)_do +{ + test([_do count] == 2); + test([[_do objectForKey:@"foo"] isEqualToString:@"abc -1.1"]); + test([[_do objectForKey:@"bar"] isEqualToString:@"abc 123123.2"]); + test([ro count] == 4); + test([[ro objectForKey:@"foo"] isEqualToString:@"abc -1.1"]); + test([[ro objectForKey:@"FOO"] isEqualToString:@"abc -100.4"]); + test([[ro objectForKey:@"bar"] isEqualToString:@"abc 123123.2"]); + test([[ro objectForKey:@"BAR"] isEqualToString:@"abc 0.5"]); + [self called]; +} +-(void) opStringStringDException:(ICEException*)ex +{ + test(NO); +} +-(void) opStringMyEnumDResponse:(TestOperationsStringMyEnumD*)ro p3:(TestOperationsStringMyEnumD*)_do +{ + test([_do count] == 2); + test([[_do objectForKey:@"abc"] intValue] == TestOperationsenum1); + test([[_do objectForKey:@""] intValue] == TestOperationsenum2); + test([ro count] == 4); + test([[ro objectForKey:@"abc"] intValue] == TestOperationsenum1); + test([[ro objectForKey:@"querty"] intValue] == TestOperationsenum3); + test([[ro objectForKey:@""] intValue] == TestOperationsenum2); + test([[ro objectForKey:@"Hello!!"] intValue] == TestOperationsenum2); + [self called]; +} +-(void) opStringMyEnumDException:(ICEException*)ex +{ + test(NO); +} +-(void) opMyEnumStringDResponse:(TestOperationsMyEnumStringD*)ro p3:(TestOperationsMyEnumStringD*)_do +{ + test([_do count] == 1); + test([ro count] == 3); + test([[ro objectForKey:@(TestOperationsenum1)] isEqualToString:@"abc"]); + test([[ro objectForKey:@(TestOperationsenum2)] isEqualToString:@"Hello!!"]); + test([[ro objectForKey:@(TestOperationsenum3)] isEqualToString:@"querty"]); + [self called]; +} +-(void) opMyEnumStringDException:(ICEException*)ex +{ + test(NO); +} +-(void) opMyStructMyEnumDResponse:(TestOperationsMyStructMyEnumD*)ro p3:(TestOperationsMyStructMyEnumD*)_do + s11:(TestOperationsMyStruct*)s11 s12:(TestOperationsMyStruct*)s12 + s22:(TestOperationsMyStruct*)s22 s23:(TestOperationsMyStruct*)s23 +{ + test([_do count] == 2); + test([ro count] == 4); + test([[ro objectForKey:s11] isEqual:@(TestOperationsenum1)]); + test([[ro objectForKey:s12] isEqual:@(TestOperationsenum2)]); + test([[ro objectForKey:s22] isEqual:@(TestOperationsenum3)]); + test([[ro objectForKey:s23] isEqual:@(TestOperationsenum2)]); + [self called]; +} +-(void) opMyStructMyEnumDException:(ICEException*)ex +{ + test(NO); +} +-(void) opIntSResponse:(TestOperationsIntS*)r +{ + const ICEInt *rp = [r bytes]; + int j; + for(j = 0; j < [r length] / sizeof(ICEInt); ++j) + { + test(rp[j] == -j); + } + [self called]; +} +-(void) opIntSException:(ICEException*)ex +{ + test(NO); +} +-(void) opEmptyContextResponse:(ICEContext*)ctx +{ + test([ctx count] == 0); + [self called]; +} +-(void) opNonEmptyContextResponse:(ICEContext*)ctx +{ + test([ctx count] == 3); + test([[ctx objectForKey:@"one"] isEqualToString:@"ONE"]); + test([[ctx objectForKey:@"two"] isEqualToString:@"TWO"]); + test([[ctx objectForKey:@"three"] isEqualToString:@"THREE"]); + [self called]; +} +-(void) opContextException:(ICEException*)ex +{ + test(NO); +} +-(void) opDoubleMarshalingResponse +{ + [self called]; +} +-(void) opDoubleMarshalingException:(ICEException*)ex +{ + test(NO); +} +@end + +void +twowaysNewAMI(id<ICECommunicator> communicator, id<TestOperationsMyClassPrx> p) +{ + { + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opByte:(ICEByte)0xff p2:(ICEByte)0x0f response:^(ICEByte ret, ICEByte p3) { [cb opByteResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opByteException:ex]; }]; + test([cb check]); + } + + { + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opBool:YES p2:NO response:^(BOOL ret, BOOL p3) { [cb opBoolResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opBoolException:ex]; }]; + test([cb check]); + } + + { + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opShortIntLong:10 p2:11 p3:12 response:^(ICELong ret, ICEShort p4, ICEInt p5, ICELong p6) { [cb opShortIntLongResponse:ret p4:p4 p5:p5 p6:p6]; } exception:^(ICEException* ex) { [cb opShortIntLongException:ex]; }]; + test([cb check]); + } + + { + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opFloatDouble:3.14f p2:1.1E10 response:^(ICEDouble ret, ICEFloat p3, ICEDouble p4) { [cb opFloatDoubleResponse:ret p3:p3 p4:p4]; } exception:^(ICEException* ex) { [cb opFloatDoubleException:ex]; }]; + test([cb check]); + } + + { + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opString:@"hello" p2:@"world" response:^(NSMutableString* ret, NSMutableString* p3) { [cb opStringResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opStringException:ex]; }]; + test([cb check]); + } + + { + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opMyEnum:TestOperationsenum2 response:^(TestOperationsMyEnum ret, TestOperationsMyEnum p2) { [cb opMyEnumResponse:ret p2:p2]; } exception:^(ICEException* ex) { [cb opMyEnumException:ex]; }]; + test([cb check]); + } + + { + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opMyClass:p response:^(id<TestOperationsMyClassPrx> ret, id<TestOperationsMyClassPrx>p2, id<TestOperationsMyClassPrx> p3) { [cb opMyClassResponse:ret p2:p2 p3:p3]; } exception:^(ICEException* ex) { [cb opMyClassException:ex]; }]; + test([cb check]); + } + + { + TestOperationsStructure *si1 = [TestOperationsStructure structure]; + si1.p = p; + si1.e = TestOperationsenum3; + si1.s = [TestOperationsAnotherStruct anotherStruct]; + si1.s.s = @"abc"; + TestOperationsStructure *si2 = [TestOperationsStructure structure]; + si2.p = nil; + si2.e = TestOperationsenum2; + si2.s = [TestOperationsAnotherStruct anotherStruct]; + si2.s.s = @"def"; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opStruct:si1 p2:si2 response:^(TestOperationsStructure* ret, TestOperationsStructure* p3) { [cb opStructResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opStructException:ex]; }]; + test([cb check]); + } + + { + ICEByte buf1[] = { 0x01, 0x11, 0x12, 0x22 }; + ICEByte buf2[] = { 0xf1, 0xf2, 0xf3, 0xf4 }; + + TestOperationsMutableByteS *bsi1 = [TestOperationsMutableByteS data]; + TestOperationsMutableByteS *bsi2 = [TestOperationsMutableByteS data]; + + [bsi1 appendBytes:buf1 length:sizeof(buf1)]; + [bsi2 appendBytes:buf2 length:sizeof(buf2)]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opByteS:bsi1 p2:bsi2 response:^(TestOperationsMutableByteS* ret, TestOperationsMutableByteS* p3) { [cb opByteSResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opByteSException:ex]; }]; + test([cb check]); + } + + { + BOOL buf1[] = { YES, YES, NO }; + BOOL buf2[] = { NO }; + + TestOperationsMutableBoolS *bsi1 = [TestOperationsMutableBoolS data]; + TestOperationsMutableBoolS *bsi2 = [TestOperationsMutableBoolS data]; + + [bsi1 appendBytes:buf1 length:sizeof(buf1)]; + [bsi2 appendBytes:buf2 length:sizeof(buf2)]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opBoolS:bsi1 p2:bsi2 response:^(TestOperationsMutableBoolS* ret, TestOperationsMutableBoolS* p3) { [cb opBoolSResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opBoolSException:ex]; }]; + test([cb check]); + } + + { + ICEShort buf1[] = { 1, 2, 3 }; + ICEInt buf2[] = { 5, 6, 7, 8 }; + ICELong buf3[] = { 10, 30, 20 }; + + TestOperationsMutableShortS *ssi = [TestOperationsMutableShortS data]; + TestOperationsMutableIntS *isi = [TestOperationsMutableIntS data]; + TestOperationsMutableLongS *lsi = [TestOperationsMutableLongS data]; + + [ssi appendBytes:buf1 length:sizeof(buf1)]; + [isi appendBytes:buf2 length:sizeof(buf2)]; + [lsi appendBytes:buf3 length:sizeof(buf3)]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opShortIntLongS:ssi p2:isi p3:lsi response:^(TestOperationsMutableLongS* ret, TestOperationsMutableShortS* p4, TestOperationsMutableIntS* p5, TestOperationsMutableLongS* p6) { [cb opShortIntLongSResponse:ret p4:p4 p5:p5 p6:p6]; } exception:^(ICEException* ex) { [cb opShortIntLongSException:ex]; }]; + test([cb check]); + } + + { + ICEFloat buf1[] = { 3.14f, 1.11f }; + ICEDouble buf2[] = { 1.1E10, 1.2E10, 1.3E10 }; + + TestOperationsMutableFloatS *fsi = [TestOperationsMutableFloatS data]; + TestOperationsMutableDoubleS *dsi = [TestOperationsMutableDoubleS data]; + + [fsi appendBytes:buf1 length:sizeof(buf1)]; + [dsi appendBytes:buf2 length:sizeof(buf2)]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opFloatDoubleS:fsi p2:dsi response:^(TestOperationsMutableDoubleS* ret, TestOperationsMutableFloatS* p3, TestOperationsMutableDoubleS* p4) { [cb opFloatDoubleSResponse:ret p3:p3 p4:p4]; } exception:^(ICEException* ex) { [cb opFloatDoubleSException:ex]; }]; + test([cb check]); + } + + { + TestOperationsMutableStringS *ssi1 = [TestOperationsMutableStringS arrayWithCapacity:3]; + TestOperationsMutableStringS *ssi2 = [TestOperationsMutableStringS arrayWithCapacity:1]; + + [ssi1 addObject:@"abc"]; + [ssi1 addObject:@"de"]; + [ssi1 addObject:@"fghi"]; + + [ssi2 addObject:@"xyz"]; + + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opStringS:ssi1 p2:ssi2 response:^(TestOperationsMutableStringS* ret, TestOperationsMutableStringS* p3) { [cb opStringSResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opStringSException:ex]; }]; + test([cb check]); + } + + { + TestOperationsMutableByteSS *bsi1 = [TestOperationsMutableByteSS array]; + TestOperationsMutableByteSS *bsi2 = [TestOperationsMutableByteSS array]; + + ICEByte b; + TestOperationsMutableByteS *tmp = [TestOperationsMutableByteS data]; + + b = 0x01; + [tmp appendBytes:&b length:sizeof(b)]; + b = 0x11; + [tmp appendBytes:&b length:sizeof(b)]; + b = 0x12; + [tmp appendBytes:&b length:sizeof(b)]; + [bsi1 addObject:tmp]; + + tmp = [TestOperationsMutableByteS data]; + b = 0xff; + [tmp appendBytes:&b length:sizeof(b)]; + [bsi1 addObject:tmp]; + + tmp = [TestOperationsMutableByteS data]; + b = 0x0e; + [tmp appendBytes:&b length:sizeof(b)]; + [bsi2 addObject:tmp]; + + tmp = [TestOperationsMutableByteS data]; + b = 0xf2; + [tmp appendBytes:&b length:sizeof(b)]; + b = 0xf1; + [tmp appendBytes:&b length:sizeof(b)]; + [bsi2 addObject:tmp]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opByteSS:bsi1 p2:bsi2 response:^(TestOperationsMutableByteSS* ret, TestOperationsMutableByteSS* p3) { [cb opByteSSResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opByteSSException:ex]; }]; + test([cb check]); + } + + { + TestOperationsMutableFloatSS *fsi = [TestOperationsMutableFloatSS array]; + TestOperationsMutableDoubleSS *dsi = [TestOperationsMutableDoubleSS array]; + + ICEFloat f; + TestOperationsMutableFloatS *ftmp; + + ftmp = [TestOperationsMutableFloatS data]; + f = 3.14f; + [ftmp appendBytes:&f length:sizeof(f)]; + [fsi addObject:ftmp]; + ftmp = [TestOperationsMutableFloatS data]; + f = 1.11f; + [ftmp appendBytes:&f length:sizeof(f)]; + [fsi addObject:ftmp]; + ftmp = [TestOperationsMutableFloatS data]; + [fsi addObject:ftmp]; + + ICEDouble d; + TestOperationsMutableDoubleS *dtmp; + + dtmp = [TestOperationsMutableDoubleS data]; + d = 1.1E10; + [dtmp appendBytes:&d length:sizeof(d)]; + d = 1.2E10; + [dtmp appendBytes:&d length:sizeof(d)]; + d = 1.3E10; + [dtmp appendBytes:&d length:sizeof(d)]; + [dsi addObject:dtmp]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opFloatDoubleSS:fsi p2:dsi response:^(TestOperationsMutableDoubleSS* ret, TestOperationsMutableFloatSS* p3, TestOperationsMutableDoubleSS* p4) { [cb opFloatDoubleSSResponse:ret p3:p3 p4:p4]; } exception:^(ICEException* ex) { [cb opFloatDoubleSSException:ex]; }]; + test([cb check]); + } + + { + TestOperationsMutableStringSS * ssi1 = [TestOperationsMutableStringSS array]; + TestOperationsMutableStringSS * ssi2 = [TestOperationsMutableStringSS array]; + + TestOperationsMutableStringS *tmp; + + tmp = [TestOperationsMutableStringS array]; + [tmp addObject:@"abc"]; + [ssi1 addObject:tmp]; + tmp = [TestOperationsMutableStringS array]; + [tmp addObject:@"de"]; + [tmp addObject:@"fghi"]; + [ssi1 addObject:tmp]; + + [ssi2 addObject:[TestOperationsStringS array]]; + [ssi2 addObject:[TestOperationsStringS array]]; + tmp = [TestOperationsMutableStringS array]; + [tmp addObject:@"xyz"]; + [ssi2 addObject:tmp]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opStringSS:ssi1 p2:ssi2 response:^(TestOperationsMutableStringSS* ret, TestOperationsMutableStringSS* p3) { [cb opStringSSResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opStringSSException:ex]; }]; + test([cb check]); + } + + { + TestOperationsMutableStringSSS *sssi1 = [TestOperationsMutableStringSSS array]; + TestOperationsMutableStringSSS *sssi2 = [TestOperationsMutableStringSSS array]; + + TestOperationsMutableStringSS *tmpss; + TestOperationsMutableStringS *tmps; + + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@"abc"]; + [tmps addObject:@"de"]; + tmpss = [TestOperationsMutableStringSS array]; + [tmpss addObject:tmps]; + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@"xyz"]; + [tmpss addObject:tmps]; + [sssi1 addObject:tmpss]; + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@"hello"]; + tmpss = [TestOperationsMutableStringSS array]; + [tmpss addObject:tmps]; + [sssi1 addObject:tmpss]; + + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@""]; + [tmps addObject:@""]; + tmpss = [TestOperationsMutableStringSS array]; + [tmpss addObject:tmps]; + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@"abcd"]; + [tmpss addObject:tmps]; + [sssi2 addObject:tmpss]; + tmps = [TestOperationsMutableStringS array]; + [tmps addObject:@""]; + tmpss = [TestOperationsMutableStringSS array]; + [tmpss addObject:tmps]; + [sssi2 addObject:tmpss]; + tmpss = [TestOperationsMutableStringSS array]; + [sssi2 addObject:tmpss]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opStringSSS:sssi1 p2:sssi2 response:^(TestOperationsMutableStringSS* ret, TestOperationsMutableStringSS* p3) { [cb opStringSSSResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opStringSSSException:ex]; }]; + test([cb check]); + } + + { + TestOperationsMutableByteBoolD *di1 = [TestOperationsMutableByteBoolD dictionary]; + [di1 setObject:[NSNumber numberWithBool:YES] forKey:[NSNumber numberWithUnsignedChar:10]]; + [di1 setObject:[NSNumber numberWithBool:NO] forKey:[NSNumber numberWithUnsignedChar:100]]; + TestOperationsMutableByteBoolD *di2 = [TestOperationsMutableByteBoolD dictionary]; + [di2 setObject:[NSNumber numberWithBool:YES] forKey:[NSNumber numberWithUnsignedChar:10]]; + [di2 setObject:[NSNumber numberWithBool:NO] forKey:[NSNumber numberWithUnsignedChar:11]]; + [di2 setObject:[NSNumber numberWithBool:TRUE] forKey:[NSNumber numberWithUnsignedChar:101]]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opByteBoolD:di1 p2:di2 response:^(TestOperationsMutableByteBoolD* ret, TestOperationsMutableByteBoolD* p3) { [cb opByteBoolDResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opByteBoolDException:ex]; }]; + test([cb check]); + } + + { + TestOperationsMutableShortIntD *di1 = [TestOperationsMutableShortIntD dictionary]; + [di1 setObject:[NSNumber numberWithInt:-1] forKey:[NSNumber numberWithShort:110]]; + [di1 setObject:[NSNumber numberWithInt:123123] forKey:[NSNumber numberWithShort:1100]]; + TestOperationsMutableShortIntD *di2 = [TestOperationsMutableShortIntD dictionary]; + [di2 setObject:[NSNumber numberWithInt:-1] forKey:[NSNumber numberWithShort:110]]; + [di2 setObject:[NSNumber numberWithInt:-100] forKey:[NSNumber numberWithShort:111]]; + [di2 setObject:[NSNumber numberWithInt:0] forKey:[NSNumber numberWithShort:1101]]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opShortIntD:di1 p2:di2 response:^(TestOperationsMutableShortIntD* ret, TestOperationsMutableShortIntD* p3) { [cb opShortIntDResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opShortIntDException:ex]; }]; + test([cb check]); + } + + { + TestOperationsMutableLongFloatD *di1 = [TestOperationsMutableLongFloatD dictionary]; + [di1 setObject:[NSNumber numberWithFloat:-1.1f] forKey:[NSNumber numberWithLong:999999110]]; + [di1 setObject:[NSNumber numberWithFloat:123123.2f] forKey:[NSNumber numberWithLong:999999111]]; + TestOperationsMutableLongFloatD *di2 = [TestOperationsMutableLongFloatD dictionary]; + [di2 setObject:[NSNumber numberWithFloat:-1.1f] forKey:[NSNumber numberWithLong:999999110]]; + [di2 setObject:[NSNumber numberWithFloat:-100.4f] forKey:[NSNumber numberWithLong:999999120]]; + [di2 setObject:[NSNumber numberWithFloat:0.5f] forKey:[NSNumber numberWithLong:999999130]]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opLongFloatD:di1 p2:di2 response:^(TestOperationsMutableLongFloatD* ret, TestOperationsMutableLongFloatD* p3) { [cb opLongFloatDResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opLongFloatDException:ex]; }]; + test([cb check]); + } + + { + TestOperationsMutableStringStringD *di1 = [TestOperationsMutableStringStringD dictionary]; + [di1 setObject:@"abc -1.1" forKey:@"foo"]; + [di1 setObject:@"abc 123123.2" forKey:@"bar"]; + TestOperationsMutableStringStringD *di2 = [TestOperationsMutableStringStringD dictionary]; + [di2 setObject:@"abc -1.1" forKey:@"foo"]; + [di2 setObject:@"abc -100.4" forKey:@"FOO"]; + [di2 setObject:@"abc 0.5" forKey:@"BAR"]; + + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opStringStringD:di1 p2:di2 response:^(TestOperationsMutableStringStringD* ret, TestOperationsMutableStringStringD* p3) { [cb opStringStringDResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opStringStringDException:ex]; }]; + test([cb check]); + } + + { + TestOperationsMutableStringMyEnumD *di1 = [TestOperationsMutableStringMyEnumD dictionary]; + [di1 setObject:[NSNumber numberWithInt:TestOperationsenum1] forKey:@"abc"]; + [di1 setObject:[NSNumber numberWithInt:TestOperationsenum2] forKey:@""]; + TestOperationsMutableStringMyEnumD *di2 = [TestOperationsMutableStringMyEnumD dictionary]; + [di2 setObject:[NSNumber numberWithInt:TestOperationsenum1] forKey:@"abc"]; + [di2 setObject:[NSNumber numberWithInt:TestOperationsenum3] forKey:@"querty"]; + [di2 setObject:[NSNumber numberWithInt:TestOperationsenum2] forKey:@"Hello!!"]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opStringMyEnumD:di1 p2:di2 response:^(TestOperationsMutableStringMyEnumD* ret, TestOperationsMutableStringMyEnumD* p3) { [cb opStringMyEnumDResponse:ret p3:p3]; } exception:^(ICEException* ex) { [cb opStringMyEnumDException:ex]; }]; + test([cb check]); + } + + { + TestOperationsMutableMyEnumStringD *di1 = [TestOperationsMutableMyEnumStringD dictionary]; + [di1 setObject:@"abc" forKey:@(TestOperationsenum1)]; + TestOperationsMutableMyEnumStringD *di2 = [TestOperationsMutableMyEnumStringD dictionary]; + [di2 setObject:@"Hello!!" forKey:@(TestOperationsenum2)]; + [di2 setObject:@"querty" forKey:@(TestOperationsenum3)]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opMyEnumStringD:di1 + p2:di2 + response:^(TestOperationsMutableMyEnumStringD* ret, + TestOperationsMutableMyEnumStringD* p3) { [cb opMyEnumStringDResponse:ret + p3:p3]; } + exception:^(ICEException* ex) { [cb opMyEnumStringDException:ex]; }]; + [cb check]; + } + + { + TestOperationsMyStruct* s11 = [TestOperationsMyStruct myStruct:1 j:1]; + TestOperationsMyStruct* s12 = [TestOperationsMyStruct myStruct:1 j:2]; + TestOperationsMutableMyStructMyEnumD* di1 = [TestOperationsMutableMyStructMyEnumD dictionary]; + [di1 setObject:@(TestOperationsenum1) forKey:s11]; + [di1 setObject:@(TestOperationsenum2) forKey:s12]; + + TestOperationsMyStruct* s22 = [TestOperationsMyStruct myStruct:2 j:2]; + TestOperationsMyStruct* s23 = [TestOperationsMyStruct myStruct:2 j:3]; + TestOperationsMutableMyStructMyEnumD* di2 = [TestOperationsMutableMyStructMyEnumD dictionary]; + [di2 setObject:@(TestOperationsenum1) forKey:s11]; + [di2 setObject:@(TestOperationsenum3) forKey:s22]; + [di2 setObject:@(TestOperationsenum2) forKey:s23]; + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opMyStructMyEnumD:di1 + p2:di2 + response:^(TestOperationsMutableMyStructMyEnumD* ret, + TestOperationsMutableMyStructMyEnumD* p3) { [cb opMyStructMyEnumDResponse:ret + p3:p3 + s11:s11 + s12:s12 + s22:s22 + s23:s23]; } + exception:^(ICEException* ex) { [cb opMyStructMyEnumDException:ex]; }]; + [cb check]; + } + + { + const int lengths[] = { 0, 1, 2, 126, 127, 128, 129, 253, 254, 255, 256, 257, 1000 }; + + int l; + for(l = 0; l != sizeof(lengths) / sizeof(*lengths); ++l) + { + TestOperationsMutableIntS *s = [TestOperationsMutableIntS dataWithLength:(lengths[l] * sizeof(ICEInt))]; + ICEInt *ip = (ICEInt *)[s bytes]; + int i; + for(i = 0; i < lengths[l]; ++i) + { + *ip++ = i; + } + + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opIntS:s response:^(TestOperationsMutableIntS* ret) { [cb opIntSResponse:ret]; } exception:^(ICEException* ex) { [cb opIntSException:ex]; }]; + test([cb check]); + } + } + + { + ICEMutableContext *ctx = [ICEMutableContext dictionary]; + [ctx setObject:@"ONE" forKey:@"one"]; + [ctx setObject:@"TWO" forKey:@"two"]; + [ctx setObject:@"THREE" forKey:@"three"]; + { + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opContext:^(ICEMutableContext* ctx) { [cb opEmptyContextResponse:ctx]; } exception:^(ICEException* ex) { [cb opContextException:ex]; }]; + test([cb check]); + } + { + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opContext:ctx response:^(ICEMutableContext* ctx) { [cb opNonEmptyContextResponse:ctx]; } exception:^(ICEException* ex) { [cb opContextException:ex]; }]; + test([cb check]); + } + { + id<TestOperationsMyClassPrx> p2 = [TestOperationsMyClassPrx checkedCast:[p ice_context:ctx]]; + test([[p2 ice_getContext] isEqual:ctx]); + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p2 begin_opContext:^(ICEMutableContext* ctx) { [cb opNonEmptyContextResponse:ctx]; } exception:^(ICEException* ex) { [cb opContextException:ex]; }]; + test([cb check]); + + + cb = [TestNewAMIOperationsCallback create]; + [p2 begin_opContext:ctx response:^(ICEMutableContext* ctx) { [cb opNonEmptyContextResponse:ctx]; } exception:^(ICEException* ex) { [cb opContextException:ex]; }]; + test([cb check]); + } + } + + { + // + // TestOperations implicit context propagation + // + + NSString *impls[] = {@"Shared", @"PerThread"}; + for(int i = 0; i < 2; i++) + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + [initData setProperties:[[communicator getProperties] clone]]; + [initData.properties setProperty:@"Ice.ImplicitContext" value:impls[i]]; + + id<ICECommunicator> ic = [ICEUtil createCommunicator:initData]; + + ICEMutableContext *ctx = [ICEMutableContext dictionary]; + [ctx setObject:@"ONE" forKey:@"one" ]; + [ctx setObject:@"TWO" forKey:@"two" ]; + [ctx setObject:@"THREE" forKey:@"three"]; + + id<TestOperationsMyClassPrx> p = [TestOperationsMyClassPrx uncheckedCast: + [ic stringToProxy:@"test:default -p 12010"]]; + + [[ic getImplicitContext] setContext:(ctx)]; + test([[[ic getImplicitContext] getContext] isEqualToDictionary:ctx]); + { + id<ICEAsyncResult> r = [p begin_opContext]; + ICEContext* c = [p end_opContext:r]; + test([c isEqualToDictionary:ctx]); + } + + test([[ic getImplicitContext] get:@"zero"] == nil); + [[ic getImplicitContext] put:@"zero" value:@"ZERO"]; + test([[[ic getImplicitContext] get:@"zero"] isEqualToString:@"ZERO"]); + + ctx = [[ic getImplicitContext] getContext]; + { + id<ICEAsyncResult> r = [p begin_opContext]; + ICEContext* c = [p end_opContext:r]; + test([c isEqualToDictionary:ctx]); + } + + ICEMutableContext *prxContext = [ICEMutableContext dictionary]; + [prxContext setObject:@"UN" forKey:@"one"]; + [prxContext setObject:@"QUATRE" forKey:@"four"]; + + ICEMutableContext *combined = [ICEMutableContext dictionaryWithDictionary:ctx]; + [combined addEntriesFromDictionary:prxContext]; + + p = [TestOperationsMyClassPrx uncheckedCast:[p ice_context:prxContext]]; + + [[ic getImplicitContext] setContext:[ICEMutableContext dictionary]]; + { + id<ICEAsyncResult> r = [p begin_opContext]; + ICEContext* c = [p end_opContext:r]; + test([c isEqualToDictionary:prxContext]); + } + + [[ic getImplicitContext] setContext:ctx]; + { + id<ICEAsyncResult> r = [p begin_opContext]; + ICEContext* c = [p end_opContext:r]; + test([c isEqualToDictionary:combined]); + } + + [[ic getImplicitContext] setContext:[ICEContext dictionary]]; + [ic destroy]; + } + } + + + + { + ICEDouble d = 1278312346.0 / 13.0; + TestOperationsMutableDoubleS *ds = [TestOperationsMutableDoubleS dataWithLength:(5 * sizeof(ICEDouble))]; + ICEDouble *pb = (ICEDouble *)[ds bytes]; + int i = 5; + while(i-- > 0) + { + *pb++ = d; + } + TestNewAMIOperationsCallback* cb = [TestNewAMIOperationsCallback create]; + [p begin_opDoubleMarshaling:d p2:ds response:^() { [cb opDoubleMarshalingResponse]; } exception:^(ICEException* ex) { [cb opDoubleMarshalingException:ex]; }]; + test([cb check]); + } + + // Marshaling tests for NSNull are present only in synchronous test because testing asynchronously + // would only test the same marshaling code that's been tested already. +} + diff --git a/objc/test/Ice/operations/run.py b/objc/test/Ice/operations/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/operations/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/optional/.gitignore b/objc/test/Ice/optional/.gitignore new file mode 100644 index 00000000000..7096f056538 --- /dev/null +++ b/objc/test/Ice/optional/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +OptionalTest.m +OptionalTest.h diff --git a/objc/test/Ice/optional/AllTests.m b/objc/test/Ice/optional/AllTests.m new file mode 100644 index 00000000000..4f785390e61 --- /dev/null +++ b/objc/test/Ice/optional/AllTests.m @@ -0,0 +1,1448 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <OptionalTest.h> + +#import <Foundation/Foundation.h> + +@interface TestObjectReader : ICEObject +{ +} +@end + +@implementation TestObjectReader +-(void) read__:(id<ICEInputStream>)is +{ + [is startObject]; + [is startSlice]; + [is endSlice]; + [is endObject:NO]; +} +@end + +@interface BObjectReader : ICEObject +{ +} +@end + +@implementation BObjectReader +-(void) read__:(id<ICEInputStream>)is +{ + [is startObject]; + // ::Test::B + [is startSlice]; + [is readInt]; + [is endSlice]; + // ::Test::A + [is startSlice]; + [is readInt]; + [is endSlice]; + [is endObject:NO]; +}; +@end + +@interface CObjectReader : ICEObject +{ +} +@end + +@implementation CObjectReader +-(void) read__:(id<ICEInputStream>)is +{ + [is startObject]; + // ::Test::C + [is startSlice]; + [is skipSlice]; + // ::Test::B + [is startSlice]; + [is readInt]; + [is endSlice]; + // ::Test::A + [is startSlice]; + [is readInt]; + [is endSlice]; + [is endObject:NO]; +}; +@end + +@interface DObjectWriter : ICEObject +{ +} +@end + +@implementation DObjectWriter +-(void) write__:(id<ICEOutputStream>)os +{ + [os startObject:0]; + // ::Test::D + [os startSlice:@"::Test::D" compactId:-1 lastSlice:NO]; + [os writeString:@"test"]; + if([os writeOptional:1 format:ICEOptionalFormatVSize]) + { + ICEMutableStringSeq* o = [ICEMutableStringSeq array]; + [o addObject:@"test1"]; + [o addObject:@"test2"]; + [o addObject:@"test3"]; + [o addObject:@"test4"]; + [ICEStringSeqHelper write:o stream:os]; + } + if([os writeOptional:1000 format:ICEOptionalFormatClass]) + { + TestOptionalA* a = [TestOptionalA a]; + a.mc = 18; + [os writeObject:a]; + } + [os endSlice]; + // ::Test::B + [os startSlice:@"::Test::B" compactId:-1 lastSlice:NO]; + [os writeInt:14]; + [os endSlice]; + // ::Test::A + [os startSlice:@"::Test::A" compactId:-1 lastSlice:YES]; + [os writeInt:14]; + [os endSlice]; + [os endObject]; +} +@end + +@interface DObjectReader : ICEObject +{ + TestOptionalA* a_; +} +@end + +@implementation DObjectReader +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [a_ release]; + [super dealloc]; +} +#endif +-(void) read__:(id<ICEInputStream>)is +{ + [is startObject]; + // ::Test::D + [is startSlice]; + NSString* s = [is readString]; + test([s isEqualToString:@"test"]); + test([is readOptional:1 format:ICEOptionalFormatVSize]); + NSMutableArray* o = [ICEStringSeqHelper read:is]; + test(o != nil && [o count] == 4 && + [[o objectAtIndex:0] isEqualToString:@"test1"] && + [[o objectAtIndex:1] isEqualToString:@"test2"] && + [[o objectAtIndex:2] isEqualToString:@"test3"] && + [[o objectAtIndex:3] isEqualToString:@"test4"]); + test([is readOptional:1000 format:ICEOptionalFormatClass]); + [is newObject:(ICEObject**)&a_ expectedType:[TestOptionalA class]]; + [is endSlice]; + + // ::Test::B + [is startSlice]; + [is readInt]; + [is endSlice]; + // ::Test::A + [is startSlice]; + [is readInt]; + [is endSlice]; + [is endObject:NO]; +} +-(void) check +{ + test(a_.mc == 18); +} +@end + +@interface FObjectReader : ICEObject +{ + TestOptionalF* f_; +} +@end + +@implementation FObjectReader +-(id) init +{ + self = [super init]; + if(self) + { + f_ = nil; + } + return self; +} + +-(void) read__:(id<ICEInputStream>)is +{ +#if defined(__clang__) && !__has_feature(objc_arc) + if(f_ != nil) + { + [f_ release]; + } +#endif + f_ = [TestOptionalF new]; + [is startObject]; + [is startSlice]; + // Don't read optional af on purpose + //[is_ readObject:(ICEObject**)&self->af expectedType:[TestOptionalA class]]; + [is endSlice]; + [is startSlice]; + TestOptionalA* ICE_AUTORELEASING_QUALIFIER ae; + [is readObject:(ICEObject**)&ae expectedType:[TestOptionalA class]]; + [is endSlice]; + [is endObject:NO]; + f_.ae = ae; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [f_ release]; + [super dealloc]; +} +#endif + +-(TestOptionalF*) getF +{ + return f_; +} +@end + +@interface FactoryI : NSObject<ICEObjectFactory> +{ + BOOL enabled_; +} ++(FactoryI*) factoryI; +-(void) setEnabled:(BOOL)enabled; +@end + +@implementation FactoryI ++(FactoryI*) factoryI +{ +#if defined(__clang__) && __has_feature(objc_arc) + return [[FactoryI alloc] init]; +#else + return [[[FactoryI alloc] init] autorelease]; +#endif +} +-(id) init +{ + self = [super init]; + if(self) + { + self->enabled_ = NO; + } + return self; +} +-(ICEObject*) create:(NSString*)typeId +{ + if(!enabled_) + { + return nil; + } + if([typeId isEqualToString:@"::Test::OneOptional"]) + { + return [TestObjectReader new]; + } + else if([typeId isEqualToString:@"::Test::MultiOptional"]) + { + return [TestObjectReader new]; + } + else if([typeId isEqualToString:@"::Test::B"]) + { + return [BObjectReader new]; + } + else if([typeId isEqualToString:@"::Test::C"]) + { + return [CObjectReader new]; + } + else if([typeId isEqualToString:@"::Test::D"]) + { + return [DObjectReader new]; + } + else if([typeId isEqualToString:@"::Test::F"]) + { + return [FObjectReader new]; + } + + return nil; +} +-(void) destroy +{ +} +-(void) setEnabled:(BOOL)enabled +{ + self->enabled_ = enabled; +} +@end + +id<TestOptionalInitialPrx> +optionalAllTests(id<ICECommunicator> communicator) +{ + FactoryI* factory = [FactoryI factoryI]; + [communicator addObjectFactory:factory sliceId:@""]; + + tprintf("testing stringToProxy... "); + NSString* sref = @"initial:default -p 12010"; + id<ICEObjectPrx> base = [communicator stringToProxy:sref]; + test(base); + tprintf("ok\n"); + + tprintf("testing checked cast... "); + id<TestOptionalInitialPrx> initial = [TestOptionalInitialPrx checkedCast:base]; + test(initial != nil); + test([initial isEqual:base]); + tprintf("ok\n"); + + tprintf("testing constructor, copy constructor, and assignment operator... "); + + TestOptionalOneOptional* oo1 = [TestOptionalOneOptional oneOptional]; + test(![oo1 hasA]); + oo1.a = 15; + test([oo1 hasA] && oo1.a == 15); + + TestOptionalOneOptional* oo2 = [TestOptionalOneOptional oneOptional:@16]; + test([oo2 hasA] && oo2.a == 16); + + TestOptionalOneOptional* oon = [TestOptionalOneOptional oneOptional:ICENone]; + test(![oon hasA]); + + TestOptionalMultiOptional* mo1 = [TestOptionalMultiOptional multiOptional]; + mo1.a = 15; + mo1.b = true; + mo1.c = 19; + mo1.d = 78; + mo1.e = 99; + mo1.f = 5.5f; + mo1.g = 1.0; + mo1.h = @"test"; + mo1.i = TestOptionalMyEnumMember; + mo1.j = [TestOptionalMultiOptionalPrx uncheckedCast:[communicator stringToProxy:@"test"]]; + //mo1.k = mo1; + ICEByte bsa[] = { 0x05 }; + mo1.bs = [TestOptionalByteSeq dataWithBytes:bsa length:1]; + mo1.ss = [TestOptionalStringSeq arrayWithObjects:@"test", @"test2", nil]; + mo1.iid = [TestOptionalIntIntDict dictionaryWithObjectsAndKeys:@3, @4, nil]; + mo1.sid = [TestOptionalStringIntDict dictionaryWithObjectsAndKeys:@10, @"test", nil]; + TestOptionalFixedStruct* fs = [TestOptionalFixedStruct fixedStruct]; + fs.m = 78; + mo1.fs = fs; + TestOptionalVarStruct* vs = [TestOptionalVarStruct varStruct]; + vs.m = @"hello"; + mo1.vs = vs; + + ICEShort shs[] = { 1 }; + mo1.shs = [TestOptionalShortSeq dataWithBytes:shs length:sizeof(shs)]; + + TestOptionalMyEnum es[] = { TestOptionalMyEnumMember, TestOptionalMyEnumMember }; + mo1.es = [TestOptionalMyEnumSeq dataWithBytes:es length:sizeof(es)]; + mo1.fss = [TestOptionalFixedStructSeq arrayWithObject:fs]; + mo1.vss = [TestOptionalVarStructSeq arrayWithObject:vs]; + mo1.oos = [TestOptionalOneOptionalSeq arrayWithObject:oo1]; + id<TestOptionalOneOptionalPrx> oneOptionalProxy = + [TestOptionalOneOptionalPrx uncheckedCast:[communicator stringToProxy:@"test"]]; + mo1.oops = [TestOptionalOneOptionalPrxSeq arrayWithObject:oneOptionalProxy]; + mo1.ied = [TestOptionalIntEnumDict dictionaryWithObjectsAndKeys:@(TestOptionalMyEnumMember), @4, nil]; + mo1.ifsd = [TestOptionalIntFixedStructDict dictionaryWithObjectsAndKeys:fs, @4, nil]; + mo1.ivsd = [TestOptionalIntVarStructDict dictionaryWithObjectsAndKeys:vs, @4, nil]; + mo1.iood = [TestOptionalIntOneOptionalDict dictionaryWithObjectsAndKeys:[TestOptionalOneOptional oneOptional:@15], + @5, nil]; + mo1.ioopd = [TestOptionalIntOneOptionalPrxDict dictionaryWithObjectsAndKeys:oneOptionalProxy, @5, nil]; + BOOL bos[] = { NO, YES, NO }; + mo1.bos = [TestOptionalBoolSeq dataWithBytes:bos length:sizeof(bos)]; + + TestOptionalMultiOptional* mo3 = [mo1 copy]; +#if defined(__clang__) && !__has_feature(objc_arc) + [mo3 autorelease]; +#endif + test(mo3.a == 15); + test(mo3.b == YES); + test(mo3.c == 19); + test(mo3.d == 78); + test(mo3.e == 99); + test(mo3.f == 5.5f); + test(mo3.g == 1.0); + test([mo3.h isEqualToString:@"test"]); + test(mo3.i == TestOptionalMyEnumMember); + test([mo3.j isEqual:[TestOptionalMultiOptionalPrx uncheckedCast:[communicator stringToProxy:@"test"]]]); + //test(mo3.k == mo1); + test(mo3.bs == mo1.bs); + test(mo3.ss == mo1.ss); + test(mo3.iid == mo1.iid); + test(mo3.sid == mo1.sid); + test(mo3.fs == mo1.fs); + test(mo3.vs == mo1.vs); + + test(mo3.shs == mo1.shs); + test(mo3.es == mo1.es); + test(mo3.fss == mo1.fss); + test(mo3.vss == mo1.vss); + test(mo3.oos == mo1.oos); + test(mo3.oops == mo1.oops); + + test(mo3.ied == mo1.ied); + test(mo3.ifsd == mo1.ifsd); + test(mo3.ivsd == mo1.ivsd); + test(mo3.iood == mo1.iood); + test(mo3.ioopd == mo1.ioopd); + + test(mo3.bos == mo1.bos); + + tprintf("ok\n"); + +// tprintf("testing comparison operators... "); + +// test(mo1->a == 15 && 15 == mo1->a && mo1->a != 16 && 16 != mo1->a); +// test(mo1->a < 16 && mo1->a > 14 && mo1->a <= 15 && mo1->a >= 15 && mo1->a <= 16 && mo1->a >= 14); +// test(mo1->a > IceUtil::Optional<int>() && IceUtil::Optional<int>() < mo1->a); +// test(14 > IceUtil::Optional<int>() && IceUtil::Optional<int>() < 14); + +// test(mo1->h == "test" && "test" == mo1->h && mo1->h != "testa" && "testa" != mo1->h); +// test(mo1->h < "test1" && mo1->h > "tesa" && mo1->h <= "test"); +// test(mo1->h >= "test" && mo1->h <= "test1" && mo1->h >= "tesa"); +// test(mo1->h > IceUtil::Optional<string>() && IceUtil::Optional<string>() < mo1->h); +// test("test1" > IceUtil::Optional<string>() && IceUtil::Optional<string>() < "test1"); + +// tprintf("ok\n"); + + tprintf("testing marshalling... "); + TestOptionalOneOptional* oo4 = (TestOptionalOneOptional*)[initial pingPong:[TestOptionalOneOptional oneOptional]]; + test(![oo4 hasA]); + + TestOptionalOneOptional* oo5 = (TestOptionalOneOptional*)[initial pingPong:oo1]; + test(oo1.a == oo5.a); + + TestOptionalMultiOptional* mo4 = (TestOptionalMultiOptional*) + [initial pingPong:[TestOptionalMultiOptional multiOptional]]; + test(![mo4 hasA]); + test(![mo4 hasB]); + test(![mo4 hasC]); + test(![mo4 hasD]); + test(![mo4 hasE]); + test(![mo4 hasF]); + test(![mo4 hasG]); + test(![mo4 hasH]); + test(![mo4 hasI]); + test(![mo4 hasJ]); + test(![mo4 hasK]); + test(![mo4 hasBs]); + test(![mo4 hasSs]); + test(![mo4 hasIid]); + test(![mo4 hasSid]); + test(![mo4 hasFs]); + test(![mo4 hasVs]); + + test(![mo4 hasShs]); + test(![mo4 hasEs]); + test(![mo4 hasFss]); + test(![mo4 hasVss]); + test(![mo4 hasOos]); + test(![mo4 hasOops]); + + test(![mo4 hasIed]); + test(![mo4 hasIfsd]); + test(![mo4 hasIvsd]); + test(![mo4 hasIood]); + test(![mo4 hasIoopd]); + + test(![mo4 hasBos]); + + //mo1.k = mo1; + TestOptionalMultiOptional* mo5 = (TestOptionalMultiOptional*)[initial pingPong:mo1]; + test(mo5.a == mo1.a); + test(mo5.b == mo1.b); + test(mo5.c == mo1.c); + test(mo5.d == mo1.d); + test(mo5.e == mo1.e); + test(mo5.f == mo1.f); + test(mo5.g == mo1.g); + test([mo5.h isEqualToString:mo1.h]); + test(mo5.i == mo1.i); + test([mo5.j isEqual:mo1.j]); + //test(mo5.k == mo5); + test([mo5.bs isEqual:mo1.bs]); + test([mo5.ss isEqual:mo1.ss]); + test([mo5.iid isEqual: mo1.iid]); + test([mo5.sid isEqual:mo1.sid]); + test([mo5.fs isEqual:mo1.fs]); + test([mo5.vs isEqual:mo1.vs]); + + test([mo5.shs isEqual:mo1.shs]); + test([mo5.es isEqual:mo1.es]); + test([mo5.fss isEqual:mo1.fss]); + test([mo5.vss isEqual:mo1.vss]); + test([mo5.oos count] > 0 && ((TestOptionalOneOptional*)[mo5.oos objectAtIndex:0]).a == oo1.a); + test([mo5.oops isEqual:mo1.oops]); + + test([mo5.ied isEqual:mo1.ied]); + test([mo5.ifsd isEqual:mo1.ifsd]); + test([mo5.ivsd isEqual:mo1.ivsd]); + test([mo5.iood count] > 0 && ((TestOptionalOneOptional*)[mo5.iood objectForKey:@5]).a == 15); + test([mo5.ioopd isEqual:mo1.ioopd]); + + test([mo5.bos isEqual:mo1.bos]); + + // Clear the first half of the optional parameters + TestOptionalMultiOptional* mo6 = [mo5 copy]; +#if defined(__clang__) && !__has_feature(objc_arc) + [mo6 autorelease]; +#endif + [mo6 clearA]; + [mo6 clearC]; + [mo6 clearE]; + [mo6 clearG]; + [mo6 clearI]; + [mo6 clearK]; + [mo6 clearSs]; + [mo6 clearSid]; + [mo6 clearVs]; + + [mo6 clearEs]; + [mo6 clearVss]; + [mo6 clearOops]; + + [mo6 clearIed]; + [mo6 clearIvsd]; + [mo6 clearIoopd]; + + TestOptionalMultiOptional* mo7 = (TestOptionalMultiOptional*)[initial pingPong:mo6]; + test(![mo7 hasA]); + test(mo7.b == mo1.b); + test(![mo7 hasC]); + test(mo7.d == mo1.d); + test(![mo7 hasE]); + test(mo7.f == mo1.f); + test(![mo7 hasG]); + test([mo7.h isEqual:mo1.h]); + test(![mo7 hasI]); + test([mo7.j isEqual:mo1.j]); + test(![mo7 hasK]); + test([mo7.bs isEqual:mo1.bs]); + test(![mo7 hasSs]); + test([mo7.iid isEqual:mo1.iid]); + test(![mo7 hasSid]); + test([mo7.fs isEqual:mo1.fs]); + test(![mo7 hasVs]); + + test([mo7.shs isEqual:mo1.shs]); + test(![mo7 hasEs]); + test([mo7.fss isEqual:mo1.fss]); + test(![mo7 hasVss]); + test([mo7.oos count] > 0 && ((TestOptionalOneOptional*)[mo7.oos objectAtIndex:0]).a == oo1.a); + test(![mo7 hasOops]); + + test(![mo7 hasIed]); + test([mo7.ifsd isEqual:mo1.ifsd]); + test(![mo7 hasIvsd]); + test([mo7.iood count] > 0 && ((TestOptionalOneOptional*)[mo7.iood objectForKey:@5]).a == 15); + test(![mo7 hasIoopd]); + + // Clear the second half of the optional parameters + TestOptionalMultiOptional* mo8 = [mo5 copy]; +#if defined(__clang__) && !__has_feature(objc_arc) + [mo8 autorelease]; +#endif + [mo8 clearB]; + [mo8 clearD]; + [mo8 clearF]; + [mo8 clearH]; + [mo8 clearJ]; + [mo8 clearBs]; + [mo8 clearIid]; + [mo8 clearFs]; + + [mo8 clearShs]; + [mo8 clearFss]; + [mo8 clearOos]; + + [mo8 clearIfsd]; + [mo8 clearIood]; + + TestOptionalMultiOptional* mo9 = (TestOptionalMultiOptional*)[initial pingPong:mo8]; + test(mo9.a == mo1.a); + test(![mo9 hasB]); + test(mo9.c == mo1.c); + test(![mo9 hasD]); + test(mo9.e == mo1.e); + test(![mo9 hasF]); + test(mo9.g == mo1.g); + test(![mo9 hasH]); + test(mo9.i == mo1.i); + test(![mo9 hasJ]); + //test(mo9.k == mo9.k); + test(![mo9 hasBs]); + test([mo9.ss isEqual:mo1.ss]); + test(![mo9 hasIid]); + test([mo9.sid isEqual:mo1.sid]); + test(![mo9 hasFs]); + test([mo9.vs isEqual:mo1.vs]); + + test(![mo8 hasShs]); + test([mo8.es isEqual:mo1.es]); + test(![mo8 hasFss]); + test([mo8.vss isEqual:mo1.vss]); + test(![mo8 hasOos]); + test([mo8.oops isEqual:mo1.oops]); + + test([mo8.ied isEqual:mo1.ied]); + test(![mo8 hasIfsd]); + test([mo8.ivsd isEqual:mo1.ivsd]); + test(![mo8 hasIood]); + + // + // Send a request using blobjects. Upon receival, we don't read + // any of the optional members. This ensures the optional members + // are skipped even if the receiver knows nothing about them. + // + [factory setEnabled:YES]; + id<ICEOutputStream> os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [os writeObject:oo1]; + [os endEncapsulation]; + ICEByteSeq* inEncaps = [os finished]; + ICEMutableByteSeq* outEncaps; + test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]); + id<ICEInputStream> is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + ICEObject* obj; + [is readObject:&obj]; + [is endEncapsulation]; + test(obj != nil && [obj isKindOfClass:[TestObjectReader class]]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [os writeObject:mo1]; + [os endEncapsulation]; + inEncaps = [os finished]; + test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]); + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is readObject:&obj]; + [is endEncapsulation]; + test(obj != nil && [obj isKindOfClass:[TestObjectReader class]]); + [factory setEnabled:false]; + + // + // Use the 1.0 encoding with operations whose only class parameters are optional. + // + id oo = [TestOptionalOneOptional oneOptional:@53]; + [initial sendOptionalClass:YES o:oo]; + [[initial ice_encodingVersion:ICEEncoding_1_0] sendOptionalClass:YES o:oo]; + + [initial returnOptionalClass:YES o:&oo]; + test(oo != nil && oo != ICENone); + [[initial ice_encodingVersion:ICEEncoding_1_0] returnOptionalClass:YES o:&oo]; + test(oo == ICENone); + + tprintf("ok\n"); + + tprintf("testing marshalling of large containers with fixed size elements..."); + TestOptionalMultiOptional* mc = [TestOptionalMultiOptional multiOptional]; + + mc.bs = [TestOptionalMutableByteSeq dataWithLength:1000]; + mc.shs = [TestOptionalMutableShortSeq dataWithLength:300 * sizeof(ICEShort)]; + mc.fss = [TestOptionalMutableFixedStructSeq array]; + for(int i = 0; i < 300; ++i) + { + [(TestOptionalMutableFixedStructSeq*)mc.fss addObject:[TestOptionalFixedStruct fixedStruct]]; + } + + mc.ifsd = [TestOptionalMutableIntFixedStructDict dictionary]; + for(int i = 0; i < 300; ++i) + { + [(TestOptionalMutableIntFixedStructDict*)mc.ifsd setObject:[TestOptionalFixedStruct fixedStruct] forKey:@(i)]; + } + + mc = (TestOptionalMultiOptional*)[initial pingPong:mc]; + test([mc.bs length] == 1000); + test([mc.shs length] == 300 * sizeof(ICEShort)); + test([mc.fss count] == 300); + test([mc.ifsd count] == 300); + + [factory setEnabled:YES]; + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [os writeObject:mc]; + [os endEncapsulation]; + inEncaps = [os finished]; + + test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]); + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is readObject:&obj]; + [is endEncapsulation]; + test(obj != nil && [obj isKindOfClass:[TestObjectReader class]]); + [factory setEnabled:NO]; + + tprintf("ok\n"); + + tprintf("testing tag marshalling... "); + TestOptionalB* b = [TestOptionalB b]; + TestOptionalB* b2 = (TestOptionalB*)[initial pingPong:b]; + test(![b2 hasMa]); + test(![b2 hasMb]); + test(![b2 hasMc]); + + b.ma = 10; + b.mb = 11; + b.mc = 12; + b.md = 13; + + b2 = (TestOptionalB*)[initial pingPong:b]; + test(b2.ma == 10); + test(b2.mb == 11); + test(b2.mc == 12); + test(b2.md == 13); + + [factory setEnabled:YES]; + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [os writeObject:b]; + [os endEncapsulation]; + inEncaps = [os finished]; + test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]); + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is readObject:&obj]; + [is endEncapsulation]; + test(obj != nil); + [factory setEnabled:NO]; + + tprintf("ok\n"); + + tprintf("testing marshalling of objects with optional objects..."); + { + TestOptionalF* f = [TestOptionalF f]; + + f.af = [TestOptionalA a]; + f.ae = f.af; + + TestOptionalF* rf = (TestOptionalF*)[initial pingPong:f]; + test(rf.ae == rf.af); + + [factory setEnabled:YES]; + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [os writeObject:f]; + [os endEncapsulation]; + inEncaps = [os finished]; + is = [ICEUtil createInputStream:communicator data:inEncaps]; + [is startEncapsulation]; + [is readObject:&obj]; + [is endEncapsulation]; + [factory setEnabled:NO]; + + test(obj != nil && [obj isKindOfClass:[FObjectReader class]]); + rf = [(FObjectReader*)obj getF]; + test(rf.ae != nil && ![rf hasAf]); + } + tprintf("ok\n"); + + tprintf("testing optional with default values... "); + TestOptionalWD* wd = (TestOptionalWD*)[initial pingPong:[TestOptionalWD wD]]; + test(wd.a == 5); + test([wd.s isEqualToString:@"test"]); + [wd clearA]; + [wd clearS]; + wd = (TestOptionalWD*)[initial pingPong:wd]; + test(![wd hasA]); + test(![wd hasS]); + tprintf("ok\n"); + + if([[communicator getProperties] getPropertyAsInt:@"Ice.Default.SlicedFormat"] > 0) + { + tprintf("testing marshalling with unknown class slices... "); + { + TestOptionalC* c = [TestOptionalC c]; + c.ss = @"test"; + c.ms = @"testms"; + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [os writeObject:c]; + [os endEncapsulation]; + inEncaps = [os finished]; + [factory setEnabled:YES]; + test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]); + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is readObject:&obj]; + [is endEncapsulation]; + test(obj != nil && [obj isKindOfClass:[CObjectReader class]]); + [factory setEnabled:NO]; + + [factory setEnabled:YES]; + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + ICEObject* d = [DObjectWriter new]; + [os writeObject:d]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d release]; +#endif + [os endEncapsulation]; + inEncaps = [os finished]; + test([initial ice_invoke:@"pingPong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]); + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is readObject:&obj]; + [is endEncapsulation]; + test(obj != nil && [obj isKindOfClass:[DObjectReader class]]); + [(DObjectReader*)obj check]; + [factory setEnabled:NO]; + } + tprintf("ok\n"); + + tprintf("testing optionals with unknown classes..."); + { + TestOptionalA* a = [TestOptionalA a]; + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [os writeObject:a]; + DObjectWriter* writer = [DObjectWriter new]; + [ICEObjectHelper writeOpt:writer stream:os tag:1]; +#if defined(__clang__) && !__has_feature(objc_arc) + [writer release]; +#endif + [os endEncapsulation]; + inEncaps = [os finished]; + test([initial ice_invoke:@"opClassAndUnknownOptional" mode:ICENormal inEncaps:inEncaps + outEncaps:&outEncaps]); + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + tprintf("ok\n"); + } + + tprintf("testing optional parameters... "); + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opByte:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + p1 = @0x56; + p2 = [initial opByte:p1 p3:&p3]; + test([p2 isEqual:@0x56] && [p3 isEqual:@0x56]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [ICEByteHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opByte" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [ICEByteHelper readOpt:is tag:1]; + p3 = [ICEByteHelper readOpt:is tag:3]; + + id p4 = @0x08; + p4 = [ICEByteHelper readOpt:is tag:89]; + + [is endEncapsulation]; + test([p2 isEqual:@0x56] && [p3 isEqual:@0x56] && [p4 isEqual:ICENone]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opLong:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + p1 = @56; + p2 = [initial opLong:p1 p3:&p3]; + test([p2 isEqual:@56] && [p3 isEqual:@56]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [ICELongHelper writeOpt:p1 stream:os tag:1]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opLong" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p3 = [ICELongHelper readOpt:is tag:2]; + p2 = [ICELongHelper readOpt:is tag:3]; + [is endEncapsulation]; + test([p2 isEqual:@56] && [p3 isEqual:@56]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opString:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + p1 = @"test"; + p2 = [initial opString:p1 p3:&p3]; + test([p2 isEqualToString:@"test"] && [p3 isEqualToString:@"test"]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [ICEStringHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opString" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [ICEStringHelper readOpt:is tag:1]; + p3 = [ICEStringHelper readOpt:is tag:3]; + [is endEncapsulation]; + test([p2 isEqualToString:@"test"] && [p3 isEqualToString:@"test"]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opOneOptional:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + p1 = [TestOptionalOneOptional oneOptional:@58]; + p2 = [initial opOneOptional:p1 p3:&p3]; + test([p2 isKindOfClass:[TestOptionalOneOptional class]] && [p3 isKindOfClass:[TestOptionalOneOptional class]]); + test(((TestOptionalOneOptional*)p2).a == 58 && ((TestOptionalOneOptional*)p3).a == 58); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [ICEObjectHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opOneOptional" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [ICEObjectHelper readOpt:&p2 stream:is tag:1]; + [ICEObjectHelper readOpt:&p3 stream:is tag:3]; + [is endEncapsulation]; + test([p2 isKindOfClass:[TestOptionalOneOptional class]] && [p3 isKindOfClass:[TestOptionalOneOptional class]]); + test(((TestOptionalOneOptional*)p2).a == 58 && ((TestOptionalOneOptional*)p3).a == 58); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opOneOptionalProxy:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + p1 = [TestOptionalOneOptionalPrx uncheckedCast:[communicator stringToProxy:@"test"]]; + p2 = [initial opOneOptionalProxy:p1 p3:&p3]; + test([p2 isKindOfClass:[TestOptionalOneOptionalPrx class]] && + [p3 isKindOfClass:[TestOptionalOneOptionalPrx class]]); + test([p2 isEqual:p1] && [p3 isEqual:p1]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [ICEProxyHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opOneOptionalProxy" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [TestOptionalOneOptionalPrxHelper readOpt:is tag:1]; + p3 = [TestOptionalOneOptionalPrxHelper readOpt:is tag:3]; + [is endEncapsulation]; + test([p2 isKindOfClass:[TestOptionalOneOptionalPrx class]] && + [p3 isKindOfClass:[TestOptionalOneOptionalPrx class]]); + test([p2 isEqual:p1] && [p3 isEqual:p1]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + TestOptionalF* f = [TestOptionalF f]; + f.af = [TestOptionalA a]; + f.af.requiredA = 56; + f.ae = f.af; + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [TestOptionalFHelper writeOpt:f stream:os tag:1]; + [TestOptionalFHelper writeOpt:f.ae stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + + is = [ICEUtil createInputStream:communicator data:inEncaps]; + [is startEncapsulation]; + id a; + [TestOptionalAHelper readOpt:&a stream:is tag:2]; + [is endEncapsulation]; + test(a != nil && [a isKindOfClass:[TestOptionalA class]] && ((TestOptionalA*)a).requiredA == 56); + } + tprintf("ok\n"); + + tprintf("testing optional parameters and sequences... "); + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opByteSeq:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + TestOptionalByteSeq* bs = [TestOptionalMutableByteSeq dataWithLength:100]; + p1 = bs; + p2 = [initial opByteSeq:p1 p3:&p3]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [TestOptionalByteSeqHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opByteSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [TestOptionalByteSeqHelper readOpt:is tag:1]; + p3 = [TestOptionalByteSeqHelper readOpt:is tag:3]; + [is endEncapsulation]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opBoolSeq:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + TestOptionalBoolSeq* bs = [TestOptionalMutableBoolSeq dataWithLength:100]; + p1 = bs; + p2 = [initial opBoolSeq:p1 p3:&p3]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [TestOptionalBoolSeqHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opBoolSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [TestOptionalBoolSeqHelper readOpt:is tag:1]; + p3 = [TestOptionalBoolSeqHelper readOpt:is tag:3]; + [is endEncapsulation]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opShortSeq:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + TestOptionalShortSeq* bs = [TestOptionalMutableShortSeq dataWithLength:100 * sizeof(ICEShort)]; + p1 = bs; + p2 = [initial opShortSeq:p1 p3:&p3]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [TestOptionalShortSeqHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opShortSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [TestOptionalShortSeqHelper readOpt:is tag:1]; + p3 = [TestOptionalShortSeqHelper readOpt:is tag:3]; + [is endEncapsulation]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opIntSeq:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + TestOptionalIntSeq* bs = [TestOptionalMutableIntSeq dataWithLength:100 * sizeof(ICEInt)]; + p1 = bs; + p2 = [initial opIntSeq:p1 p3:&p3]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [TestOptionalIntSeqHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opIntSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [TestOptionalIntSeqHelper readOpt:is tag:1]; + p3 = [TestOptionalIntSeqHelper readOpt:is tag:3]; + [is endEncapsulation]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opLongSeq:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + TestOptionalLongSeq* bs = [TestOptionalMutableLongSeq dataWithLength:100 * sizeof(ICELong)]; + p1 = bs; + p2 = [initial opLongSeq:p1 p3:&p3]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [TestOptionalLongSeqHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opLongSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [TestOptionalLongSeqHelper readOpt:is tag:1]; + p3 = [TestOptionalLongSeqHelper readOpt:is tag:3]; + [is endEncapsulation]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opFloatSeq:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + TestOptionalFloatSeq* bs = [TestOptionalMutableFloatSeq dataWithLength:100 * sizeof(ICEFloat)]; + p1 = bs; + p2 = [initial opFloatSeq:p1 p3:&p3]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [TestOptionalFloatSeqHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opFloatSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [TestOptionalFloatSeqHelper readOpt:is tag:1]; + p3 = [TestOptionalFloatSeqHelper readOpt:is tag:3]; + [is endEncapsulation]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opDoubleSeq:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + TestOptionalDoubleSeq* bs = [TestOptionalMutableDoubleSeq dataWithLength:100 * sizeof(ICEDouble)]; + p1 = bs; + p2 = [initial opDoubleSeq:p1 p3:&p3]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [TestOptionalDoubleSeqHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opDoubleSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [TestOptionalDoubleSeqHelper readOpt:is tag:1]; + p3 = [TestOptionalDoubleSeqHelper readOpt:is tag:3]; + [is endEncapsulation]; + test([p2 isEqual:bs] && [p3 isEqual:bs]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opStringSeq:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + TestOptionalMutableStringSeq* ss = [TestOptionalMutableStringSeq array]; + [ss addObject:@"test1"]; + p1 = ss; + p2 = [initial opStringSeq:p1 p3:&p3]; + test([p2 isEqual:ss] && [p3 isEqual:ss]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [TestOptionalStringSeqHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opStringSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [TestOptionalStringSeqHelper readOpt:is tag:1]; + p3 = [TestOptionalStringSeqHelper readOpt:is tag:3]; + [is endEncapsulation]; + test([p2 isEqual:ss] && [p3 isEqual:ss]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opFixedStructSeq:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + p2 = [initial opFixedStructSeq:[TestOptionalMutableFixedStructSeq array] p3:&p3]; + test(p2 != nil && p3 != nil && [p2 count] == 0 && [p3 count] == 0); + + TestOptionalMutableFixedStructSeq* fss = [TestOptionalMutableFixedStructSeq array]; + [fss addObject:[TestOptionalFixedStruct fixedStruct:1]]; + [fss addObject:[TestOptionalFixedStruct fixedStruct:2]]; + [fss addObject:[TestOptionalFixedStruct fixedStruct:3]]; + [fss addObject:[TestOptionalFixedStruct fixedStruct:4]]; + [fss addObject:[TestOptionalFixedStruct fixedStruct:5]]; + [fss addObject:[TestOptionalFixedStruct fixedStruct:6]]; + [fss addObject:[TestOptionalFixedStruct fixedStruct:7]]; + [fss addObject:[TestOptionalFixedStruct fixedStruct:8]]; + [fss addObject:[TestOptionalFixedStruct fixedStruct:9]]; + [fss addObject:[TestOptionalFixedStruct fixedStruct:10]]; + p1 = fss; + p2 = [initial opFixedStructSeq:p1 p3:&p3]; + test(p2 != nil && p3 != nil); + test([p2 isEqual:fss] && [p3 isEqual:fss]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [TestOptionalFixedStructSeqHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opFixedStructSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [TestOptionalFixedStructSeqHelper readOpt:is tag:1]; + p3 = [TestOptionalFixedStructSeqHelper readOpt:is tag:3]; + [is endEncapsulation]; + test(p2 != nil && p3 != nil); + test([p2 isEqual:fss] && [p3 isEqual:fss]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + { + id p1 = ICENone; + id p3 = ICENone; + id p2 = [initial opVarStructSeq:p1 p3:&p3]; + test(p2 == ICENone && p3 == ICENone); + + p2 = [initial opVarStructSeq:[TestOptionalMutableVarStructSeq array] p3:&p3]; + test(p2 != nil && p3 != nil && [p2 count] == 0 && [p3 count] == 0); + + TestOptionalMutableVarStructSeq* fss = [TestOptionalMutableVarStructSeq array]; + [fss addObject:[TestOptionalVarStruct varStruct:@"1"]]; + [fss addObject:[TestOptionalVarStruct varStruct:@"2"]]; + [fss addObject:[TestOptionalVarStruct varStruct:@"3"]]; + [fss addObject:[TestOptionalVarStruct varStruct:@"4"]]; + [fss addObject:[TestOptionalVarStruct varStruct:@"5"]]; + [fss addObject:[TestOptionalVarStruct varStruct:@"6"]]; + [fss addObject:[TestOptionalVarStruct varStruct:@"7"]]; + [fss addObject:[TestOptionalVarStruct varStruct:@"8"]]; + [fss addObject:[TestOptionalVarStruct varStruct:@"9"]]; + [fss addObject:[TestOptionalVarStruct varStruct:@"10"]]; + p1 = fss; + p2 = [initial opVarStructSeq:p1 p3:&p3]; + test(p2 != nil && p3 != nil); + test([p2 isEqual:fss] && [p3 isEqual:fss]); + + os = [ICEUtil createOutputStream:communicator]; + [os startEncapsulation]; + [TestOptionalVarStructSeqHelper writeOpt:p1 stream:os tag:2]; + [os endEncapsulation]; + inEncaps = [os finished]; + [initial ice_invoke:@"opVarStructSeq" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + p2 = [TestOptionalVarStructSeqHelper readOpt:is tag:1]; + p3 = [TestOptionalVarStructSeqHelper readOpt:is tag:3]; + [is endEncapsulation]; + test(p2 != nil && p3 != nil); + test([p2 isEqual:fss] && [p3 isEqual:fss]); + + is = [ICEUtil createInputStream:communicator data:outEncaps]; + [is startEncapsulation]; + [is endEncapsulation]; + } + + tprintf("ok\n"); + + tprintf("testing exception optionals... "); + { + @try + { + [initial opOptionalException:ICENone b:ICENone o:ICENone]; + test(NO); + } + @catch(TestOptionalOptionalException* ex) + { + test(![ex hasA]); + test(![ex hasB]); + test(![ex hasO]); + } + + @try + { + [initial opOptionalException:@30 b:@"test" o:[TestOptionalOneOptional oneOptional:@53]]; + test(NO); + } + @catch(TestOptionalOptionalException* ex) + { + test(ex.a == 30); + test([ex.b isEqualToString:@"test"]); + test(ex.o.a == 53); + } + + @try + { + // + // Use the 1.0 encoding with an exception whose only class members are optional. + // + [[initial ice_encodingVersion:ICEEncoding_1_0] + opOptionalException:@30 b:@"test" o:[TestOptionalOneOptional oneOptional:@53]]; + test(NO); + } + @catch(TestOptionalOptionalException* ex) + { + test(![ex hasA]); + test(![ex hasB]); + test(![ex hasO]); + } + + @try + { + id a = ICENone; + id b = ICENone; + id o = ICENone; + [initial opDerivedException:a b:b o:o]; + test(NO); + } + @catch(TestOptionalDerivedException* ex) + { + test(![ex hasA]); + test(![ex hasB]); + test(![ex hasO]); + test(![ex hasSs]); + test(![ex hasO2]); + } + @catch(TestOptionalOptionalException* ex) + { + test(NO); + } + + @try + { + id a = @30; + id b = @"test2"; + TestOptionalOneOptional* o = [TestOptionalOneOptional oneOptional:@53]; + [initial opDerivedException:a b:b o:o]; + test(NO); + } + @catch(TestOptionalDerivedException* ex) + { + test(ex.a == 30); + test([ex.b isEqualToString:@"test2"]); + test(ex.o.a == 53); + test([ex.ss isEqualToString:@"test2"]); + test(ex.o2.a == 53); + } + @catch(TestOptionalOptionalException* ex) + { + test(NO); + } + + @try + { + id a = ICENone; + id b = ICENone; + id o = ICENone; + [initial opRequiredException:a b:b o:o]; + test(NO); + } + @catch(TestOptionalRequiredException* ex) + { + test(![ex hasA]); + test(![ex hasB]); + test(![ex hasO]); + test([ex.ss isEqualToString:@"test"]); + } + @catch(TestOptionalOptionalException* ex) + { + test(NO); + } + + @try + { + id a = @30; + id b = @"test2"; + id o = [TestOptionalOneOptional oneOptional:@53]; + [initial opRequiredException:a b:b o:o]; + test(NO); + } + @catch(TestOptionalRequiredException* ex) + { + test(ex.a == 30); + test([ex.b isEqualToString:@"test2"]); + test(ex.o.a == 53); + test([ex.ss isEqualToString:@"test2"]); + test(ex.o2.a == 53); + } + @catch(TestOptionalOptionalException* ex) + { + test(NO); + } + } + tprintf("ok\n"); + + return initial; +} diff --git a/objc/test/Ice/optional/Client.m b/objc/test/Ice/optional/Client.m new file mode 100644 index 00000000000..78a1566d3f0 --- /dev/null +++ b/objc/test/Ice/optional/Client.m @@ -0,0 +1,76 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <OptionalTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + id<TestOptionalInitialPrx> optionalAllTests(id<ICECommunicator>); + id<TestOptionalInitialPrx> optional = optionalAllTests(communicator); + [optional shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main optionalClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestOptional", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/optional/Makefile b/objc/test/Ice/optional/Makefile new file mode 100644 index 00000000000..6a109d52841 --- /dev/null +++ b/objc/test/Ice/optional/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = OptionalTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/optional/OptionalTest.ice b/objc/test/Ice/optional/OptionalTest.ice new file mode 100644 index 00000000000..0d7bf921f37 --- /dev/null +++ b/objc/test/Ice/optional/OptionalTest.ice @@ -0,0 +1,279 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +[["cpp:include:list"]] + +["objc:prefix:TestOptional"] +module Test +{ + +class OneOptional +{ + optional(1) int a; +}; + +enum MyEnum +{ + MyEnumMember +}; + +struct SmallStruct +{ + byte m; +}; + +struct FixedStruct +{ + int m; +}; + +struct VarStruct +{ + string m; +}; + +["cpp:class"] struct ClassVarStruct +{ + int a; +}; + +sequence<byte> ByteSeq; +sequence<bool> BoolSeq; +sequence<short> ShortSeq; +sequence<int> IntSeq; +sequence<long> LongSeq; +sequence<float> FloatSeq; +sequence<double> DoubleSeq; +sequence<string> StringSeq; +sequence<MyEnum> MyEnumSeq; +sequence<SmallStruct> SmallStructSeq; +["cpp:type:std::list< ::Test::SmallStruct>"] sequence<SmallStruct> SmallStructList; +sequence<FixedStruct> FixedStructSeq; +["cpp:type:std::list< ::Test::FixedStruct>"] sequence<FixedStruct> FixedStructList; +sequence<VarStruct> VarStructSeq; +sequence<OneOptional> OneOptionalSeq; +sequence<OneOptional*> OneOptionalPrxSeq; + +sequence<byte> Serializable; + +dictionary<int, int> IntIntDict; +dictionary<string, int> StringIntDict; +dictionary<int, MyEnum> IntEnumDict; +dictionary<int, FixedStruct> IntFixedStructDict; +dictionary<int, VarStruct> IntVarStructDict; +dictionary<int, OneOptional> IntOneOptionalDict; +dictionary<int, OneOptional*> IntOneOptionalPrxDict; + +class MultiOptional +{ + optional(1) byte a; + optional(2) bool b; + optional(3) short c; + optional(4) int d; + optional(5) long e; + optional(6) float f; + optional(7) double g; + optional(8) string h; + optional(9) MyEnum i; + optional(10) MultiOptional* j; + optional(11) MultiOptional k; + optional(12) ByteSeq bs; + optional(13) StringSeq ss; + optional(14) IntIntDict iid; + optional(15) StringIntDict sid; + optional(16) FixedStruct fs; + optional(17) VarStruct vs; + + optional(18) ShortSeq shs; + optional(19) MyEnumSeq es; + optional(20) FixedStructSeq fss; + optional(21) VarStructSeq vss; + optional(22) OneOptionalSeq oos; + optional(23) OneOptionalPrxSeq oops; + + optional(24) IntEnumDict ied; + optional(25) IntFixedStructDict ifsd; + optional(26) IntVarStructDict ivsd; + optional(27) IntOneOptionalDict iood; + optional(28) IntOneOptionalPrxDict ioopd; + + optional(29) BoolSeq bos; + + optional(30) Serializable ser; +}; + +class A +{ + int requiredA = 0; + optional(500) int mc; + optional(50) int mb; + optional(1) int ma; +}; + +["preserve-slice"] +class B extends A +{ + int requiredB = 0; + optional(10) int md; +}; + +class C extends B +{ + string ss; + optional(890) string ms; +}; + +class WD +{ + optional(1) int a = 5; + optional(2) string s = "test"; +}; + +exception OptionalException +{ + bool req = false; + optional(1) int a = 5; + optional(2) string b; + optional(50) OneOptional o; +}; + +exception DerivedException extends OptionalException +{ + optional(600) string ss = "test"; + optional(601) OneOptional o2; +}; + +exception RequiredException extends OptionalException +{ + string ss = "test"; + OneOptional o2; +}; + +class OptionalWithCustom +{ + optional(1) SmallStructList l; + ["protected"] optional(2) SmallStructList lp; + optional(3) ClassVarStruct s; +}; + +class E +{ + A ae; +}; + +class F extends E +{ + optional(1) A af; +}; + +class Initial +{ + void shutdown(); + + Object pingPong(Object o); + + void opOptionalException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + void opDerivedException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + void opRequiredException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + optional(1) byte opByte(optional(2) byte p1, out optional(3) byte p3); + + optional(1) bool opBool(optional(2) bool p1, out optional(3) bool p3); + + optional(1) short opShort(optional(2) short p1, out optional(3) short p3); + + optional(1) int opInt(optional(2) int p1, out optional(3) int p3); + + optional(3) long opLong(optional(1) long p1, out optional(2) long p3); + + optional(1) float opFloat(optional(2) float p1, out optional(3) float p3); + + optional(1) double opDouble(optional(2) double p1, out optional(3) double p3); + + optional(1) string opString(optional(2) string p1, out optional(3) string p3); + + optional(1) MyEnum opMyEnum(optional(2) MyEnum p1, out optional(3) MyEnum p3); + + optional(1) SmallStruct opSmallStruct(optional(2) SmallStruct p1, out optional(3) SmallStruct p3); + + optional(1) FixedStruct opFixedStruct(optional(2) FixedStruct p1, out optional(3) FixedStruct p3); + + optional(1) VarStruct opVarStruct(optional(2) VarStruct p1, out optional(3) VarStruct p3); + + optional(1) OneOptional opOneOptional(optional(2) OneOptional p1, out optional(3) OneOptional p3); + + optional(1) OneOptional* opOneOptionalProxy(optional(2) OneOptional* p1, out optional(3) OneOptional* p3); + + // Custom mapping operations + ["cpp:array"] optional(1) ByteSeq opByteSeq(["cpp:array"] optional(2) ByteSeq p1, + out ["cpp:array"] optional(3) ByteSeq p3); + + ["cpp:array"] optional(1) BoolSeq opBoolSeq(["cpp:array"] optional(2) BoolSeq p1, + out ["cpp:array"] optional(3) BoolSeq p3); + + ["cpp:array"] optional(1) ShortSeq opShortSeq(["cpp:array"] optional(2) ShortSeq p1, + out ["cpp:array"] optional(3) ShortSeq p3); + + ["cpp:range:array"] optional(1) IntSeq opIntSeq(["cpp:range:array"] optional(2) IntSeq p1, + out ["cpp:range:array"] optional(3) IntSeq p3); + + ["cpp:range:array"] optional(1) LongSeq opLongSeq(["cpp:range:array"] optional(2) LongSeq p1, + out ["cpp:range:array"] optional(3) LongSeq p3); + + ["cpp:range:array"] optional(1) FloatSeq opFloatSeq(["cpp:range:array"] optional(2) FloatSeq p1, + out ["cpp:range:array"] optional(3) FloatSeq p3); + + ["cpp:range:array"] optional(1) DoubleSeq opDoubleSeq(["cpp:range:array"] optional(2) DoubleSeq p1, + out ["cpp:range:array"] optional(3) DoubleSeq p3); + + ["cpp:range"] optional(1) StringSeq opStringSeq(["cpp:range"] optional(2) StringSeq p1, + out ["cpp:range"] optional(3) StringSeq p3); + + ["cpp:array"] optional(1) SmallStructSeq opSmallStructSeq(["cpp:array"] optional(2) SmallStructSeq p1, + out ["cpp:array"] optional(3) SmallStructSeq p3); + + ["cpp:array"] optional(1) SmallStructList opSmallStructList(["cpp:array"] optional(2) SmallStructList p1, + out ["cpp:array"] optional(3) SmallStructList p3); + + ["cpp:array"] optional(1) FixedStructSeq opFixedStructSeq(["cpp:array"] optional(2) FixedStructSeq p1, + out ["cpp:array"] optional(3) FixedStructSeq p3); + + ["cpp:array"] optional(1) FixedStructList opFixedStructList(["cpp:array"] optional(2) FixedStructList p1, + out ["cpp:array"] optional(3) FixedStructList p3); + + ["cpp:range"] optional(1) VarStructSeq opVarStructSeq(["cpp:range"] optional(2) VarStructSeq p1, + out ["cpp:range"] optional(3) VarStructSeq p3); + + optional(1) Serializable opSerializable(optional(2) Serializable p1, out optional(3) Serializable p3); + + optional(1) IntIntDict opIntIntDict(optional(2) IntIntDict p1, out optional(3) IntIntDict p3); + + optional(1) StringIntDict opStringIntDict(optional(2) StringIntDict p1, out optional(3) StringIntDict p3); + + void opClassAndUnknownOptional(A p); + + void sendOptionalClass(bool req, optional(1) OneOptional o); + + void returnOptionalClass(bool req, out optional(1) OneOptional o); + + bool supportsRequiredParams(); + + bool supportsJavaSerializable(); + + bool supportsCsharpSerializable(); +}; + +}; diff --git a/objc/test/Ice/optional/Server.m b/objc/test/Ice/optional/Server.m new file mode 100644 index 00000000000..6062cd44604 --- /dev/null +++ b/objc/test/Ice/optional/Server.m @@ -0,0 +1,82 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <optional/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* object = [[[InitialI alloc] init] autorelease]; +#else + ICEObject* object = [[InitialI alloc] init]; +#endif + [adapter add:object identity:[communicator stringToIdentity:@"initial"]]; + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main optionalServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestOptional", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/optional/TestI.h b/objc/test/Ice/optional/TestI.h new file mode 100644 index 00000000000..e4aa3497d7e --- /dev/null +++ b/objc/test/Ice/optional/TestI.h @@ -0,0 +1,18 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <OptionalTest.h> + +@interface InitialI : TestOptionalInitial<TestOptionalInitial> +-(void) shutdown:(ICECurrent *)current; +-(ICEObject*) pingPong:(ICEObject*)obj current:(ICECurrent*)current; +-(BOOL) supportsRequiredParams:(ICECurrent*)current; +-(BOOL) supportsJavaSerializable:(ICECurrent*)current; +-(BOOL) supportsCsharpSerializable:(ICECurrent*)current; +@end diff --git a/objc/test/Ice/optional/TestI.m b/objc/test/Ice/optional/TestI.m new file mode 100644 index 00000000000..17e22e5a471 --- /dev/null +++ b/objc/test/Ice/optional/TestI.m @@ -0,0 +1,239 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <optional/TestI.h> +#import <objc/Ice.h> + +#import <Foundation/NSThread.h> + +@implementation InitialI +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} +-(ICEObject*) pingPong:(ICEObject*)obj current:(ICECurrent*)current +{ + return obj; +} +-(void) opOptionalException:(id)a b:(id)b o:(id)o current:(ICECurrent *)current +{ + @throw [TestOptionalOptionalException optionalException:NO a:a b:b o:o]; +} +-(void) opDerivedException:(id)a b:(id)b o:(id)o current:(ICECurrent *)current +{ + @throw [TestOptionalDerivedException derivedException:NO a:a b:b o:o ss:b o2:o]; +} +-(void) opRequiredException:(id)a b:(id)b o:(id)o current:(ICECurrent *)current +{ + TestOptionalRequiredException* ex = [TestOptionalRequiredException requiredException]; + if(a != ICENone) + { + ex.a = [a intValue]; + } + else + { + [ex clearA]; + } + if(b != ICENone) + { + ex.b = b; + } + else + { + [ex clearB]; + } + if(o != ICENone) + { + ex.o = o; + ex.o2 = o; + } + else + { + [ex clearO]; + } + if(b != ICENone) + { + ex.ss = b; + } + @throw ex; +} +-(id) opByte:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opBool:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opShort:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opInt:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opLong:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opFloat:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opDouble:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opString:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opMyEnum:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opSmallStruct:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opFixedStruct:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opVarStruct:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opOneOptional:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opOneOptionalProxy:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opByteSeq:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opBoolSeq:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opShortSeq:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opIntSeq:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opLongSeq:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opFloatSeq:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opDoubleSeq:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opStringSeq:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opSmallStructSeq:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opSmallStructList:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opFixedStructSeq:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opFixedStructList:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opVarStructSeq:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opSerializable:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opIntIntDict:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(id) opStringIntDict:(id)p1 p3:(id *)p3 current:(ICECurrent *)current +{ + *p3 = p1; + return p1; +} +-(void) opClassAndUnknownOptional:(TestOptionalA *)p current:(ICECurrent *)current +{ +} +-(void) sendOptionalClass:(BOOL)req o:(id)o current:(ICECurrent *)current +{ +} +-(void) returnOptionalClass:(BOOL)req o:(id *)o current:(ICECurrent *)current +{ + *o = [TestOptionalOneOptional oneOptional:@53]; +} +-(BOOL) supportsRequiredParams:(ICECurrent*)current +{ + return NO; +} +-(BOOL) supportsJavaSerializable:(ICECurrent*)current +{ + return NO; +} +-(BOOL) supportsCsharpSerializable:(ICECurrent*)current +{ + return NO; +} + +@end diff --git a/objc/test/Ice/optional/run.py b/objc/test/Ice/optional/run.py new file mode 100755 index 00000000000..a46b2e38375 --- /dev/null +++ b/objc/test/Ice/optional/run.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +print("Running test with compact (default) format.") +TestUtil.clientServerTest() +print("Running test with sliced format.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.SlicedFormat", additionalServerOptions="--Ice.Default.SlicedFormat") diff --git a/objc/test/Ice/proxy/.gitignore b/objc/test/Ice/proxy/.gitignore new file mode 100644 index 00000000000..c2defa1d701 --- /dev/null +++ b/objc/test/Ice/proxy/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +ProxyTest.m +ProxyTest.h diff --git a/objc/test/Ice/proxy/AllTests.m b/objc/test/Ice/proxy/AllTests.m new file mode 100644 index 00000000000..a2760b729eb --- /dev/null +++ b/objc/test/Ice/proxy/AllTests.m @@ -0,0 +1,869 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <ProxyTest.h> + + +TestProxyMyClassPrx* +proxyAllTests(id<ICECommunicator> communicator) +{ + tprintf("testing stringToProxy... "); + NSString* ref = @"test:default -p 12010"; + id<ICEObjectPrx> base = [communicator stringToProxy:ref]; + test(base); + + id<ICEObjectPrx> b1 = [communicator stringToProxy:@"test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getAdapterId] length] == 0 && [[b1 ice_getFacet] length] == 0); + b1 = [communicator stringToProxy:@"test "]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] length] == 0); + b1 = [communicator stringToProxy:@" test "]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] length] == 0); + b1 = [communicator stringToProxy:@" test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] length] == 0); + b1 = [communicator stringToProxy:@"'test -f facet'"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test -f facet"] && + [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] length] == 0); + @try + { + b1 = [communicator stringToProxy:@"\"test -f facet'"]; + test(NO); + } + @catch(ICEProxyParseException*) + { + } + b1 = [communicator stringToProxy:@"\"test -f facet\""]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test -f facet"] && + [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] length] == 0); + b1 = [communicator stringToProxy:@"\"test -f facet@test\""]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test -f facet@test"] && + [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] length] == 0); + b1 = [communicator stringToProxy:@"\"test -f facet@test @test\""]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test -f facet@test @test"] && + [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] length] == 0); + @try + { + b1 = [communicator stringToProxy:@"test test"]; + test(NO); + } + @catch(ICEProxyParseException*) + { + } + b1 = [communicator stringToProxy:@"test\\040test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test test"] && + [[[b1 ice_getIdentity] category] length] == 0); + @try + { + b1 = [communicator stringToProxy:@"test\\777"]; + test(NO); + } + @catch(ICEIdentityParseException*) + { + } + b1 = [communicator stringToProxy:@"test\\40test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test test"]); + + // TestProxy some octal and hex corner cases. + b1 = [communicator stringToProxy:@"test\\4test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test\4test"]); + b1 = [communicator stringToProxy:@"test\\04test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test\4test"]); + b1 = [communicator stringToProxy:@"test\\004test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test\4test"]); + b1 = [communicator stringToProxy:@"test\\1114test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test\1114test"]); + + b1 = [communicator stringToProxy:@"test\\b\\f\\n\\r\\t\\'\\\"\\\\test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test\b\f\n\r\t\'\"\\test"] && + [[[b1 ice_getIdentity] category] length] == 0); + + b1 = [communicator stringToProxy:@"category/test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] isEqualToString:@"category"] && + [[b1 ice_getAdapterId] length] == 0); + + b1 = [communicator stringToProxy:@"test@adapter"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getAdapterId] isEqualToString:@"adapter"]); + @try + { + b1 = [communicator stringToProxy:@"id@adapter test"]; + test(NO); + } + @catch(ICEProxyParseException*) + { + } + b1 = [communicator stringToProxy:@"category/test@adapter"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] isEqualToString:@"category"] && + [[b1 ice_getAdapterId] isEqualToString:@"adapter"]); + b1 = [communicator stringToProxy:@"category/test@adapter:tcp"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] isEqualToString:@"category"] && + [[b1 ice_getAdapterId] isEqualToString:@"adapter:tcp"]); + b1 = [communicator stringToProxy:@"'category 1/test'@adapter"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] isEqualToString:@"category 1"] && + [[b1 ice_getAdapterId] isEqualToString:@"adapter"]); + b1 = [communicator stringToProxy:@"'category/test 1'@adapter"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test 1"] && + [[[b1 ice_getIdentity] category] isEqualToString:@"category"] && + [[b1 ice_getAdapterId] isEqualToString:@"adapter"]); + b1 = [communicator stringToProxy:@"'category/test'@'adapter 1'"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] isEqualToString:@"category"] && + [[b1 ice_getAdapterId] isEqualToString:@"adapter 1"]); + b1 = [communicator stringToProxy:@"\"category \\/test@foo/test\"@adapter"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] isEqualToString:@"category /test@foo"] && + [[b1 ice_getAdapterId] isEqualToString:@"adapter"]); + b1 = [communicator stringToProxy:@"\"category \\/test@foo/test\"@\"adapter:tcp\""]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && + [[[b1 ice_getIdentity] category] isEqualToString:@"category /test@foo"] && + [[b1 ice_getAdapterId] isEqualToString:@"adapter:tcp"]); + + b1 = [communicator stringToProxy:@"id -f facet"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"id"] && [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] isEqualToString:@"facet"]); + b1 = [communicator stringToProxy:@"id -f 'facet x'"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"id"] && [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] isEqualToString:@"facet x"]); + b1 = [communicator stringToProxy:@"id -f \"facet x\""]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"id"] && [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] isEqualToString:@"facet x"]); + @try + { + b1 = [communicator stringToProxy:@"id -f \"facet x"]; + test(NO); + } + @catch(ICEProxyParseException*) + { + } + @try + { + b1 = [communicator stringToProxy:@"id -f \'facet x"]; + test(NO); + } + @catch(ICEProxyParseException*) + { + } + b1 = [communicator stringToProxy:@"test -f facet:tcp"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] isEqualToString:@"facet"] && [[b1 ice_getAdapterId] length] == 0); + b1 = [communicator stringToProxy:@"test -f \"facet:tcp\""]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] isEqualToString:@"facet:tcp"] && [[b1 ice_getAdapterId] length] == 0); + b1 = [communicator stringToProxy:@"test -f facet@test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] isEqualToString:@"facet"] && [[b1 ice_getAdapterId] isEqualToString:@"test"]); + b1 = [communicator stringToProxy:@"test -f 'facet@test'"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] isEqualToString:@"facet@test"] && [[b1 ice_getAdapterId] length] == 0); + b1 = [communicator stringToProxy:@"test -f 'facet@test'@test"]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getFacet] isEqualToString:@"facet@test"] && [[b1 ice_getAdapterId] isEqualToString:@"test"]); + @try + { + b1 = [communicator stringToProxy:@"test -f facet@test @test"]; + test(NO); + } + @catch(ICEProxyParseException*) + { + } + b1 = [communicator stringToProxy:@"test"]; + test([b1 ice_isTwoway]); + b1 = [communicator stringToProxy:@"test -t"]; + test([b1 ice_isTwoway]); + b1 = [communicator stringToProxy:@"test -o"]; + test([b1 ice_isOneway]); + b1 = [communicator stringToProxy:@"test -O"]; + test([b1 ice_isBatchOneway]); + b1 = [communicator stringToProxy:@"test -d"]; + test([b1 ice_isDatagram]); + b1 = [communicator stringToProxy:@"test -D"]; + test([b1 ice_isBatchDatagram]); + b1 = [communicator stringToProxy:@"test"]; + test(![b1 ice_isSecure]); + b1 = [communicator stringToProxy:@"test -s"]; + test([b1 ice_isSecure]); + + test([[b1 ice_getEncodingVersion] isEqual:ICECurrentEncoding]); + + b1 = [communicator stringToProxy:@"test -e 1.0"]; + test([b1 ice_getEncodingVersion].major == 1 && [b1 ice_getEncodingVersion].minor == 0); + + b1 = [communicator stringToProxy:@"test -e 6.5"]; + test([b1 ice_getEncodingVersion].major == 6 && [b1 ice_getEncodingVersion].minor == 5); + + b1 = [communicator stringToProxy:@"test -p 1.0 -e 1.0"]; + test([[b1 ice_toString] isEqualToString:@"test -t -e 1.0"]); + + b1 = [communicator stringToProxy:@"test -p 6.5 -e 1.0"]; + test([[b1 ice_toString] isEqualToString:@"test -t -p 6.5 -e 1.0"]); + + @try + { + b1 = [communicator stringToProxy:@"test:tcp@adapterId"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + // This is an unknown endpoint warning, not a parse exception. + // + //try + //{ + // b1 = [communicator stringToProxy:@"test -f the:facet:tcp"]; + // test(NO); + //} + //catch(ICEEndpointParseException*) + //{ + //} + @try + { + b1 = [communicator stringToProxy:@"test::tcp"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + tprintf("ok\n"); + + tprintf("testing propertyToProxy... "); + id<ICEProperties> prop = [communicator getProperties]; + NSString* propertyPrefix = @"Foo.Proxy"; + [prop setProperty:propertyPrefix value:@"test:default -p 12010"]; + b1 = [communicator propertyToProxy:propertyPrefix]; + test([[[b1 ice_getIdentity] name] isEqualToString:@"test"] && [[[b1 ice_getIdentity] category] length] == 0 && + [[b1 ice_getAdapterId] length] == 0 && [[b1 ice_getFacet] length] == 0); + + NSString* property; + + property = [propertyPrefix stringByAppendingString:@".Locator"]; + test(![b1 ice_getLocator]); + [prop setProperty:property value:@"locator:default -p 10000"]; + b1 = [communicator propertyToProxy:propertyPrefix]; + test([b1 ice_getLocator] && [[[[b1 ice_getLocator] ice_getIdentity] name] isEqualToString:@"locator"]); + [prop setProperty:property value:@""]; + + property = [propertyPrefix stringByAppendingString:@".LocatorCacheTimeout"]; + test([b1 ice_getLocatorCacheTimeout] == -1); + [prop setProperty:property value:@"1"]; + b1 = [communicator propertyToProxy:propertyPrefix]; + test([b1 ice_getLocatorCacheTimeout] == 1); + [prop setProperty:property value:@""]; + + // Now retest with an indirect proxy. + [prop setProperty:propertyPrefix value:@"test"]; + property = [propertyPrefix stringByAppendingString:@".Locator"]; + [prop setProperty:property value:@"locator:default -p 10000"]; + b1 = [communicator propertyToProxy:propertyPrefix]; + test([b1 ice_getLocator] && [[[[b1 ice_getLocator] ice_getIdentity] name] isEqualToString:@"locator"]); + [prop setProperty:property value:@""]; + + property = [propertyPrefix stringByAppendingString:@".LocatorCacheTimeout"]; + test([b1 ice_getLocatorCacheTimeout] == -1); + [prop setProperty:property value:@"1"]; + b1 = [communicator propertyToProxy:propertyPrefix]; + test([b1 ice_getLocatorCacheTimeout] == 1); + [prop setProperty:property value:@""]; + + // This cannot be tested so easily because the property is cached + // on communicator initialization. + // + //prop->setProperty:"Ice.Default.LocatorCacheTimeout" :@"60"); + //b1 = [communicator propertyToProxy:propertyPrefix]; + //test([b1 ice_getLocatorCacheTimeout] == 60); + //prop->setProperty("Ice.Default.LocatorCacheTimeout" :@""); + + [prop setProperty:propertyPrefix value:@"test:default -p 12010"]; + + property = [propertyPrefix stringByAppendingString:@".Router"]; + test(![b1 ice_getRouter]); + [prop setProperty:property value:@"router:default -p 10000"]; + b1 = [communicator propertyToProxy:propertyPrefix]; + test([b1 ice_getRouter] && [[[[b1 ice_getRouter] ice_getIdentity] name] isEqualToString:@"router"]); + [prop setProperty:property value:@""]; + + property = [propertyPrefix stringByAppendingString:@".PreferSecure"]; + test(![b1 ice_isPreferSecure]); + [prop setProperty:property value:@"1"]; + b1 = [communicator propertyToProxy:propertyPrefix]; + test([b1 ice_isPreferSecure]); + [prop setProperty:property value:@""]; + + property = [propertyPrefix stringByAppendingString:@".ConnectionCached"]; + test([b1 ice_isConnectionCached]); + [prop setProperty:property value:@"0"]; + b1 = [communicator propertyToProxy:propertyPrefix]; + test(![b1 ice_isConnectionCached]); + [prop setProperty:property value:@""]; + + property = [propertyPrefix stringByAppendingString:@".EndpointSelection"]; + test([b1 ice_getEndpointSelection] == ICERandom); + [prop setProperty:property value:@"Random"]; + b1 = [communicator propertyToProxy:propertyPrefix]; + test([b1 ice_getEndpointSelection] == ICERandom); + [prop setProperty:property value:@"Ordered"]; + b1 = [communicator propertyToProxy:propertyPrefix]; + test([b1 ice_getEndpointSelection] == ICEOrdered); + [prop setProperty:property value:@""]; + +// property = [propertyPrefix stringByAppendingString:@".CollocationOptimized"]; +// test([b1 ice_isCollocationOptimized]); +// [prop setProperty:property value:@"0"]; +// b1 = [communicator propertyToProxy:propertyPrefix]; +// test(![b1 ice_isCollocationOptimized]); +// [prop setProperty:property value:@""]; + + tprintf("ok\n"); + + tprintf("testing proxyToProperty... "); + + b1 = [communicator stringToProxy:@"test"]; + //b1 = [b1 ice_collocationOptimized:YES]; + b1 = [b1 ice_connectionCached:YES]; + b1 = [b1 ice_preferSecure:false]; + b1 = [b1 ice_endpointSelection:ICEOrdered]; + b1 = [b1 ice_locatorCacheTimeout:100]; + ICEEncodingVersion* v = [ICEEncodingVersion encodingVersion:1 minor:0]; + b1 = [b1 ice_encodingVersion:v]; + id<ICEObjectPrx> router = [communicator stringToProxy:@"router"]; + //router = [router ice_collocationOptimized:false]; + router = [router ice_connectionCached:YES]; + router = [router ice_preferSecure:YES]; + router = [router ice_endpointSelection:ICERandom]; + router = [router ice_locatorCacheTimeout:200]; + + id<ICEObjectPrx> locator = [communicator stringToProxy:@"locator"]; + //locator = [locator ice_collocationOptimized:YES]; + locator = [locator ice_connectionCached:false]; + locator = [locator ice_preferSecure:YES]; + locator = [locator ice_endpointSelection:ICERandom]; + locator = [locator ice_locatorCacheTimeout:300]; + + locator = [locator ice_router:[ICERouterPrx uncheckedCast:router]]; + b1 = [b1 ice_locator:[ICELocatorPrx uncheckedCast:locator]]; + + ICEMutablePropertyDict* proxyProps = [communicator proxyToProperty:b1 property:@"Test"]; + test([proxyProps count] == 21); + + test([[proxyProps objectForKey:@"Test"] isEqualToString:@"test -t -e 1.0"]); + //test([[proxyProps[ objectForKey:@"Test.CollocationOptimized"] isEqualToString:@"1"]); + test([[proxyProps objectForKey:@"Test.ConnectionCached"] isEqualToString:@"1"]); + test([[proxyProps objectForKey:@"Test.PreferSecure"] isEqualToString:@"0"]); + test([[proxyProps objectForKey:@"Test.EndpointSelection"] isEqualToString:@"Ordered"]); + test([[proxyProps objectForKey:@"Test.LocatorCacheTimeout"] isEqualToString:@"100"]); + + NSString* sl = [NSString stringWithFormat:@"locator -t -e %@", [ICECurrentEncoding description]]; + test([[proxyProps objectForKey:@"Test.Locator"] isEqualToString:sl]); + //test([[proxyProps objectForKey:@"Test.Locator.CollocationOptimized"] isEqualToString:@"1"]); + test([[proxyProps objectForKey:@"Test.Locator.ConnectionCached"] isEqualToString:@"0"]); + test([[proxyProps objectForKey:@"Test.Locator.PreferSecure"] isEqualToString:@"1"]); + test([[proxyProps objectForKey:@"Test.Locator.EndpointSelection"] isEqualToString:@"Random"]); + test([[proxyProps objectForKey:@"Test.Locator.LocatorCacheTimeout"] isEqualToString:@"300"]); + + NSString* sr = [NSString stringWithFormat:@"router -t -e %@", [ICECurrentEncoding description]]; + test([[proxyProps objectForKey:@"Test.Locator.Router"] isEqualToString:sr]); + //test([proxyProps objectForKey:@"Test.Locator.Router.CollocationOptimized"] isEqualToString:@"0"]); + test([[proxyProps objectForKey:@"Test.Locator.Router.ConnectionCached"] isEqualToString:@"1"]); + test([[proxyProps objectForKey:@"Test.Locator.Router.PreferSecure"] isEqualToString:@"1"]); + test([[proxyProps objectForKey:@"Test.Locator.Router.EndpointSelection"] isEqualToString:@"Random"]); + test([[proxyProps objectForKey:@"Test.Locator.Router.LocatorCacheTimeout"] isEqualToString:@"200"]); + + tprintf("ok\n"); + + tprintf("testing ice_getCommunicator... "); + test([base ice_getCommunicator] == communicator); + tprintf("ok\n"); + + tprintf("testing proxy methods... "); + test([[communicator identityToString:[[base ice_identity:[communicator stringToIdentity:@"other"]] ice_getIdentity]] + isEqualToString:@"other"]); + test([[[base ice_facet:@"facet"] ice_getFacet] isEqualToString:@"facet"]); + test([[[base ice_adapterId:@"id"] ice_getAdapterId] isEqualToString:@"id"]); + test([[base ice_twoway] ice_isTwoway]); + test([[base ice_oneway] ice_isOneway]); + test([[base ice_batchOneway] ice_isBatchOneway]); + test([[base ice_datagram] ice_isDatagram]); + test([[base ice_batchDatagram] ice_isBatchDatagram]); + test([[base ice_secure:YES] ice_isSecure]); + test(![[base ice_secure:NO] ice_isSecure]); +// test([[base ice_collocationOptimized:YES] ice_isCollocationOptimized]); +// test(![[base ice_collocationOptimized:NO] ice_isCollocationOptimized]); + test([[base ice_preferSecure:YES] ice_isPreferSecure]); + test(![[base ice_preferSecure:NO] ice_isPreferSecure]); + + test([[[base ice_encodingVersion:ICEEncoding_1_0] ice_getEncodingVersion] isEqual:ICEEncoding_1_0]); + test([[[base ice_encodingVersion:ICEEncoding_1_1] ice_getEncodingVersion] isEqual:ICEEncoding_1_1]); + test(![[[base ice_encodingVersion:ICEEncoding_1_0] ice_getEncodingVersion] isEqual:ICEEncoding_1_1]); + + tprintf("ok\n"); + + tprintf("testing proxy comparison... "); + + test([[communicator stringToProxy:@"foo"] isEqual:[communicator stringToProxy:@"foo"]]); + test(![[communicator stringToProxy:@"foo"] isEqual:[communicator stringToProxy:@"foo2"]]); +// test([communicator stringToProxy:@"foo"]] < [communicator stringToProxy:@"foo2"]); +// test(!([communicator stringToProxy:@"foo2"]] < [communicator stringToProxy:@"foo"]); + + id<ICEObjectPrx> compObj = [communicator stringToProxy:@"foo"]; + + test([[compObj ice_facet:@"facet"] isEqual:[compObj ice_facet:@"facet"]]); + test(![[compObj ice_facet:@"facet"] isEqual:[compObj ice_facet:@"facet1"]]); +// test([compObj ice_facet:@"facet"] < [compObj ice_facet:"facet1"]); +// test(!([compObj ice_facet:@"facet"] < [compObj ice_facet:"facet"])); + + test([[compObj ice_oneway] isEqual:[compObj ice_oneway]]); + test(![[compObj ice_oneway] isEqual:[compObj ice_twoway]]); +// test([compObj ice_twoway] < [compObj ice_oneway]); +// test(!([compObj ice_oneway] < [compObj ice_twoway])); + + test([[compObj ice_secure:YES] isEqual:[compObj ice_secure:YES]]); + test(![[compObj ice_secure:NO] isEqual:[compObj ice_secure:YES]]); +// test([compObj ice_secure:NO] < [compObj ice_secure:YES]); +// test(!([compObj ice_secure:YES] < [compObj ice_secure:NO])); + +// test([[compObj ice_collocationOptimized:YES] isEqual:[compObj ice_collocationOptimized:YES]]); +// test(![[compObj ice_collocationOptimized:NO] isEqual:[compObj ice_collocationOptimized:YES]]); +// test([compObj ice_collocationOptimized:NO] < [compObj ice_collocationOptimized:YES]); +// test(!([compObj ice_collocationOptimized:YES] < [compObj ice_collocationOptimized:NO])); + + test([[compObj ice_connectionCached:YES] isEqual:[compObj ice_connectionCached:YES]]); + test(![[compObj ice_connectionCached:NO] isEqual:[compObj ice_connectionCached:YES]]); +// test([compObj ice_connectionCached:NO] < [compObj ice_connectionCached:YES]); +// test(!([compObj ice_connectionCached:YES] < [compObj ice_connectionCached:NO])); + + test([[compObj ice_endpointSelection:ICERandom] isEqual:[compObj ice_endpointSelection:ICERandom]]); + test(![[compObj ice_endpointSelection:ICERandom] isEqual:[compObj ice_endpointSelection:ICEOrdered]]); +// test([compObj ice_endpointSelection:ICERandom] < [compObj ice_endpointSelection:ICEOrdered]); +// test(!([compObj ice_endpointSelection:ICEOrdered] < [compObj ice_endpointSelection:ICERandom])); + +// test([[compObj ice_connectionId:@"id2"] isEqual:[compObj ice_connectionId:@"id2"]]); +// test(![[compObj ice_connectionId:@"id1"] isEqual:[compObj ice_connectionId:@"id2"]]); +// test([compObj ice_connectionId:@"id1"] < [compObj ice_connectionId:"id2"]); +// test(!([compObj ice_connectionId:@"id2"] < [compObj ice_connectionId:"id1"])); + + test([[compObj ice_compress:YES] isEqual:[compObj ice_compress:YES]]); + test(![[compObj ice_compress:NO] isEqual:[compObj ice_compress:YES]]); +// test([compObj ice_compress:NO] < [compObj ice_compress:YES]); +// test(!([compObj ice_compress:YES] < [compObj ice_compress:NO])); + + test([[compObj ice_timeout:20] isEqual:[compObj ice_timeout:20]]); + test(![[compObj ice_timeout:10] isEqual:[compObj ice_timeout:20]]); +// test([compObj ice_timeout:10] < [compObj ice_timeout:20]); +// test(!([compObj ice_timeout:20] < [compObj ice_timeout:10])); + + id<ICELocatorPrx> loc1 = [ICELocatorPrx uncheckedCast:[communicator stringToProxy:@"loc1:default -p 10000"]]; + id<ICELocatorPrx> loc2 = [ICELocatorPrx uncheckedCast:[communicator stringToProxy:@"loc2:default -p 10000"]]; + test([[compObj ice_locator:0] isEqual:[compObj ice_locator:0]]); + test([[compObj ice_locator:loc1] isEqual:[compObj ice_locator:loc1]]); + test(![[compObj ice_locator:loc1] isEqual:[compObj ice_locator:0]]); + test(![[compObj ice_locator:0] isEqual:[compObj ice_locator:loc2]]); + test(![[compObj ice_locator:loc1] isEqual:[compObj ice_locator:loc2]]); +// test([compObj ice_locator:0] < [compObj ice_locator:loc1]); +// test(!([compObj ice_locator:loc1] < [compObj ice_locator:0])); +// test([compObj ice_locator:loc1] < [compObj ice_locator:loc2]); +// test(!([compObj ice_locator:loc2] < [compObj ice_locator:loc1])); + + id<ICERouterPrx> rtr1 = [ICERouterPrx uncheckedCast:[communicator stringToProxy:@"rtr1:default -p 10000"]]; + id<ICERouterPrx> rtr2 = [ICERouterPrx uncheckedCast:[communicator stringToProxy:@"rtr2:default -p 10000"]]; + test([[compObj ice_router:0] isEqual:[compObj ice_router:0]]); + test([[compObj ice_router:rtr1] isEqual:[compObj ice_router:rtr1]]); + test(![[compObj ice_router:rtr1] isEqual:[compObj ice_router:0]]); + test(![[compObj ice_router:0] isEqual:[compObj ice_router:rtr2]]); + test(![[compObj ice_router:rtr1] isEqual:[compObj ice_router:rtr2]]); +// test([compObj ice_router:0] < [compObj ice_router:rtr1]); +// test(!([compObj ice_router:rtr1] < [compObj ice_router:0])); +// test([compObj ice_router:rtr1] < [compObj ice_router:rtr2]); +// test(!([compObj ice_router:rtr2] < [compObj ice_router:rtr1])); + + ICEMutableContext* ctx1 = [ICEMutableContext dictionary]; + [ctx1 setObject:@"v1" forKey:@"ctx1"]; + ICEMutableContext* ctx2 = [ICEMutableContext dictionary]; + [ctx2 setObject:@"v2" forKey:@"ctx2"]; + test([[compObj ice_context:nil] isEqual:[compObj ice_context:nil]]); + test([[compObj ice_context:ctx1] isEqual:[compObj ice_context:ctx1]]); + test(![[compObj ice_context:ctx1] isEqual:[compObj ice_context:nil]]); + test(![[compObj ice_context:nil] isEqual:[compObj ice_context:ctx2]]); + test(![[compObj ice_context:ctx1] isEqual:[compObj ice_context:ctx2]]); +// test([compObj ice_context:ctx1] < [compObj ice_context:ctx2]); +// test(!([compObj ice_context:ctx2] < [compObj ice_context:ctx1])); + + test([[compObj ice_preferSecure:YES] isEqual:[compObj ice_preferSecure:YES]]); + test(![[compObj ice_preferSecure:YES] isEqual:[compObj ice_preferSecure:NO]]); +// test([compObj ice_preferSecure:NO] < [compObj ice_preferSecure:YES]); +// test(!([compObj ice_preferSecure:YES] < [compObj ice_preferSecure:NO])); + + id<ICEObjectPrx> compObj1 = [communicator stringToProxy:@"foo:tcp -h 127.0.0.1 -p 10000"]; + id<ICEObjectPrx> compObj2 = [communicator stringToProxy:@"foo:tcp -h 127.0.0.1 -p 10001"]; + test(![compObj isEqual:compObj2]); +// test(compObj1 < compObj2); +// test(!(compObj2 < compObj1)); + + compObj1 = [communicator stringToProxy:@"foo@MyAdapter1"]; + compObj2 = [communicator stringToProxy:@"foo@MyAdapter2"]; + test(![compObj isEqual:compObj2]); +// test(compObj1 < compObj2); +// test(!(compObj2 < compObj1)); + + test([[compObj1 ice_locatorCacheTimeout:20] isEqual:[compObj1 ice_locatorCacheTimeout:20]]); + test(![[compObj1 ice_locatorCacheTimeout:10] isEqual:[compObj1 ice_locatorCacheTimeout:20]]); +// test([compObj1 ice_locatorCacheTimeout:10] < [compObj1 ice_locatorCacheTimeout:20]); +// test(!([compObj1 ice_locatorCacheTimeout:20] < [compObj1 ice_locatorCacheTimeout:10])); + + compObj1 = [communicator stringToProxy:@"foo:tcp -h 127.0.0.1 -p 1000"]; + compObj2 = [communicator stringToProxy:@"foo@MyAdapter1"]; + test(![compObj isEqual:compObj2]); +// test(compObj1 < compObj2); +// test(!(compObj2 < compObj1)); + + test([[compObj1 ice_encodingVersion:ICEEncoding_1_0] isEqual:[compObj1 ice_encodingVersion:ICEEncoding_1_0]]); + test(![[compObj1 ice_encodingVersion:ICEEncoding_1_0] isEqual:[compObj1 ice_encodingVersion:ICEEncoding_1_1]]); + +// test(compObj ice_encodingVersion:Ice::Encoding_1_0] < compObj->ice_encodingVersion(Ice::Encoding_1_1)); +// test(!(compObj->ice_encodingVersion(Ice::Encoding_1_1) < compObj->ice_encodingVersion(Ice::Encoding_1_0))); + // + // TODO: Ideally we should also test comparison of fixed proxies. + // + + tprintf("ok\n"); + + tprintf("testing checked cast... "); + id<TestProxyMyClassPrx> cl = [TestProxyMyClassPrx checkedCast:base]; + test(cl); + + id<TestProxyMyDerivedClassPrx> derived = [TestProxyMyDerivedClassPrx checkedCast:cl]; + test(derived); + test([cl isEqual:base]); + test([derived isEqual:base]); + test([cl isEqual:derived]); + + id<ICELocatorPrx> loc = [ICELocatorPrx checkedCast:base]; + test(loc == nil); + + // + // Upcasting + // + id<TestProxyMyClassPrx> cl2 = [TestProxyMyClassPrx checkedCast:derived]; + id<ICEObjectPrx> obj = [ICEObjectPrx checkedCast:derived]; + test(cl2); + test(obj); + test([cl2 isEqual:obj]); + test([cl2 isEqual:derived]); + + tprintf("ok\n"); + + tprintf("testing checked cast with context... "); + ICEMutableContext* c = [cl getContext]; + test([c count] == 0); + + [c setObject:@"hello" forKey:@"one"]; + [c setObject:@"world" forKey:@"two"]; + cl = [TestProxyMyClassPrx checkedCast:base context:c]; + ICEContext* c2 = [cl getContext]; + test([c isEqual:c2]); + + tprintf("ok\n"); + + tprintf("testing encoding versioning... "); + TestProxyMyClassPrx* cl20 = [TestProxyMyClassPrx uncheckedCast: + [communicator stringToProxy:@"test -e 2.0:default -p 12010"]]; + @try + { + [cl20 ice_ping]; + test(NO); + } + @catch(ICEUnsupportedEncodingException*) + { + // Server 2.0 endpoint doesn't support 1.1 version. + } + + TestProxyMyClassPrx* cl10 = [TestProxyMyClassPrx uncheckedCast: + [communicator stringToProxy:@"test -e 1.0:default -p 12010"]]; + [cl10 ice_ping]; + [[cl10 ice_encodingVersion:ICEEncoding_1_0] ice_ping]; + //cl->ice_collocationOptimized(false)->ice_encodingVersion(Ice::Encoding_1_0)->ice_ping(); + + // 1.3 isn't supported but since a 1.3 proxy supports 1.1, the + // call will use the 1.1 encoding + TestProxyMyClassPrx* cl13 = [TestProxyMyClassPrx uncheckedCast: + [communicator stringToProxy:@"test -e 1.3:default -p 12010"]]; + [cl13 ice_ping]; + [cl13 end_ice_ping:[cl13 begin_ice_ping]]; + + @try + { + // Send request with bogus 1.2 encoding. + ICEEncodingVersion* version = [ICEEncodingVersion encodingVersion:1 minor:2]; + id<ICEOutputStream> out = [ICEUtil createOutputStream:communicator]; + [out startEncapsulation]; + [out endEncapsulation]; + NSMutableData* inEncaps = [out finished]; + ((ICEByte*)[inEncaps mutableBytes])[4] = version.major; + ((ICEByte*)[inEncaps mutableBytes])[5] = version.minor; + NSMutableData* outEncaps; + [cl ice_invoke:@"ice_ping" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + test(NO); + } + @catch(ICEUnknownLocalException* ex) + { + // The server threw an UnsupportedEncodingException + test([ex.unknown rangeOfString:@"UnsupportedEncodingException"].location != NSNotFound); + } + + @try + { + // Send request with bogus 2.0 encoding. + ICEEncodingVersion* version = [ICEEncodingVersion encodingVersion:2 minor:0]; + id<ICEOutputStream> out = [ICEUtil createOutputStream:communicator]; + [out startEncapsulation]; + [out endEncapsulation]; + NSMutableData* inEncaps = [out finished]; + ((ICEByte*)[inEncaps mutableBytes])[4] = version.major; + ((ICEByte*)[inEncaps mutableBytes])[5] = version.minor; + NSMutableData* outEncaps; + [cl ice_invoke:@"ice_ping" mode:ICENormal inEncaps:inEncaps outEncaps:&outEncaps]; + test(NO); + } + @catch(ICEUnknownLocalException* ex) + { + // The server thrown an UnsupportedEncodingException + test([ex.unknown rangeOfString:@"UnsupportedEncodingException"].location != NSNotFound); + } + + tprintf("ok\n"); + + tprintf("testing protocol versioning... "); + + cl20 = [TestProxyMyClassPrx uncheckedCast:[communicator stringToProxy:@"test -p 2.0:default -p 12010"]]; + @try + { + [cl20 ice_ping]; + test(NO); + } + @catch(ICEUnsupportedProtocolException*) + { + // Server 2.0 proxy doesn't support 1.0 version. + } + + cl10 = [TestProxyMyClassPrx uncheckedCast:[communicator stringToProxy:@"test -p 1.0:default -p 12010"]]; + [cl10 ice_ping]; + + // 1.3 isn't supported but since a 1.3 proxy supports 1.0, the + // call will use the 1.0 encoding + cl13 = [TestProxyMyClassPrx uncheckedCast:[communicator stringToProxy:@"test -p 1.3:default -p 12010"]]; + [cl13 ice_ping]; + [cl13 end_ice_ping:[cl13 begin_ice_ping]]; + + tprintf("ok\n"); + + tprintf("testing opaque endpoints... "); + + @try + { + // Invalid -x option + [communicator stringToProxy:@"id:opaque -t 99 -v abc -x abc"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + + @try + { + // Missing -t and -v + [communicator stringToProxy:@"id:opaque"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + + @try + { + // Repeated -t + [communicator stringToProxy:@"id:opaque -t 1 -t 1 -v abc"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + + @try + { + // Repeated -v + [communicator stringToProxy:@"id:opaque -t 1 -v abc -v abc"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + + @try + { + // Missing -t + [communicator stringToProxy:@"id:opaque -v abc"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + + @try + { + // Missing -v + [communicator stringToProxy:@"id:opaque -t 1"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + + @try + { + // Missing arg for -t + [communicator stringToProxy:@"id:opaque -t -v abc"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + + @try + { + // Missing arg for -v + [communicator stringToProxy:@"id:opaque -t 1 -v"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + + @try + { + // Not a number for -t + [communicator stringToProxy:@"id:opaque -t x -v abc"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + + @try + { + // < 0 for -t + [communicator stringToProxy:@"id:opaque -t -1 -v abc"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + + @try + { + // Invalid char for -v + [communicator stringToProxy:@"id:opaque -t 99 -v x?c"]; + test(NO); + } + @catch(ICEEndpointParseException*) + { + } + + // Legal TCP endpoint expressed as opaque endpoint + id<ICEObjectPrx> p1 = [communicator stringToProxy:@"test -e 1.1:opaque -t 1 -v CTEyNy4wLjAuMeouAAAQJwAAAA=="]; + NSString* pstr = [communicator proxyToString:p1]; + test([pstr isEqualToString:@"test -t -e 1.1:tcp -h 127.0.0.1 -p 12010 -t 10000"]); + + if([[communicator getProperties] getPropertyAsInt:@"Ice.IPv6"] == 0) + { + // Working? + BOOL ssl = [[[communicator getProperties] getProperty:@"Ice.Default.Protocol"] isEqualToString:@"ssl"]; + if(!ssl) + { + [p1 ice_ping]; + } + + // Two legal TCP endpoints expressed as opaque endpoints + p1 = [communicator stringToProxy:@"test -e 1.0:opaque -t 1 -v CTEyNy4wLjAuMeouAAAQJwAAAA==:opaque -e 1.0 -t 1 -v CTEyNy4wLjAuMusuAAAQJwAAAA=="]; + pstr = [communicator proxyToString:p1]; + test([pstr isEqualToString:@"test -t -e 1.0:tcp -h 127.0.0.1 -p 12010 -t 10000:tcp -h 127.0.0.2 -p 12011 -t 10000"]); + +#if 0 // SSL is always enabled + // + // TestProxy that an SSL endpoint and a nonsense endpoint get written + // back out as an opaque endpoint. + // + p1 = [communicator stringToProxy:@"test:opaque -t 2 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -v abch"]; + pstr = [communicator proxyToString:p1]; + if(!ssl) + { + test([pstr isEqualToString:@"test -t:opaque -t 2 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -v abch"]); + } + else + { + test([pstr isEqualToString:@"test -t:ssl -h 127.0.0.1 -p 10001:opaque -t 99 -v abch"]); + } + + // + // Try to invoke on the SSL endpoint to verify that we get a + // NoEndpointException (or ConnectionRefusedException when + // running with SSL). + // + @try + { + [p1 ice_ping]; + test(NO); + } + @catch(ICENoEndpointException*) + { + test(!ssl); + } + @catch(ICEConnectionRefusedException*) + { + test(ssl); + } + + // + // TestProxy that the proxy with an SSL endpoint and a nonsense + // endpoint (which the server doesn't understand either) can be + // sent over the wire and returned by the server without losing + // the opaque endpoints. + // + id<ICEObjectPrx> p2 = [derived echo:p1]; + pstr = [communicator proxyToString:p2]; + if(!ssl) + { + test([pstr isEqualToString:@"test -t:opaque -t 2 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -v abch"]); + } + else + { + test([pstr isEqualToString:@"test -t:ssl -h 127.0.0.1 -p 10001:opaque -t 99 -v abch"]); + } +#endif + } + + tprintf("ok\n"); + + return cl; +} diff --git a/objc/test/Ice/proxy/Client.m b/objc/test/Ice/proxy/Client.m new file mode 100644 index 00000000000..a1854dc6bdb --- /dev/null +++ b/objc/test/Ice/proxy/Client.m @@ -0,0 +1,79 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <ProxyTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + TestProxyMyClassPrx* proxyAllTests(id<ICECommunicator>); + TestProxyMyClassPrx* myClass = proxyAllTests(communicator); + + [myClass shutdown]; + + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main proxyClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestProxy", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/proxy/Makefile b/objc/test/Ice/proxy/Makefile new file mode 100644 index 00000000000..86fab9f027d --- /dev/null +++ b/objc/test/Ice/proxy/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = ProxyTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/proxy/ProxyTest.ice b/objc/test/Ice/proxy/ProxyTest.ice new file mode 100644 index 00000000000..5a915876920 --- /dev/null +++ b/objc/test/Ice/proxy/ProxyTest.ice @@ -0,0 +1,30 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Ice/Current.ice> + +["objc:prefix:TestProxy"] +module Test +{ + +class MyClass +{ + void shutdown(); + + Ice::Context getContext(); +}; + +class MyDerivedClass extends MyClass +{ + Object* echo(Object* obj); +}; + +}; diff --git a/objc/test/Ice/proxy/Server.m b/objc/test/Ice/proxy/Server.m new file mode 100644 index 00000000000..cc2fd0fb1ee --- /dev/null +++ b/objc/test/Ice/proxy/Server.m @@ -0,0 +1,84 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <proxy/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010:udp"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + [adapter add:[[[TestProxyMyDerivedClassI alloc] init] autorelease] + identity:[communicator stringToIdentity:@"test"]]; +#else + [adapter add:[[TestProxyMyDerivedClassI alloc] init] identity:[communicator stringToIdentity:@"test"]]; +#endif + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main proxyServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + 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: + @"TestProxy", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/proxy/TestI.h b/objc/test/Ice/proxy/TestI.h new file mode 100644 index 00000000000..02b6cbcea1b --- /dev/null +++ b/objc/test/Ice/proxy/TestI.h @@ -0,0 +1,21 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <ProxyTest.h> + +@interface TestProxyMyDerivedClassI : TestProxyMyDerivedClass<TestProxyMyDerivedClass> +{ +@private + ICEContext *_ctx; +} +-(id<ICEObjectPrx>) echo:(id<ICEObjectPrx>)proxy current:(ICECurrent*)current; +-(void) shutdown:(ICECurrent*)current; +-(ICEContext*) getContext:(ICECurrent*)current; +-(BOOL) ice_isA:(NSString*)typeId current:(ICECurrent*)current; +@end diff --git a/objc/test/Ice/proxy/TestI.m b/objc/test/Ice/proxy/TestI.m new file mode 100644 index 00000000000..0ed9e270219 --- /dev/null +++ b/objc/test/Ice/proxy/TestI.m @@ -0,0 +1,53 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <proxy/TestI.h> +#import <TestCommon.h> + +@implementation TestProxyMyDerivedClassI +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [_ctx release]; + [super dealloc]; +} +#endif + +-(id<ICEObjectPrx>) echo:(id<ICEObjectPrx>)obj current:(ICECurrent*)current +{ + return obj; +} + +-(void) shutdown:(ICECurrent*)c +{ + [[[c adapter] getCommunicator] shutdown]; +} + +-(ICEContext*) getContext:(ICECurrent*)c +{ +#if defined(__clang__) && !__has_feature(objc_arc) + return [[_ctx retain] autorelease]; +#else + return _ctx; +#endif +} + +-(BOOL) ice_isA:(NSString*)s current:(ICECurrent*)current +{ +#if defined(__clang__) && !__has_feature(objc_arc) + [_ctx release]; + _ctx = [[current ctx] retain]; +#else + _ctx = [current ctx]; +#endif + return [super ice_isA:s current:current]; +} + +@end diff --git a/objc/test/Ice/proxy/run.py b/objc/test/Ice/proxy/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/proxy/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/retry/.gitignore b/objc/test/Ice/retry/.gitignore new file mode 100644 index 00000000000..c69a35a62bd --- /dev/null +++ b/objc/test/Ice/retry/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +RetryTest.m +RetryTest.h diff --git a/objc/test/Ice/retry/AllTests.m b/objc/test/Ice/retry/AllTests.m new file mode 100644 index 00000000000..3b47e02f7cd --- /dev/null +++ b/objc/test/Ice/retry/AllTests.m @@ -0,0 +1,147 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <RetryTest.h> + +#import <Foundation/Foundation.h> + +@interface TestRetryCallback : NSObject +{ + BOOL called; + NSCondition* cond; +} +-(void) check; +-(void) called; +@end + +@implementation TestRetryCallback +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + cond = [[NSCondition alloc] init]; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [super dealloc]; +} +#endif + +-(void) check +{ + [cond lock]; + while(!called) + { + [cond wait]; + } + called = NO; + [cond unlock]; +} +-(void) called +{ + [cond lock]; + called = YES; + [cond signal]; + [cond unlock]; +} +-(void) retryOpResponse +{ + [self called]; +} +-(void) retryOpException:(ICEException*)ex +{ + test(NO); +} +-(void) killRetryOpResponse +{ + test(NO); +} + +-(void) killRetryOpException:(ICEException*)ex +{ + test([ex isKindOfClass:[ICEConnectionLostException class]]); + [self called]; +}; +@end + +id<TestRetryRetryPrx> +retryAllTests(id<ICECommunicator> communicator) +{ + tprintf("testing stringToProxy... "); + NSString* ref = @"retry:default -p 12010"; + id<ICEObjectPrx> base1 = [communicator stringToProxy:ref]; + test(base1); + id<ICEObjectPrx> base2 = [communicator stringToProxy:ref]; + test(base2); + tprintf("ok\n"); + + tprintf("testing checked cast... "); + id<TestRetryRetryPrx> retry1 = [TestRetryRetryPrx checkedCast:base1]; + test(retry1); + test([retry1 isEqual:base1]); + id<TestRetryRetryPrx> retry2 = [TestRetryRetryPrx checkedCast:base2]; + test(retry2); + test([retry2 isEqual:base2]); + tprintf("ok\n"); + + tprintf("calling regular operation with first proxy... "); + [retry1 op:NO]; + tprintf("ok\n"); + + tprintf("calling operation to kill connection with second proxy... "); + @try + { + [retry2 op:YES]; + test(NO); + } + @catch(ICEConnectionLostException*) + { + tprintf("ok\n"); + } + + tprintf("calling regular operation with first proxy again... "); + [retry1 op:NO]; + tprintf("ok\n"); + +#if defined(__clang__) && !__has_feature(objc_arc) + TestRetryCallback* cb1 = [[[TestRetryCallback alloc] init] autorelease]; + TestRetryCallback* cb2 = [[[TestRetryCallback alloc] init] autorelease]; +#else + TestRetryCallback* cb1 = [[TestRetryCallback alloc] init]; + TestRetryCallback* cb2 = [[TestRetryCallback alloc] init]; +#endif + tprintf("calling regular AMI operation with first proxy... "); + [retry1 begin_op:NO response:^{ [cb1 retryOpResponse]; } + exception:^(ICEException* ex) { [cb1 retryOpException:ex]; }]; + [cb1 check]; + tprintf("ok\n"); + + tprintf("calling AMI operation to kill connection with second proxy... "); + [retry2 begin_op:YES response:^{ [cb2 killRetryOpResponse]; } + exception:^(ICEException* ex) { [cb2 killRetryOpException:ex]; }]; + [cb2 check]; + tprintf("ok\n"); + + tprintf("calling regular AMI operation with first proxy again... "); + [retry1 begin_op:NO response:^{ [cb1 retryOpResponse]; } + exception:^(ICEException* ex) { [cb1 retryOpException:ex]; }]; + [cb1 check]; + tprintf("ok\n"); + + return retry1; +} diff --git a/objc/test/Ice/retry/Client.m b/objc/test/Ice/retry/Client.m new file mode 100644 index 00000000000..1f7be1dc7d6 --- /dev/null +++ b/objc/test/Ice/retry/Client.m @@ -0,0 +1,89 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <RetryTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + TestRetryRetryPrx* retryAllTests(id<ICECommunicator>); + TestRetryRetryPrx* retry = retryAllTests(communicator); + [retry shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main retryClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); + + // + // For this test, we want to disable retries. + // + [initData.properties setProperty:@"Ice.RetryIntervals" value:@"-1"]; + + // + // This test kills connections, so we don't want warnings. + // + [initData.properties setProperty:@"Ice.Warn.Connections" value:@"0"]; + +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestRetry", @"::Test", + nil]; +#endif + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/retry/Makefile b/objc/test/Ice/retry/Makefile new file mode 100644 index 00000000000..2f09fea4047 --- /dev/null +++ b/objc/test/Ice/retry/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = RetryTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/retry/RetryTest.ice b/objc/test/Ice/retry/RetryTest.ice new file mode 100644 index 00000000000..39cb6c534a8 --- /dev/null +++ b/objc/test/Ice/retry/RetryTest.ice @@ -0,0 +1,22 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestRetry"] +module Test +{ + +interface Retry +{ + void op(bool kill); + void shutdown(); +}; + +}; diff --git a/objc/test/Ice/retry/Server.m b/objc/test/Ice/retry/Server.m new file mode 100644 index 00000000000..5b506b36912 --- /dev/null +++ b/objc/test/Ice/retry/Server.m @@ -0,0 +1,83 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <retry/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010:udp"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* object = [[[TestRetryRetryI alloc] init] autorelease]; +#else + ICEObject* object = [[TestRetryRetryI alloc] init]; +#endif + [adapter add:object identity:[communicator stringToIdentity:@"retry"]]; + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main retryServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestRetry", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/retry/TestI.h b/objc/test/Ice/retry/TestI.h new file mode 100644 index 00000000000..fe4cdc61d67 --- /dev/null +++ b/objc/test/Ice/retry/TestI.h @@ -0,0 +1,15 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <RetryTest.h> + +@interface TestRetryRetryI : TestRetryRetry +-(void) op:(BOOL)kill current:(ICECurrent *)current; +-(void) shutdown:(ICECurrent *)current; +@end diff --git a/objc/test/Ice/retry/TestI.m b/objc/test/Ice/retry/TestI.m new file mode 100644 index 00000000000..ab507218653 --- /dev/null +++ b/objc/test/Ice/retry/TestI.m @@ -0,0 +1,26 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <retry/TestI.h> + +@implementation TestRetryRetryI +-(void) op:(BOOL)kill current:(ICECurrent*)current +{ + if(kill) + { + [[current con] close:YES]; + } +} + +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} +@end diff --git a/objc/test/Ice/retry/run.py b/objc/test/Ice/retry/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/retry/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Ice/services/.gitignore b/objc/test/Ice/services/.gitignore new file mode 100644 index 00000000000..67ac8b78837 --- /dev/null +++ b/objc/test/Ice/services/.gitignore @@ -0,0 +1,7 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +.depend +ServicesTest.m +ServicesTest.h diff --git a/objc/test/Ice/services/AllTests.m b/objc/test/Ice/services/AllTests.m new file mode 100644 index 00000000000..823aa5b8692 --- /dev/null +++ b/objc/test/Ice/services/AllTests.m @@ -0,0 +1,116 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <objc/Glacier2.h> +#import <objc/IceStorm.h> +#import <objc/IceGrid.h> +#import <TestCommon.h> +#import <ServicesTest.h> + +#import <Foundation/Foundation.h> + +@interface ClockI : TestServicesClock<TestServicesClock> +-(id) init; ++(id) cloki; +-(void)tick:(NSString*)time current:(ICECurrent*)current; +@end + +@implementation ClockI +-(id) init +{ + self = [super init]; + return self; +} ++(id) cloki +{ +#if defined(__clang__) && !__has_feature(objc_arc) + return [[[ClockI alloc] init] autorelease]; +#else + return [[ClockI alloc] init]; +#endif +} + +-(void)tick:(NSString*)time current:(ICECurrent*)current +{ + NSLog(@"%@", time); +} +@end + +void +servicesAllTests(id<ICECommunicator> communicator) +{ + { + tprintf("testing Glacier2 stub... "); + @try + { + id<GLACIER2RouterPrx> router = [GLACIER2RouterPrx checkedCast:[communicator getDefaultRouter]]; + [router createSession:@"" password:@""]; + } + @catch(ICEException* ex) + { + test(NO); + } + tprintf("ok\n"); + } + + { + tprintf("testing IceStorm stub... "); + ICESTORMTopicManagerPrx* manager = + [ICESTORMTopicManagerPrx uncheckedCast:[communicator stringToProxy:@"test:default -p 12010"]]; + + ICESTORMQoS* qos; + ICESTORMTopicPrx* topic; + NSString* topicName = @"time"; + + id<ICEObjectAdapter> adapter = [communicator createObjectAdapterWithEndpoints:@"subscriber" endpoints:@"tcp"]; + ICEObjectPrx* subscriber = [adapter addWithUUID:[ClockI cloki]]; + [adapter activate]; + + @try + { + topic = [manager retrieve:topicName]; + [topic subscribeAndGetPublisher:qos subscriber:subscriber]; + } + @catch(ICESTORMNoSuchTopic*) + { + test(NO); + } + @catch(ICESTORMAlreadySubscribed*) + { + test(NO); + } + @catch(ICELocalException*) + { + } + tprintf("ok\n"); + } + + { + tprintf("testing IceGrid stub... "); + ICEObjectPrx* base = [communicator stringToProxy:@"test:default -p 12010"]; + ICEGRIDRegistryPrx* registry = [ICEGRIDRegistryPrx uncheckedCast:base]; + ICEGRIDAdminSessionPrx* session; + ICEGRIDAdminPrx* admin; + @try + { + session = [registry createAdminSession:@"username" password:@"password"]; + test(NO); + admin = [session getAdmin]; + } + @catch(ICEGRIDPermissionDeniedException*) + { + test(NO); + } + @catch(ICELocalException*) + { + } + tprintf("ok\n"); + } +} diff --git a/objc/test/Ice/services/Client.m b/objc/test/Ice/services/Client.m new file mode 100644 index 00000000000..fa46df374ae --- /dev/null +++ b/objc/test/Ice/services/Client.m @@ -0,0 +1,76 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <ServicesTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + void servicesAllTests(id<ICECommunicator>); + servicesAllTests(communicator); + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main servicesClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestServices", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/services/Makefile b/objc/test/Ice/services/Makefile new file mode 100644 index 00000000000..1cf284bceaf --- /dev/null +++ b/objc/test/Ice/services/Makefile @@ -0,0 +1,30 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client + +TARGETS = $(CLIENT) + +SLICE_OBJS = ServicesTest.o + +COBJS = Client.o \ + AllTests.o + +OBJS = $(COBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I../../include $(CPPFLAGS) +LIBS := -lGlacier2ObjC$(libsuffix) -lIceStormObjC$(libsuffix) -lIceGridObjC$(libsuffix) $(TEST_LIBS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/services/ServicesTest.ice b/objc/test/Ice/services/ServicesTest.ice new file mode 100644 index 00000000000..3fea6f9d73b --- /dev/null +++ b/objc/test/Ice/services/ServicesTest.ice @@ -0,0 +1,21 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestServices"] +module Test +{ + +interface Clock +{ + void tick(string time); +}; + +}; diff --git a/objc/test/Ice/services/run.py b/objc/test/Ice/services/run.py new file mode 100755 index 00000000000..ac32c445572 --- /dev/null +++ b/objc/test/Ice/services/run.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +client = os.path.join(os.getcwd(), "client") +TestUtil.simpleTest(client) + diff --git a/objc/test/Ice/slicing/Makefile b/objc/test/Ice/slicing/Makefile new file mode 100644 index 00000000000..b458725f9f6 --- /dev/null +++ b/objc/test/Ice/slicing/Makefile @@ -0,0 +1,21 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = exceptions objects + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done diff --git a/objc/test/Ice/slicing/exceptions/.gitignore b/objc/test/Ice/slicing/exceptions/.gitignore new file mode 100644 index 00000000000..0962671d892 --- /dev/null +++ b/objc/test/Ice/slicing/exceptions/.gitignore @@ -0,0 +1,10 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +SlicingExceptionsTestClient.m +SlicingExceptionsTestServer.m +SlicingExceptionsTestClient.h +SlicingExceptionsTestServer.h diff --git a/objc/test/Ice/slicing/exceptions/AllTests.m b/objc/test/Ice/slicing/exceptions/AllTests.m new file mode 100644 index 00000000000..0516781f124 --- /dev/null +++ b/objc/test/Ice/slicing/exceptions/AllTests.m @@ -0,0 +1,826 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <SlicingExceptionsTestClient.h> + +#import <Foundation/Foundation.h> + +@interface RelayI : TestSlicingExceptionsClientRelay<TestSlicingExceptionsClientRelay> ++(id) relayi; +@end + +@implementation RelayI + ++(id) relayi +{ +#if defined(__clang__) && !__has_feature(objc_arc) + return [[[RelayI alloc] init] autorelease]; +#else + return [[RelayI alloc] init]; +#endif +} + +-(void) knownPreservedAsBase:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsClientKnownPreservedDerived knownPreservedDerived:@"base" + kp:@"preserved" + kpd:@"derived"]; +} + +-(void) knownPreservedAsKnownPreserved:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsClientKnownPreservedDerived knownPreservedDerived:@"base" + kp:@"preserved" + kpd:@"derived"]; +} + +-(void) unknownPreservedAsBase:(ICECurrent*)current +{ + TestSlicingExceptionsClientPreserved2* ex = [TestSlicingExceptionsClientPreserved2 alloc]; + ex.b = @"base"; + ex.kp = @"preserved"; + ex.kpd = @"derived"; + ex.p1 = [TestSlicingExceptionsClientPreservedClass preservedClass:@"bc" pc:@"pc"]; + ex.p2 = ex.p1; +#if defined(__clang__) && !__has_feature(objc_arc) + [ex autorelease]; +#endif + @throw ex; +} + +-(void) unknownPreservedAsKnownPreserved:(ICECurrent*)current +{ + TestSlicingExceptionsClientPreserved2* ex = [TestSlicingExceptionsClientPreserved2 alloc]; + ex.b = @"base"; + ex.kp = @"preserved"; + ex.kpd = @"derived"; + ex.p1 = [TestSlicingExceptionsClientPreservedClass preservedClass:@"bc" pc:@"pc"]; + ex.p2 = ex.p1; +#if defined(__clang__) && !__has_feature(objc_arc) + [ex autorelease]; +#endif + @throw ex; +} + +@end + +@interface TestSlicingExceptionsClientCallback : NSObject +{ + BOOL called; + NSCondition* cond; +} +-(void) check; +-(void) called; +@end + +@implementation TestSlicingExceptionsClientCallback +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + cond = [[NSCondition alloc] init]; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [super dealloc]; +} +#endif + ++(id) create +{ +#if defined(__clang__) && __has_feature(objc_arc) + return [[TestSlicingExceptionsClientCallback alloc] init]; +#else + return [[[TestSlicingExceptionsClientCallback alloc] init] autorelease]; +#endif +} + +-(void) check +{ + [cond lock]; + while(!called) + { + [cond wait]; + } + called = NO; + [cond unlock]; +} + +-(void) called +{ + [cond lock]; + called = YES; + [cond signal]; + [cond unlock]; +} + +-(void) response +{ + test(NO); +} + +-(void) baseAsBaseException:(ICEException*)exc +{ + @try + { + @throw exc; + } + @catch(TestSlicingExceptionsClientBase* b) + { + test([b.b isEqualToString:@"Base.b"]); + test([[b ice_name] isEqualToString:@"Test::Base"]); + } + @catch(...) + { + test(NO); + } + [self called]; +} + +-(void) unknownDerivedAsBaseException:(ICEException*)exc +{ + @try + { + @throw exc; + } + @catch(TestSlicingExceptionsClientBase* b) + { + test([b.b isEqualToString:@"UnknownDerived.b"]); + test([[b ice_name] isEqualToString:@"Test::Base"]); + } + @catch(...) + { + test(NO); + } + [self called]; +} + +-(void) knownDerivedException:(ICEException*)exc +{ + @try + { + @throw exc; + } + @catch(TestSlicingExceptionsClientKnownDerived* k) + { + test([k.b isEqualToString:@"KnownDerived.b"]); + test([k.kd isEqualToString:@"KnownDerived.kd"]); + test([[k ice_name] isEqualToString:@"Test::KnownDerived"]); + } + @catch(...) + { + test(NO); + } + [self called]; +} + +-(void) unknownIntermediateAsBaseException:(ICEException*)exc +{ + @try + { + @throw exc; + } + @catch(TestSlicingExceptionsClientBase* b) + { + test([b.b isEqualToString:@"UnknownIntermediate.b"]); + test([[b ice_name] isEqualToString:@"Test::Base"]); + } + @catch(...) + { + test(NO); + } + [self called]; +} + +-(void) knownIntermediateAsBaseException:(ICEException*)exc +{ + @try + { + @throw exc; + } + @catch(TestSlicingExceptionsClientKnownIntermediate* ki) + { + test([ki.b isEqualToString:@"KnownIntermediate.b"]); + test([ki.ki isEqualToString:@"KnownIntermediate.ki"]); + test([[ki ice_name] isEqualToString:@"Test::KnownIntermediate"]); + } + @catch(...) + { + test(NO); + } + [self called]; +} + +-(void) knownMostDerivedException:(ICEException*)exc +{ + @try + { + @throw exc; + } + @catch(TestSlicingExceptionsClientKnownMostDerived* kmd) + { + test([kmd.b isEqualToString:@"KnownMostDerived.b"]); + test([kmd.ki isEqualToString:@"KnownMostDerived.ki"]); + test([kmd.kmd isEqualToString:@"KnownMostDerived.kmd"]); + test([[kmd ice_name] isEqualToString:@"Test::KnownMostDerived"]); + } + @catch(...) + { + test(NO); + } + [self called]; +} + +-(void) knownIntermediateAsKnownIntermediateException:(ICEException*)exc +{ + @try + { + @throw exc; + } + @catch(TestSlicingExceptionsClientKnownIntermediate* ki) + { + test([ki.b isEqualToString:@"KnownIntermediate.b"]); + test([ki.ki isEqualToString:@"KnownIntermediate.ki"]); + test([[ki ice_name] isEqualToString:@"Test::KnownIntermediate"]); + } + @catch(...) + { + test(NO); + } + [self called]; +} + +-(void) unknownMostDerived1Exception:(ICEException*)exc +{ + @try + { + @throw exc; + } + @catch(TestSlicingExceptionsClientKnownIntermediate* ki) + { + test([ki.b isEqualToString:@"UnknownMostDerived1.b"]); + test([ki.ki isEqualToString:@"UnknownMostDerived1.ki"]); + test([[ki ice_name] isEqualToString:@"Test::KnownIntermediate"]); + } + @catch(...) + { + test(NO); + } + [self called]; +} + +-(void) unknownMostDerived2Exception:(ICEException*)exc +{ + @try + { + @throw exc; + } + @catch(TestSlicingExceptionsClientBase* b) + { + test([b.b isEqualToString:@"UnknownMostDerived2.b"]); + test([[b ice_name] isEqualToString:@"Test::Base"]); + } + @catch(...) + { + test(NO); + } + [self called]; +} +@end + +id<TestSlicingExceptionsClientTestIntfPrx> +slicingExceptionsAllTests(id<ICECommunicator> communicator) +{ + id<ICEObjectPrx> obj = [communicator stringToProxy:@"Test:default -p 12010"]; + id<TestSlicingExceptionsClientTestIntfPrx> test = [TestSlicingExceptionsClientTestIntfPrx checkedCast:obj]; + tprintf("base... "); + { + @try + { + [test baseAsBase]; + test(NO); + } + @catch(TestSlicingExceptionsClientBase* b) + { + test([b.b isEqual:@"Base.b"]); + test([[b ice_name] isEqualToString:@"Test::Base"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("base (AMI)... "); + { + TestSlicingExceptionsClientCallback *cb = [TestSlicingExceptionsClientCallback create]; + [test begin_baseAsBase:^ { test(NO); } exception:^(ICEException* e) { [cb baseAsBaseException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("slicing of unknown derived... "); + { + @try + { + [test unknownDerivedAsBase]; + test(NO); + } + @catch(TestSlicingExceptionsClientBase* b) + { + test([b.b isEqualToString:@"UnknownDerived.b"]); + test([[b ice_name] isEqualToString:@"Test::Base"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("slicing of unknown derived (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_unknownDerivedAsBase:^ { test(NO); } exception:^(ICEException* e) { [cb unknownDerivedAsBaseException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("non-slicing of known derived as base... "); + { + @try + { + [test knownDerivedAsBase]; + test(NO); + } + @catch(TestSlicingExceptionsClientKnownDerived* k) + { + test([k.b isEqualToString:@"KnownDerived.b"]); + test([k.kd isEqualToString:@"KnownDerived.kd"]); + test([[k ice_name] isEqualToString:@"Test::KnownDerived"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("non-slicing of known derived as base (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_knownDerivedAsBase:^ { test(NO); } exception:^(ICEException* e) { [cb knownDerivedException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("non-slicing of known derived as derived... "); + { + @try + { + [test knownDerivedAsKnownDerived]; + test(NO); + } + @catch(TestSlicingExceptionsClientKnownDerived* k) + { + test([k.b isEqualToString:@"KnownDerived.b"]); + test([k.kd isEqualToString:@"KnownDerived.kd"]); + test([[k ice_name] isEqualToString:@"Test::KnownDerived"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("non-slicing of known derived as derived (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_knownDerivedAsKnownDerived:^ { test(NO); } exception:^(ICEException* e) { [cb knownDerivedException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("slicing of unknown intermediate as base... "); + { + @try + { + [test unknownIntermediateAsBase]; + test(NO); + } + @catch(TestSlicingExceptionsClientBase* b) + { + test([b.b isEqualToString:@"UnknownIntermediate.b"]); + test([[b ice_name] isEqualToString:@"Test::Base"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("slicing of unknown intermediate as base (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_unknownIntermediateAsBase:^ { test(NO); } exception:^(ICEException* e) { [cb unknownIntermediateAsBaseException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("slicing of known intermediate as base... "); + { + @try + { + [test knownIntermediateAsBase]; + test(NO); + } + @catch(TestSlicingExceptionsClientKnownIntermediate* ki) + { + test([ki.b isEqualToString:@"KnownIntermediate.b"]); + test([ki.ki isEqualToString:@"KnownIntermediate.ki"]); + test([[ki ice_name] isEqualToString:@"Test::KnownIntermediate"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("slicing of known intermediate as base (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_knownIntermediateAsBase:^ { test(NO); } exception:^(ICEException* e) { [cb knownIntermediateAsBaseException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("slicing of known most derived as base... "); + { + @try + { + [test knownMostDerivedAsBase]; + test(NO); + } + @catch(TestSlicingExceptionsClientKnownMostDerived* kmd) + { + test([kmd.b isEqualToString:@"KnownMostDerived.b"]); + test([kmd.ki isEqualToString:@"KnownMostDerived.ki"]); + test([kmd.kmd isEqualToString:@"KnownMostDerived.kmd"]); + test([[kmd ice_name] isEqualToString:@"Test::KnownMostDerived"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("slicing of known most derived as base (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_knownMostDerivedAsBase:^ { test(NO); } exception:^(ICEException* e) { [cb knownMostDerivedException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("non-slicing of known intermediate as intermediate... "); + { + @try + { + [test knownIntermediateAsKnownIntermediate]; + test(NO); + } + @catch(TestSlicingExceptionsClientKnownIntermediate* ki) + { + test([ki.b isEqualToString:@"KnownIntermediate.b"]); + test([ki.ki isEqualToString:@"KnownIntermediate.ki"]); + test([[ki ice_name] isEqualToString:@"Test::KnownIntermediate"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("non-slicing of known intermediate as intermediate (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_knownIntermediateAsKnownIntermediate:^ { test(NO); } exception:^(ICEException* e) { [cb knownIntermediateAsKnownIntermediateException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("non-slicing of known most derived exception as intermediate... "); + { + @try + { + [test knownMostDerivedAsKnownIntermediate]; + test(NO); + } + @catch(TestSlicingExceptionsClientKnownMostDerived* kmd) + { + test([kmd.b isEqualToString:@"KnownMostDerived.b"]); + test([kmd.ki isEqualToString:@"KnownMostDerived.ki"]); + test([kmd.kmd isEqualToString:@"KnownMostDerived.kmd"]); + test([[kmd ice_name] isEqualToString:@"Test::KnownMostDerived"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("non-slicing of known most derived as intermediate (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_knownMostDerivedAsKnownIntermediate:^ { test(NO); } exception:^(ICEException* e) { [cb knownMostDerivedException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("non-slicing of known most derived as most derived... "); + { + @try + { + [test knownMostDerivedAsKnownMostDerived]; + test(NO); + } + @catch(TestSlicingExceptionsClientKnownMostDerived* kmd) + { + test([kmd.b isEqualToString:@"KnownMostDerived.b"]); + test([kmd.ki isEqualToString:@"KnownMostDerived.ki"]); + test([kmd.kmd isEqualToString:@"KnownMostDerived.kmd"]); + test([[kmd ice_name] isEqualToString:@"Test::KnownMostDerived"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("non-slicing of known most derived as most derived (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_knownMostDerivedAsKnownMostDerived:^ { test(NO); } exception:^(ICEException* e) { [cb knownMostDerivedException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("slicing of unknown most derived, known intermediate as base... "); + { + @try + { + [test unknownMostDerived1AsBase]; + test(NO); + } + @catch(TestSlicingExceptionsClientKnownIntermediate* ki) + { + test([ki.b isEqualToString:@"UnknownMostDerived1.b"]); + test([ki.ki isEqualToString:@"UnknownMostDerived1.ki"]); + test([[ki ice_name] isEqualToString:@"Test::KnownIntermediate"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("slicing of unknown most derived, known intermediate as base (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_unknownMostDerived1AsBase:^ { test(NO); } exception:^(ICEException* e) { [cb unknownMostDerived1Exception:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("slicing of unknown most derived, known intermediate as intermediate... "); + { + @try + { + [test unknownMostDerived1AsKnownIntermediate]; + test(NO); + } + @catch(TestSlicingExceptionsClientKnownIntermediate* ki) + { + test([ki.b isEqualToString:@"UnknownMostDerived1.b"]); + test([ki.ki isEqualToString:@"UnknownMostDerived1.ki"]); + test([[ki ice_name] isEqualToString:@"Test::KnownIntermediate"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("slicing of unknown most derived, known intermediate as intermediate (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_unknownMostDerived1AsKnownIntermediate:^ { test(NO); } exception:^(ICEException* e) { [cb unknownMostDerived1Exception:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("slicing of unknown most derived, unknown intermediate as base... "); + { + @try + { + [test unknownMostDerived2AsBase]; + test(NO); + } + @catch(TestSlicingExceptionsClientBase* b) + { + test([b.b isEqualToString:@"UnknownMostDerived2.b"]); + test([[b ice_name] isEqualToString:@"Test::Base"]); + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("slicing of unknown most derived, unknown intermediate as base (AMI)... "); + { + TestSlicingExceptionsClientCallback* cb = [TestSlicingExceptionsClientCallback create]; + [test begin_unknownMostDerived2AsBase:^ { test(NO); } exception:^(ICEException* e) { [cb unknownMostDerived2Exception:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("unknown most derived in compact format... "); + { + @try + { + [test unknownMostDerived2AsBaseCompact]; + test(false); + } + @catch(TestSlicingExceptionsClientBase*) + { + // + // For the 1.0 encoding, the unknown exception is sliced to Base. + // + test([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]); + } + @catch(ICEUnknownUserException*) + { + // + // An UnknownUserException is raised for the compact format because the + // most-derived type is unknown and the exception cannot be sliced. + // + test(![[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]); + } + @catch(ICEOperationNotExistException*) + { + } + @catch(...) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("preserved exceptions... "); + { + id<ICEObjectAdapter> adapter = [communicator createObjectAdapterWithEndpoints:@"Relay" endpoints:@"default"]; + TestSlicingExceptionsClientRelayPrx* relay = + [TestSlicingExceptionsClientRelayPrx uncheckedCast:[adapter addWithUUID:[RelayI relayi]]]; + [adapter activate]; + + @try + { + [test relayKnownPreservedAsBase:relay]; + test(NO); + } + @catch(TestSlicingExceptionsClientKnownPreservedDerived* ex) + { + test([ex.b isEqualToString:@"base"]); + test([ex.kp isEqualToString:@"preserved"]); + test([ex.kpd isEqualToString:@"derived"]); + } + @catch(ICEOperationNotExistException*) + { + } + @catch(NSException*) + { + test(NO); + } + + @try + { + [test relayKnownPreservedAsKnownPreserved:relay]; + test(NO); + } + @catch(TestSlicingExceptionsClientKnownPreservedDerived* ex) + { + test([ex.b isEqualToString:@"base"]); + test([ex.kp isEqualToString:@"preserved"]); + test([ex.kpd isEqualToString:@"derived"]); + } + @catch(const ICEOperationNotExistException*) + { + } + @catch(NSException*) + { + test(NO); + } + + @try + { + [test relayUnknownPreservedAsBase:relay]; + test(NO); + } + @catch(TestSlicingExceptionsClientPreserved2* ex) + { + test([ex.b isEqualToString:@"base"]); + test([ex.kp isEqualToString:@"preserved"]); + test([ex.kpd isEqualToString:@"derived"]); + test([[ex.p1 ice_id] isEqualToString:[TestSlicingExceptionsClientPreservedClass ice_staticId]]); + + test([ex.p1 isKindOfClass:[TestSlicingExceptionsClientPreservedClass class]]); + TestSlicingExceptionsClientPreservedClass* pc = (TestSlicingExceptionsClientPreservedClass*)ex.p1; + test([pc.bc isEqualToString:@"bc"]); + test([pc.pc isEqualToString:@"pc"]); + test([ex.p2 isEqual:ex.p1]); + } + @catch(ICEOperationNotExistException*) + { + } + @catch(TestSlicingExceptionsClientKnownPreservedDerived* ex) + { + // + // For the 1.0 encoding, the unknown exception is sliced to KnownPreserved. + // + test([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]); + test([ex.b isEqualToString:@"base"]); + test([ex.kp isEqualToString:@"preserved"]); + test([ex.kpd isEqualToString:@"derived"]); + } + @catch(NSException*) + { + test(NO); + } + + @try + { + [test relayUnknownPreservedAsKnownPreserved:relay]; + test(NO); + } + @catch(ICEOperationNotExistException*) + { + } + @catch(TestSlicingExceptionsClientPreserved2* ex) + { + test([ex.b isEqualToString:@"base"]); + test([ex.kp isEqualToString:@"preserved"]); + test([ex.kpd isEqualToString:@"derived"]); + test([[ex.p1 ice_id] isEqualToString:[TestSlicingExceptionsClientPreservedClass ice_staticId]]); + test([ex.p1 isKindOfClass:[TestSlicingExceptionsClientPreservedClass class]]); + TestSlicingExceptionsClientPreservedClass* pc = (TestSlicingExceptionsClientPreservedClass*)ex.p1; + test([pc.bc isEqualToString:@"bc"]); + test([pc.pc isEqualToString:@"pc"]); + test([ex.p2 isEqual:ex.p1]); + } + @catch(TestSlicingExceptionsClientKnownPreservedDerived* ex) + { + // + // For the 1.0 encoding, the unknown exception is sliced to KnownPreserved. + // + test([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]); + test([ex.b isEqualToString:@"base"]); + test([ex.kp isEqualToString:@"preserved"]); + test([ex.kpd isEqualToString:@"derived"]); + } + @catch(NSException*) + { + test(NO); + } + + [adapter destroy]; + } + tprintf("ok\n"); + return test; +} diff --git a/objc/test/Ice/slicing/exceptions/Client.m b/objc/test/Ice/slicing/exceptions/Client.m new file mode 100644 index 00000000000..4c99f94b915 --- /dev/null +++ b/objc/test/Ice/slicing/exceptions/Client.m @@ -0,0 +1,76 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <SlicingExceptionsTestClient.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + id<TestSlicingExceptionsClientTestIntfPrx> slicingExceptionsAllTests(id<ICECommunicator>); + id<TestSlicingExceptionsClientTestIntfPrx> thrower = slicingExceptionsAllTests(communicator); + [thrower shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main slicingExceptionsClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestSlicingExceptionsClient", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/slicing/exceptions/Makefile b/objc/test/Ice/slicing/exceptions/Makefile new file mode 100644 index 00000000000..a34f5ba1506 --- /dev/null +++ b/objc/test/Ice/slicing/exceptions/Makefile @@ -0,0 +1,40 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = SlicingExceptionsTestClient.o \ + SlicingExceptionsTestServer.o + +COBJS = Client.o \ + AllTests.o \ + SlicingExceptionsTestClient.o + +SOBJS = TestI.o \ + Server.o \ + SlicingExceptionsTestServer.o + +OBJS = $(COBJS) $(SOBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I../.. -I../../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/slicing/exceptions/Server.m b/objc/test/Ice/slicing/exceptions/Server.m new file mode 100644 index 00000000000..054f8354816 --- /dev/null +++ b/objc/test/Ice/slicing/exceptions/Server.m @@ -0,0 +1,84 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <slicing/exceptions/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"Ice.Warn.Dispatch" value:@"0"]; + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* object = [[[TestSlicingExceptionsServerI alloc] init] autorelease]; +#else + ICEObject* object = [[TestSlicingExceptionsServerI alloc] init]; +#endif + [adapter add:object identity:[communicator stringToIdentity:@"Test"]]; + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main slicingExceptionsServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestSlicingExceptionsServer", @"::Test", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/slicing/exceptions/SlicingExceptionsTestClient.ice b/objc/test/Ice/slicing/exceptions/SlicingExceptionsTestClient.ice new file mode 100644 index 00000000000..fd7aa0cb695 --- /dev/null +++ b/objc/test/Ice/slicing/exceptions/SlicingExceptionsTestClient.ice @@ -0,0 +1,113 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestSlicingExceptionsClient"] +module Test +{ + +exception Base +{ + string b; +}; + +exception KnownDerived extends Base +{ + string kd; +}; + +exception KnownIntermediate extends Base +{ + string ki; +}; + +exception KnownMostDerived extends KnownIntermediate +{ + string kmd; +}; + +["preserve-slice"] +exception KnownPreserved extends Base +{ + string kp; +}; + +exception KnownPreservedDerived extends KnownPreserved +{ + string kpd; +}; + +["preserve-slice"] +class BaseClass +{ + string bc; +}; + +class PreservedClass extends BaseClass +{ + string pc; +}; + +exception Preserved1 extends KnownPreservedDerived +{ + BaseClass p1; +}; + +exception Preserved2 extends Preserved1 +{ + BaseClass p2; +}; + +["format:sliced"] +interface Relay +{ + void knownPreservedAsBase() throws Base; + void knownPreservedAsKnownPreserved() throws KnownPreserved; + + void unknownPreservedAsBase() throws Base; + void unknownPreservedAsKnownPreserved() throws KnownPreserved; +}; + +["format:sliced"] interface TestIntf +{ + void baseAsBase() throws Base; + void unknownDerivedAsBase() throws Base; + void knownDerivedAsBase() throws Base; + void knownDerivedAsKnownDerived() throws KnownDerived; + + void unknownIntermediateAsBase() throws Base; + void knownIntermediateAsBase() throws Base; + void knownMostDerivedAsBase() throws Base; + void knownIntermediateAsKnownIntermediate() throws KnownIntermediate; + void knownMostDerivedAsKnownIntermediate() throws KnownIntermediate; + void knownMostDerivedAsKnownMostDerived() throws KnownMostDerived; + + void unknownMostDerived1AsBase() throws Base; + void unknownMostDerived1AsKnownIntermediate() throws KnownIntermediate; + void unknownMostDerived2AsBase() throws Base; + + ["format:compact"] void unknownMostDerived2AsBaseCompact() throws Base; + + void knownPreservedAsBase() throws Base; + void knownPreservedAsKnownPreserved() throws KnownPreserved; + + void relayKnownPreservedAsBase(Relay* r) throws Base; + void relayKnownPreservedAsKnownPreserved(Relay* r) throws KnownPreserved; + + void unknownPreservedAsBase() throws Base; + void unknownPreservedAsKnownPreserved() throws KnownPreserved; + + void relayUnknownPreservedAsBase(Relay* r) throws Base; + void relayUnknownPreservedAsKnownPreserved(Relay* r) throws KnownPreserved; + + void shutdown(); +}; + +}; diff --git a/objc/test/Ice/slicing/exceptions/SlicingExceptionsTestServer.ice b/objc/test/Ice/slicing/exceptions/SlicingExceptionsTestServer.ice new file mode 100644 index 00000000000..322a6e1c7f0 --- /dev/null +++ b/objc/test/Ice/slicing/exceptions/SlicingExceptionsTestServer.ice @@ -0,0 +1,134 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestSlicingExceptionsServer"] +module Test +{ + +exception Base +{ + string b; +}; + +exception KnownDerived extends Base +{ + string kd; +}; + +exception KnownIntermediate extends Base +{ + string ki; +}; + +exception KnownMostDerived extends KnownIntermediate +{ + string kmd; +}; + +["preserve-slice"] +exception KnownPreserved extends Base +{ + string kp; +}; + +exception KnownPreservedDerived extends KnownPreserved +{ + string kpd; +}; + +["preserve-slice"] +class BaseClass +{ + string bc; +}; + +["format:sliced"] +interface Relay +{ + void knownPreservedAsBase() throws Base; + void knownPreservedAsKnownPreserved() throws KnownPreserved; + + void unknownPreservedAsBase() throws Base; + void unknownPreservedAsKnownPreserved() throws KnownPreserved; +}; + +["format:sliced"] interface TestIntf +{ + void baseAsBase() throws Base; + void unknownDerivedAsBase() throws Base; + void knownDerivedAsBase() throws Base; + void knownDerivedAsKnownDerived() throws KnownDerived; + + void unknownIntermediateAsBase() throws Base; + void knownIntermediateAsBase() throws Base; + void knownMostDerivedAsBase() throws Base; + void knownIntermediateAsKnownIntermediate() throws KnownIntermediate; + void knownMostDerivedAsKnownIntermediate() throws KnownIntermediate; + void knownMostDerivedAsKnownMostDerived() throws KnownMostDerived; + + void unknownMostDerived1AsBase() throws Base; + void unknownMostDerived1AsKnownIntermediate() throws KnownIntermediate; + void unknownMostDerived2AsBase() throws Base; + + ["format:compact"] void unknownMostDerived2AsBaseCompact() throws Base; + + void knownPreservedAsBase() throws Base; + void knownPreservedAsKnownPreserved() throws KnownPreserved; + + void relayKnownPreservedAsBase(Relay* r) throws Base; + void relayKnownPreservedAsKnownPreserved(Relay* r) throws KnownPreserved; + + void unknownPreservedAsBase() throws Base; + void unknownPreservedAsKnownPreserved() throws KnownPreserved; + + void relayUnknownPreservedAsBase(Relay* r) throws Base; + void relayUnknownPreservedAsKnownPreserved(Relay* r) throws KnownPreserved; + + void shutdown(); +}; + +// Stuff present in the server, not present in the client. +exception UnknownDerived extends Base +{ + string ud; +}; + +exception UnknownIntermediate extends Base +{ + string ui; +}; + +exception UnknownMostDerived1 extends KnownIntermediate +{ + string umd1; +}; + +exception UnknownMostDerived2 extends UnknownIntermediate +{ + string umd2; +}; + +class SPreservedClass extends BaseClass +{ + string spc; +}; + +exception SPreserved1 extends KnownPreservedDerived +{ + BaseClass p1; +}; + +exception SPreserved2 extends SPreserved1 +{ + BaseClass p2; +}; + +}; diff --git a/objc/test/Ice/slicing/exceptions/TestI.h b/objc/test/Ice/slicing/exceptions/TestI.h new file mode 100644 index 00000000000..674328d7b21 --- /dev/null +++ b/objc/test/Ice/slicing/exceptions/TestI.h @@ -0,0 +1,13 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <SlicingExceptionsTestServer.h> + +@interface TestSlicingExceptionsServerI : TestSlicingExceptionsServerTestIntf<TestSlicingExceptionsServerTestIntf> +@end diff --git a/objc/test/Ice/slicing/exceptions/TestI.m b/objc/test/Ice/slicing/exceptions/TestI.m new file mode 100644 index 00000000000..b9628d0cdee --- /dev/null +++ b/objc/test/Ice/slicing/exceptions/TestI.m @@ -0,0 +1,156 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <slicing/exceptions/TestI.h> +#import <TestCommon.h> +#import <objc/Ice.h> + +@implementation TestSlicingExceptionsServerI +-(void) baseAsBase:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerBase base:@"Base.b"]; +} + +-(void) unknownDerivedAsBase:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerUnknownDerived unknownDerived:@"UnknownDerived.b" ud:@"UnknownDerived.ud"]; +} + +-(void) knownDerivedAsBase:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerKnownDerived knownDerived:@"KnownDerived.b" kd:@"KnownDerived.kd"]; +} + +-(void) knownDerivedAsKnownDerived:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerKnownDerived knownDerived:@"KnownDerived.b" kd:@"KnownDerived.kd"]; +} + +-(void) unknownIntermediateAsBase:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerUnknownIntermediate unknownIntermediate:@"UnknownIntermediate.b" ui:@"UnknownIntermediate.ui"]; +} + +-(void) knownIntermediateAsBase:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerKnownIntermediate knownIntermediate:@"KnownIntermediate.b" ki:@"KnownIntermediate.ki"]; +} + +-(void) knownMostDerivedAsBase:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerKnownMostDerived knownMostDerived:@"KnownMostDerived.b" ki:@"KnownMostDerived.ki" kmd:@"KnownMostDerived.kmd"]; +} + +-(void) knownIntermediateAsKnownIntermediate:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerKnownIntermediate knownIntermediate:@"KnownIntermediate.b" ki:@"KnownIntermediate.ki"]; +} + +-(void) knownMostDerivedAsKnownIntermediate:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerKnownMostDerived knownMostDerived:@"KnownMostDerived.b" ki:@"KnownMostDerived.ki" kmd:@"KnownMostDerived.kmd"]; +} + +-(void) knownMostDerivedAsKnownMostDerived:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerKnownMostDerived knownMostDerived:@"KnownMostDerived.b" ki:@"KnownMostDerived.ki" kmd:@"KnownMostDerived.kmd"]; +} + +-(void) unknownMostDerived1AsBase:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerUnknownMostDerived1 unknownMostDerived1:@"UnknownMostDerived1.b" ki:@"UnknownMostDerived1.ki" umd1:@"UnknownMostDerived1.umd1"]; +} + +-(void) unknownMostDerived1AsKnownIntermediate:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerUnknownMostDerived1 unknownMostDerived1:@"UnknownMostDerived1.b" + ki:@"UnknownMostDerived1.ki" + umd1:@"UnknownMostDerived1.umd1"]; +} + +-(void) unknownMostDerived2AsBase:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerUnknownMostDerived2 unknownMostDerived2:@"UnknownMostDerived2.b" + ui:@"UnknownMostDerived2.ui" + umd2:@"UnknownMostDerived2.umd2"]; +} + +-(void) unknownMostDerived2AsBaseCompact:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerUnknownMostDerived2 unknownMostDerived2:@"UnknownMostDerived2.b" + ui:@"UnknownMostDerived2.ui" + umd2:@"UnknownMostDerived2.umd2"]; +} + +-(void) knownPreservedAsBase:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerKnownPreservedDerived knownPreservedDerived:@"base" + kp:@"preserved" + kpd:@"derived"]; +} + +-(void) knownPreservedAsKnownPreserved:(ICECurrent*)current +{ + @throw [TestSlicingExceptionsServerKnownPreservedDerived knownPreservedDerived:@"base" + kp:@"preserved" + kpd:@"derived"]; +} + +-(void) relayKnownPreservedAsBase:(TestSlicingExceptionsServerRelayPrx*)relay current:(ICECurrent*)current +{ + [relay knownPreservedAsBase]; + test(NO); +} + +-(void) relayKnownPreservedAsKnownPreserved:(TestSlicingExceptionsServerRelayPrx*)relay current:(ICECurrent*)current +{ + [relay knownPreservedAsKnownPreserved]; + test(NO); +} + +-(void) unknownPreservedAsBase:(ICECurrent*)current +{ + TestSlicingExceptionsServerSPreserved2* ex = [TestSlicingExceptionsServerSPreserved2 alloc]; + ex.b = @"base"; + ex.kp = @"preserved"; + ex.kpd = @"derived"; + ex.p1 = [TestSlicingExceptionsServerSPreservedClass sPreservedClass:@"bc" spc:@"spc"]; + ex.p2 = ex.p1; + @throw ex; +} + +-(void) unknownPreservedAsKnownPreserved:(ICECurrent*)current +{ + TestSlicingExceptionsServerSPreserved2* ex = [TestSlicingExceptionsServerSPreserved2 alloc]; + ex.b = @"base"; + ex.kp = @"preserved"; + ex.kpd = @"derived"; + ex.p1 = [TestSlicingExceptionsServerSPreservedClass sPreservedClass:@"bc" spc:@"spc"]; + ex.p2 = ex.p1; + @throw ex; +} + +-(void) relayUnknownPreservedAsBase:(TestSlicingExceptionsServerRelayPrx*)relay current:(ICECurrent*)current +{ + [relay unknownPreservedAsBase]; + test(NO); +} + +-(void) relayUnknownPreservedAsKnownPreserved:(TestSlicingExceptionsServerRelayPrx*)relay current:(ICECurrent*)current +{ + [relay unknownPreservedAsKnownPreserved]; + test(NO); +} + + +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} +@end diff --git a/objc/test/Ice/slicing/exceptions/run.py b/objc/test/Ice/slicing/exceptions/run.py new file mode 100755 index 00000000000..8e41f17c1be --- /dev/null +++ b/objc/test/Ice/slicing/exceptions/run.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../..", "../../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +print("Running test with sliced format.") +TestUtil.clientServerTest() + +print("Running test with 1.0 encoding.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", + additionalServerOptions="--Ice.Default.EncodingVersion=1.0") diff --git a/objc/test/Ice/slicing/objects/.gitignore b/objc/test/Ice/slicing/objects/.gitignore new file mode 100644 index 00000000000..a2c2a1c0974 --- /dev/null +++ b/objc/test/Ice/slicing/objects/.gitignore @@ -0,0 +1,14 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +SlicingObjectsTestClient.m +SlicingObjectsForwardClient.m +SlicingObjectsTestServer.m +SlicingObjectsForwardServer.m +SlicingObjectsTestClient.h +SlicingObjectsForwardClient.h +SlicingObjectsTestServer.h +SlicingObjectsForwardServer.h diff --git a/objc/test/Ice/slicing/objects/AllTests.m b/objc/test/Ice/slicing/objects/AllTests.m new file mode 100644 index 00000000000..efc0edf3ae7 --- /dev/null +++ b/objc/test/Ice/slicing/objects/AllTests.m @@ -0,0 +1,2232 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <SlicingObjectsTestClient.h> +#import <SlicingObjectsForwardClient.h> + +#import <Foundation/Foundation.h> + +@interface TestSlicingObjectsClientCallback : NSObject +{ + BOOL called; + NSCondition* cond; +@public + id r; + id bout; +} +@property(nonatomic, retain) id r; +@property(nonatomic, retain) id bout; +-(void) check; +-(void) called; +@end + +@implementation TestSlicingObjectsClientCallback +@synthesize r; +@synthesize bout; +-(id) init +{ + if(![super init]) + { + return nil; + } + cond = [[NSCondition alloc] init]; + return self; +} + ++(id) create +{ +#if defined(__clang__) && __has_feature(objc_arc) + return [[TestSlicingObjectsClientCallback alloc] init]; +#else + return [[[TestSlicingObjectsClientCallback alloc] init] autorelease]; +#endif +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [super dealloc]; +} +#endif + +-(void) check +{ + [cond lock]; + while(!called) + { + [cond wait]; + } + called = NO; + [cond unlock]; +} +-(void) called +{ + [cond lock]; + called = YES; + [cond signal]; + [cond unlock]; +} +-(void) SBaseAsObjectResponse:(ICEObject*)o +{ + test(o); + test([[o ice_id:nil] isEqualToString:@"::Test::SBase"]); + test([o isKindOfClass:[TestSlicingObjectsClientSBase class]]); + TestSlicingObjectsClientSBase* sb = (TestSlicingObjectsClientSBase*)o; + test([sb.sb isEqualToString:@"SBase.sb"]); + [self called]; +} + +-(void) SBaseAsObjectException:(ICEException*)exc +{ + test(NO); +} + +-(void) SBaseAsSBaseResponse:(TestSlicingObjectsClientSBase*)sb +{ + test([sb.sb isEqualToString:@"SBase.sb"]); + [self called]; +} + +-(void) SBaseAsSBaseException:(ICEException*)exc +{ + test(NO); +} + +-(void) SBSKnownDerivedAsSBaseResponse:(TestSlicingObjectsClientSBase*)sb +{ + test([sb isKindOfClass:[TestSlicingObjectsClientSBSKnownDerived class]]); + TestSlicingObjectsClientSBSKnownDerived* sbskd = (TestSlicingObjectsClientSBSKnownDerived*)sb; + test([sbskd.sbskd isEqualToString:@"SBSKnownDerived.sbskd"]); + [self called]; +} + +-(void) SBSKnownDerivedAsSBaseException:(ICEException*)exc +{ + test(NO); +} + +-(void) SBSKnownDerivedAsSBSKnownDerivedResponse:(TestSlicingObjectsClientSBSKnownDerived*)sbskd +{ + test([sbskd.sbskd isEqualToString:@"SBSKnownDerived.sbskd"]); + [self called]; +} + +-(void) SBSKnownDerivedAsSBSKnownDerivedException:(ICEException*)exc +{ + test(NO); +} + +-(void) SBSUnknownDerivedAsSBaseResponse:(TestSlicingObjectsClientSBase*)sb +{ + test([sb.sb isEqualToString:@"SBSUnknownDerived.sb"]); + [self called]; +} + +-(void) SBSUnknownDerivedAsSBaseException:(ICEException*)exc +{ + test(NO); +} + +-(void) SBSUnknownDerivedAsSBaseCompactResponse:(TestSlicingObjectsClientSBase*)sb +{ + test(NO); +} + +-(void) SBSUnknownDerivedAsSBaseCompactException:(ICEException*)exc +{ + test([[exc ice_name] isEqualToString:@"Ice::NoObjectFactoryException"]); + [self called]; +} + +-(void) SUnknownAsObjectResponse10:(ICEObject*)o +{ + test(NO); +} + +-(void) SUnknownAsObjectException10:(ICEException*)exc +{ + test([[exc ice_name] isEqualToString:@"Ice::NoObjectFactoryException"]); + [self called]; +} + +-(void) SUnknownAsObjectResponse11:(ICEObject*)o +{ + [self called]; +} + +-(void) SUnknownAsObjectException11:(ICEException*)exc +{ + test(NO); +} + +-(void) oneElementCycleResponse:(TestSlicingObjectsClientB*)b +{ + test(b); + test([[b ice_id:nil] isEqualToString:@"::Test::B"]); + test([b.sb isEqualToString:@"B1.sb"]); + test(b.pb == b); + [self called]; +} + +-(void) oneElementCycleException:(ICEException*)exc +{ + test(NO); +} + +-(void) twoElementCycleResponse:(TestSlicingObjectsClientB*)b1 +{ + test(b1); + test([[b1 ice_id:nil] isEqualToString:@"::Test::B"]); + test([b1.sb isEqualToString:@"B1.sb"]); + + TestSlicingObjectsClientB* b2 = b1.pb; + test(b2); + test([[b2 ice_id:nil] isEqualToString:@"::Test::B"]); + test([b2.sb isEqualToString:@"B2.sb"]); + test(b2.pb == b1); + [self called]; +} + +-(void) twoElementCycleException:(ICEException*)exc +{ + test(NO); +} + +-(void) D1AsBResponse:(TestSlicingObjectsClientB*)b1 +{ + test(b1); + test([[b1 ice_id:nil] isEqualToString:@"::Test::D1"]); + test([b1.sb isEqualToString:@"D1.sb"]); + test(b1.pb); + test(b1.pb != b1); + test([b1 isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* d1 = (TestSlicingObjectsClientD1*)b1; + test([d1.sd1 isEqualToString:@"D1.sd1"]); + test(d1.pd1); + test(d1.pd1 != b1); + test(b1.pb == d1.pd1); + + TestSlicingObjectsClientB* b2 = b1.pb; + test(b2); + test(b2.pb == b1); + test([b2.sb isEqualToString:@"D2.sb"]); + test([[b2 ice_id:nil] isEqualToString:@"::Test::B"]); + [self called]; +} + +-(void) D1AsBException:(ICEException*)exc +{ + test(NO); +} + +-(void) D1AsD1Response:(TestSlicingObjectsClientD1*)d1 +{ + test(d1); + test([[d1 ice_id:nil] isEqualToString:@"::Test::D1"]); + test([d1.sb isEqualToString:@"D1.sb"]); + test(d1.pb); + test(d1.pb != d1); + + TestSlicingObjectsClientB* b2 = d1.pb; + test(b2); + test([[b2 ice_id:nil] isEqualToString:@"::Test::B"]); + test([b2.sb isEqualToString:@"D2.sb"]); + test(b2.pb == d1); + [self called]; +} + +-(void) D1AsD1Exception:(ICEException*)exc +{ + test(NO); +} + +-(void) D2AsBResponse:(TestSlicingObjectsClientB*)b2 +{ + test(b2); + test([[b2 ice_id:nil] isEqualToString:@"::Test::B"]); + test([b2.sb isEqualToString:@"D2.sb"]); + test(b2.pb); + test(b2.pb != b2); + + TestSlicingObjectsClientB* b1 = b2.pb; + test(b1); + test([[b1 ice_id:nil] isEqualToString:@"::Test::D1"]); + test([b1.sb isEqualToString:@"D1.sb"]); + test(b1.pb == b2); + test([b1 isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* d1 = (TestSlicingObjectsClientD1*)b1; + test([d1.sd1 isEqualToString:@"D1.sd1"]); + test(d1.pd1 == b2); + [self called]; +} + +-(void) D2AsBException:(ICEException*)exc +{ + test(NO); +} + +-(void) paramTest1Response:(TestSlicingObjectsClientB*)b1 p2:(TestSlicingObjectsClientB*)b2 +{ + test(b1); + test([[b1 ice_id:nil] isEqualToString:@"::Test::D1"]); + test([b1.sb isEqualToString:@"D1.sb"]); + test(b1.pb == b2); + test([b1 isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* d1 = (TestSlicingObjectsClientD1*)b1; + test([d1.sd1 isEqualToString:@"D1.sd1"]); + test(d1.pd1 == b2); + + test(b2); + test([[b2 ice_id:nil] isEqualToString:@"::Test::B"]); // No factory, must be sliced + test([b2.sb isEqualToString:@"D2.sb"]); + test(b2.pb == b1); + [self called]; +} + +-(void) paramTest1Exception:(ICEException*)exc +{ + test(NO); +} + +-(void) returnTest1Response:(TestSlicingObjectsClientB*)r_ p1:(TestSlicingObjectsClientB*)p1 p2:(TestSlicingObjectsClientB*)p2 +{ + test(r_ == p1); + [self called]; +} + +-(void) returnTest1Exception:(ICEException*)exc +{ + test(NO); +} + +-(void) returnTest2Response:(TestSlicingObjectsClientB*)r_ p1:(TestSlicingObjectsClientB*)p1 p2:(TestSlicingObjectsClientB*)p2 +{ + test(r_ == p1); + [self called]; +} + +-(void) returnTest2Exception:(ICEException*)exc +{ + test(NO); +} + +-(void) returnTest3Response:(TestSlicingObjectsClientB*)b +{ + self.r = b; + [self called]; +} + +-(void) returnTest3Exception:(ICEException*)exc +{ + test(NO); +} + +-(void) paramTest3Response:(TestSlicingObjectsClientB*)ret p1:(TestSlicingObjectsClientB*)p1 p2:(TestSlicingObjectsClientB*)p2 +{ + test(p1); + test([p1.sb isEqualToString:@"D2.sb (p1 1)"]); + test(p1.pb == 0); + test([[p1 ice_id:nil] isEqualToString:@"::Test::B"]); + + test(p2); + test([p2.sb isEqualToString:@"D2.sb (p2 1)"]); + test(p2.pb == 0); + test([[p2 ice_id:nil] isEqualToString:@"::Test::B"]); + + test(ret); + test([ret.sb isEqualToString:@"D1.sb (p2 2)"]); + test(ret.pb == 0); + test([[ret ice_id:nil] isEqualToString:@"::Test::D1"]); + [self called]; +} + +-(void) paramTest3Exception:(ICEException*)exc +{ + test(NO); +} + +-(void) paramTest4Response:(TestSlicingObjectsClientB*)ret p1:(TestSlicingObjectsClientB*)b +{ + test(b); + test([b.sb isEqualToString:@"D4.sb (1)"]); + test(b.pb == 0); + test([[b ice_id:nil] isEqualToString:@"::Test::B"]); + + test(ret); + test([ret.sb isEqualToString:@"B.sb (2)"]); + test(ret.pb == 0); + test([[ret ice_id:nil] isEqualToString:@"::Test::B"]); + [self called]; +} + +-(void) paramTest4Exception:(ICEException*)exc +{ + test(NO); +} + +-(void) sequenceTestResponse:(TestSlicingObjectsClientSS*)ss +{ + self.r = ss; + [self called]; +} + +-(void) sequenceTestException:(ICEException*)exc +{ + test(NO); +} + +-(void) dictionaryTestResponse:(TestSlicingObjectsClientBDict*)r_ bout:(TestSlicingObjectsClientBDict*)bout_ +{ + self.r = r_; + self.bout = bout_; + [self called]; +} + +-(void) dictionaryTestException:(ICEException*)exc +{ + test(NO); +} + +-(void) throwBaseAsBaseResponse +{ + test(NO); +} + +-(void) throwBaseAsBaseException:(ICEException*)ex +{ + test([[ex ice_name] isEqualToString:@"Test::BaseException"]); + TestSlicingObjectsClientBaseException* e = (TestSlicingObjectsClientBaseException*)ex; + test([e.sbe isEqualToString:@"sbe"]); + test(e.pb); + test([e.pb.sb isEqualToString:@"sb"]); + test(e.pb.pb == e.pb); + [self called]; +} + +-(void) throwDerivedAsBaseResponse +{ + test(NO); +} + +-(void) throwDerivedAsBaseException:(ICEException*)ex +{ + test([[ex ice_name] isEqualToString:@"Test::DerivedException"]); + TestSlicingObjectsClientDerivedException* e = (TestSlicingObjectsClientDerivedException*)ex; + test([e.sbe isEqualToString:@"sbe"]); + test(e.pb); + test([e.pb.sb isEqualToString:@"sb1"]); + test(e.pb.pb == e.pb); + test([e.sde isEqualToString:@"sde1"]); + test(e.pd1); + test([e.pd1.sb isEqualToString:@"sb2"]); + test(e.pd1.pb == e.pd1); + test([e.pd1.sd1 isEqualToString:@"sd2"]); + test(e.pd1.pd1 == e.pd1); + [self called]; +} + +-(void) throwDerivedAsDerivedResponse +{ + test(NO); +} + +-(void) throwDerivedAsDerivedException:(ICEException*)ex +{ + test([[ex ice_name] isEqualToString:@"Test::DerivedException"]); + TestSlicingObjectsClientDerivedException* e = (TestSlicingObjectsClientDerivedException*)ex; + test([e.sbe isEqualToString:@"sbe"]); + test(e.pb); + test([e.pb.sb isEqualToString:@"sb1"]); + test(e.pb.pb == e.pb); + test([e.sde isEqualToString:@"sde1"]); + test(e.pd1); + test([e.pd1.sb isEqualToString:@"sb2"]); + test(e.pd1.pb == e.pd1); + test([e.pd1.sd1 isEqualToString:@"sd2"]); + test(e.pd1.pd1 == e.pd1); + [self called]; +} + +-(void) throwUnknownDerivedAsBaseResponse +{ + test(NO); +} + +-(void) throwUnknownDerivedAsBaseException:(ICEException*)ex +{ + test([[ex ice_name] isEqualToString:@"Test::BaseException"]); + TestSlicingObjectsClientBaseException* e = (TestSlicingObjectsClientBaseException*)ex; + test([e.sbe isEqualToString:@"sbe"]); + test(e.pb); + test([e.pb.sb isEqualToString:@"sb d2"]); + test(e.pb.pb == e.pb); + [self called]; +} + +-(void) useForwardResponse:(TestSlicingObjectsClientForward*)f +{ + test(f); + [self called]; +} + +-(void) useForwardException:(ICEException*)exc +{ + test(NO); +} + +-(void) responsePreserved1:(TestSlicingObjectsClientPBase*)res +{ + test([res isKindOfClass:[TestSlicingObjectsClientPDerived class]]); + TestSlicingObjectsClientPDerived* pd = (TestSlicingObjectsClientPDerived*)res; + test(pd); + test(pd.pi == 3); + test([pd.ps isEqualToString:@"preserved"]); + test([pd.pb isEqual:pd]); + [self called]; +} + +-(void) responsePreserved2:(TestSlicingObjectsClientPBase*)res +{ + test(![res isKindOfClass:[TestSlicingObjectsClientPCUnknown class]]); + test(res.pi == 3); + [self called]; +} + +-(void) responsePreserved3:(TestSlicingObjectsClientPBase*)res +{ + // + // Encoding 1.0 + // + test(![res isKindOfClass:[TestSlicingObjectsClientPCDerived class]]); + test(res.pi == 3); + [self called]; +} + +-(void) responsePreserved4:(TestSlicingObjectsClientPBase*)res +{ + // + // Encoding > 1.0 + // + test([res isKindOfClass:[TestSlicingObjectsClientPCDerived class]]); + TestSlicingObjectsClientPCDerived* p2 = (TestSlicingObjectsClientPCDerived*)res; + test(p2.pi == 3); + test([[p2.pbs objectAtIndex:0] isEqual:p2]); + [self called]; +} + +-(void) responsePreserved5:(TestSlicingObjectsClientPBase*)res +{ + test([res isKindOfClass:[TestSlicingObjectsClientPCDerived3 class]]); + TestSlicingObjectsClientPCDerived3* p3 = (TestSlicingObjectsClientPCDerived3*)res; + test(p3.pi == 3); + for(int i = 0; i < 300; ++i) + { + TestSlicingObjectsClientPCDerived2* p2 = (TestSlicingObjectsClientPCDerived2*)[p3.pbs objectAtIndex:i]; + test(p2.pi == i); + test([p2.pbs count] == 1); + test([[p2.pbs objectAtIndex:0] isEqual:[NSNull null]]); + test(p2.pcd2 == i); + } + test(p3.pcd2 == p3.pi); + test([p3.pcd3 isEqual:[p3.pbs objectAtIndex:10]]); + [self called]; +} + +-(void) responseCompactPreserved1:(TestSlicingObjectsClientPBase*)res +{ + // + // Encoding 1.0 + // + test(![res isKindOfClass:[TestSlicingObjectsClientCompactPCDerived class]]); + test(res.pi == 3); + [self called]; +} + +-(void) responseCompactPreserved2:(TestSlicingObjectsClientPBase*)res +{ + // + // Encoding > 1.0 + // + test([res isKindOfClass:[TestSlicingObjectsClientCompactPCDerived class]]); + TestSlicingObjectsClientCompactPCDerived* p2 = (TestSlicingObjectsClientCompactPCDerived*)res; + test(p2.pi == 3); + test([[p2.pbs objectAtIndex:0] isEqual:p2]); + [self called]; +} + +-(void) response +{ + test(NO); +} + +-(void) exception:(ICEException*)ex +{ + if(![ex isKindOfClass:[ICEOperationNotExistException class]]) + { + test(NO); + } + else + { + [self called]; + } +} + +@end + +id<TestSlicingObjectsClientTestIntfPrx> +slicingObjectsAllTests(id<ICECommunicator> communicator) +{ + id<ICEObjectPrx> obj = [communicator stringToProxy:@"Test:default -p 12010"]; + id<TestSlicingObjectsClientTestIntfPrx> test = [TestSlicingObjectsClientTestIntfPrx checkedCast:obj]; + + tprintf("base as Object... "); + { + ICEObject* o = nil; + @try + { + o = [test SBaseAsObject]; + test(o); + test([[o ice_id] isEqualToString:@"::Test::SBase"]); + } + @catch(...) + { + test(0); + } + + test([o isKindOfClass:[TestSlicingObjectsClientSBase class]]); + test([((TestSlicingObjectsClientSBase*)o).sb isEqualToString:@"SBase.sb"]); + } + tprintf("ok\n"); + + tprintf("base as Object (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_SBaseAsObject:^(ICEObject* o) { [cb SBaseAsObjectResponse:o]; } + exception:^(ICEException* ex) { [cb SBaseAsObjectException:ex]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("base as base... "); + { + TestSlicingObjectsClientSBase* sb; + @try + { + sb = [test SBaseAsSBase]; + test([sb.sb isEqualToString:@"SBase.sb"]); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("base as base (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_SBaseAsSBase:^(TestSlicingObjectsClientSBase* o) { [cb SBaseAsSBaseResponse:o]; } + exception:^(ICEException* e) { [cb SBaseAsSBaseException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("base with known derived as base... "); + { + TestSlicingObjectsClientSBase* sb = nil; + @try + { + sb = [test SBSKnownDerivedAsSBase]; + test([sb.sb isEqualToString:@"SBSKnownDerived.sb"]); + } + @catch(...) + { + test(0); + } + test([sb isKindOfClass:[TestSlicingObjectsClientSBSKnownDerived class]]); + test([((TestSlicingObjectsClientSBSKnownDerived*)sb).sbskd isEqualToString:@"SBSKnownDerived.sbskd"]); + } + tprintf("ok\n"); + + tprintf("base with known derived as base (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_SBSKnownDerivedAsSBase:^(TestSlicingObjectsClientSBase* o) { [cb SBSKnownDerivedAsSBaseResponse:o]; } exception:^(ICEException* e) { [cb SBSKnownDerivedAsSBaseException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("base with known derived as known derived... "); + { + TestSlicingObjectsClientSBSKnownDerived* sbskd; + @try + { + sbskd = [test SBSKnownDerivedAsSBSKnownDerived]; + test([sbskd.sbskd isEqualToString:@"SBSKnownDerived.sbskd"]); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("base with known derived as known derived (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_SBSKnownDerivedAsSBSKnownDerived:^(TestSlicingObjectsClientSBSKnownDerived* o) { [cb SBSKnownDerivedAsSBSKnownDerivedResponse:o]; } exception:^(ICEException* e) { [cb SBSKnownDerivedAsSBSKnownDerivedException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("base with unknown derived as base... "); + { + TestSlicingObjectsClientSBase* sb; + @try + { + sb = [test SBSUnknownDerivedAsSBase]; + test([sb.sb isEqualToString:@"SBSUnknownDerived.sb"]); + } + @catch(...) + { + test(0); + } + if([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]) + { + @try + { + // + // This test succeeds for the 1.0 encoding. + // + sb = [test SBSUnknownDerivedAsSBaseCompact]; + test([[sb sb] isEqual:@"SBSUnknownDerived.sb"]); + } + @catch(ICEOperationNotExistException*) + { + } + @catch(...) + { + test(NO); + } + } + else + { + @try + { + // + // This test fails when using the compact format because the instance cannot + // be sliced to a known type. + // + sb = [test SBSUnknownDerivedAsSBaseCompact]; + test(NO); + } + @catch(const ICEOperationNotExistException*) + { + } + @catch(const ICENoObjectFactoryException*) + { + // Expected. + } + @catch(...) + { + test(NO); + } + } + } + tprintf("ok\n"); + + tprintf("base with unknown derived as base (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_SBSUnknownDerivedAsSBase:^(TestSlicingObjectsClientSBase* o) { [cb SBSUnknownDerivedAsSBaseResponse:o]; } exception:^(ICEException* e) { [cb SBSUnknownDerivedAsSBaseException:e]; }]; + [cb check]; + } + if([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]) + { + // + // This test succeeds for the 1.0 encoding. + // + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_SBSUnknownDerivedAsSBaseCompact:^(TestSlicingObjectsClientSBase* o) { [cb SBSUnknownDerivedAsSBaseResponse:o]; } exception:^(ICEException* e) { [cb SBSUnknownDerivedAsSBaseException:e]; }]; + [cb check]; + } + else + { + // + // This test fails when using the compact format because the instance cannot + // be sliced to a known type. + // + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_SBSUnknownDerivedAsSBaseCompact:^(TestSlicingObjectsClientSBase* o) { [cb SBSUnknownDerivedAsSBaseCompactResponse:o]; } exception:^(ICEException* e) { [cb SBSUnknownDerivedAsSBaseCompactException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("unknown with Object as Object... "); + { + ICEObject* o; + @try + { + o = [test SUnknownAsObject]; + test(![[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]); + test([o isKindOfClass:[ICEUnknownSlicedObject class]]); + test([[((ICEUnknownSlicedObject*)o) getUnknownTypeId] isEqualToString:@"::Test::SUnknown"]); + [test checkSUnknown:o]; + } + @catch(ICENoObjectFactoryException*) + { + test([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]); + } + @catch(NSException* ex) + { + NSLog(@"exception: %@", ex); + test(0); + } + } + tprintf("ok\n"); + + tprintf("unknown with Object as Object (AMI)... "); + { + @try + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + if([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]) + { + [test begin_SUnknownAsObject:^(ICEObject* o) { [cb SUnknownAsObjectResponse10:o]; } + exception:^(ICEException* e) { [cb SUnknownAsObjectException10:e]; }]; + } + else + { + [test begin_SUnknownAsObject:^(ICEObject* o) { [cb SUnknownAsObjectResponse11:o]; } + exception:^(ICEException* e) { [cb SUnknownAsObjectException11:e]; }]; + } + [cb check]; + } + @catch(NSException*) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("one-element cycle... "); + { + @try + { + TestSlicingObjectsClientB* b = [test oneElementCycle]; + test(b); + test([[b ice_id] isEqualToString:@"::Test::B"]); + test([b.sb isEqualToString:@"B1.sb"]); + test([b.pb.sb isEqualToString:@"B1.sb"]); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("one-element cycle (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_oneElementCycle:^(TestSlicingObjectsClientB* o) { [cb oneElementCycleResponse:o]; } exception:^(ICEException* e) { [cb oneElementCycleException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("two-element cycle... "); + { + @try + { + TestSlicingObjectsClientB* b1 = [test twoElementCycle]; + test(b1); + test([[b1 ice_id] isEqualToString:@"::Test::B"]); + test([b1.sb isEqualToString:@"B1.sb"]); + + TestSlicingObjectsClientB* b2 = b1.pb; + test(b2); + test([[b2 ice_id] isEqualToString:@"::Test::B"]); + test([b2.sb isEqualToString:@"B2.sb"]); + test(b2.pb == b1); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("two-element cycle (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_twoElementCycle:^(TestSlicingObjectsClientB* o) { [cb twoElementCycleResponse:o]; } exception:^(ICEException* e) { [cb twoElementCycleException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("known derived pointer slicing as base... "); + { + @try + { + TestSlicingObjectsClientB* b1; + b1 = [test D1AsB]; + test(b1); + test([[b1 ice_id] isEqualToString:@"::Test::D1"]); + test([b1.sb isEqualToString:@"D1.sb"]); + test(b1.pb); + test(b1.pb != b1); + test([b1 isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* d1 = (TestSlicingObjectsClientD1*)b1; + test([d1.sd1 isEqualToString:@"D1.sd1"]); + test(d1.pd1); + test(d1.pd1 != b1); + test(b1.pb == d1.pd1); + + TestSlicingObjectsClientB* b2 = b1.pb; + test(b2); + test(b2.pb == b1); + test([b2.sb isEqualToString:@"D2.sb"]); + test([[b2 ice_id] isEqualToString:@"::Test::B"]); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("known derived pointer slicing as base (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_D1AsB:^(TestSlicingObjectsClientB* o) { [cb D1AsBResponse:o]; } exception:^(ICEException* e) { [cb D1AsBException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("known derived pointer slicing as derived... "); + { + @try + { + TestSlicingObjectsClientD1* d1; + d1 = [test D1AsD1]; + test(d1); + test([[d1 ice_id] isEqualToString:@"::Test::D1"]); + test([d1.sb isEqualToString:@"D1.sb"]); + test(d1.pb); + test(d1.pb != d1); + + TestSlicingObjectsClientB* b2 = d1.pb; + test(b2); + test([[b2 ice_id] isEqualToString:@"::Test::B"]); + test([b2.sb isEqualToString:@"D2.sb"]); + test(b2.pb == d1); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("known derived pointer slicing as derived (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_D1AsD1:^(TestSlicingObjectsClientD1* o) { [cb D1AsD1Response:o]; } exception:^(ICEException* e) { [cb D1AsD1Exception:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("unknown derived pointer slicing as base... "); + { + @try + { + TestSlicingObjectsClientB* b2; + b2 = [test D2AsB]; + test(b2); + test([[b2 ice_id] isEqualToString:@"::Test::B"]); + test([b2.sb isEqualToString:@"D2.sb"]); + test(b2.pb); + test(b2.pb != b2); + + TestSlicingObjectsClientB* b1 = b2.pb; + test(b1); + test([[b1 ice_id] isEqualToString:@"::Test::D1"]); + test([b1.sb isEqualToString:@"D1.sb"]); + test(b1.pb == b2); + test([b1 isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* d1 = (TestSlicingObjectsClientD1*)b1; + test([d1.sd1 isEqualToString:@"D1.sd1"]); + test(d1.pd1 == b2); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("unknown derived pointer slicing as base (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_D2AsB:^(TestSlicingObjectsClientB* o) { [cb D2AsBResponse:o]; } exception:^(ICEException* e) { [cb D2AsBException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("param ptr slicing with known first... "); + { + @try + { + TestSlicingObjectsClientB* b1; + TestSlicingObjectsClientB* b2; + [test paramTest1:&b1 p2:&b2]; + + test(b1); + test([[b1 ice_id] isEqualToString:@"::Test::D1"]); + test([b1.sb isEqualToString:@"D1.sb"]); + test(b1.pb == b2); + test([b1 isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* d1 = (TestSlicingObjectsClientD1*)b1; + test([d1.sd1 isEqualToString:@"D1.sd1"]); + test(d1.pd1 == b2); + + test(b2); + test([[b2 ice_id] isEqualToString:@"::Test::B"]); // No factory, must be sliced + test([b2.sb isEqualToString:@"D2.sb"]); + test(b2.pb == b1); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("param ptr slicing with known first (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_paramTest1:^(TestSlicingObjectsClientB* o, TestSlicingObjectsClientB* b2) { [cb paramTest1Response:o p2:b2]; } exception:^(ICEException* e) { [cb paramTest1Exception:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("param ptr slicing with unknown first... "); + { + @try + { + TestSlicingObjectsClientB* b2; + TestSlicingObjectsClientB* b1; + [test paramTest2:&b2 p1:&b1]; + + test(b1); + test([[b1 ice_id] isEqualToString:@"::Test::D1"]); + test([b1.sb isEqualToString:@"D1.sb"]); + test(b1.pb == b2); + test([b1 isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* d1 = (TestSlicingObjectsClientD1*)b1; + test([d1.sd1 isEqualToString:@"D1.sd1"]); + test(d1.pd1 == b2); + + test(b2); + test([[b2 ice_id] isEqualToString:@"::Test::B"]); // No factory, must be sliced + test([b2.sb isEqualToString:@"D2.sb"]); + test(b2.pb == b1); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("return value identity with known first... "); + { + @try + { + TestSlicingObjectsClientB* p1; + TestSlicingObjectsClientB* p2; + TestSlicingObjectsClientB* r = [test returnTest1:&p1 p2:&p2]; + test(r == p1); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("return value identity with known first (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_returnTest1:^(TestSlicingObjectsClientB* o, TestSlicingObjectsClientB* b1, TestSlicingObjectsClientB* b2) { [cb returnTest1Response:o p1:b1 p2:b2]; } exception:^(ICEException* e) { [cb returnTest1Exception:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("return value identity with unknown first... "); + { + @try + { + TestSlicingObjectsClientB* p1; + TestSlicingObjectsClientB* p2; + TestSlicingObjectsClientB* r = [test returnTest2:&p1 p1:&p2]; + test(r == p1); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("return value identity with unknown first (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_returnTest2:^(TestSlicingObjectsClientB* o, TestSlicingObjectsClientB* b1, TestSlicingObjectsClientB* b2) { [cb returnTest2Response:o p1:b1 p2:b2]; } exception:^(ICEException* e) { [cb returnTest2Exception:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("return value identity for input params known first... "); + { + @try + { + TestSlicingObjectsClientD1* d1 = [TestSlicingObjectsClientD1 d1]; + d1.sb = @"D1.sb"; + d1.sd1 = @"D1.sd1"; + TestSlicingObjectsClientD3* d3 = [TestSlicingObjectsClientD3 d3]; + d3.pb = d1; + d3.sb = @"D3.sb"; + d3.sd3 = @"D3.sd3"; + d3.pd3 = d1; + d1.pb = d3; + d1.pd1 = d3; + + TestSlicingObjectsClientB* b1 = [test returnTest3:d1 p2:d3]; + + test(b1); + test([b1.sb isEqualToString:@"D1.sb"]); + test([[b1 ice_id] isEqualToString:@"::Test::D1"]); + test([b1 isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* p1 = (TestSlicingObjectsClientD1*)b1; + test([p1.sd1 isEqualToString:@"D1.sd1"]); + test(p1.pd1 == b1.pb); + + TestSlicingObjectsClientB* b2 = b1.pb; + test(b2); + test([b2.sb isEqualToString:@"D3.sb"]); + test([[b2 ice_id] isEqualToString:@"::Test::B"]); // Sliced by server + test(b2.pb == b1); + test(![b2 isKindOfClass:[TestSlicingObjectsClientD3 class]]); + + test(b1 != d1); + test(b1 != d3); + test(b2 != d1); + test(b2 != d3); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("return value identity for input params known first (AMI)... "); + { + @try + { + TestSlicingObjectsClientD1* d1 = [TestSlicingObjectsClientD1 d1]; + d1.sb = @"D1.sb"; + d1.sd1 = @"D1.sd1"; + TestSlicingObjectsClientD3* d3 = [TestSlicingObjectsClientD3 d3]; + d3.pb = d1; + d3.sb = @"D3.sb"; + d3.sd3 = @"D3.sd3"; + d3.pd3 = d1; + d1.pb = d3; + d1.pd1 = d3; + + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_returnTest3:d1 p2:d3 response:^(TestSlicingObjectsClientB* o) { [cb returnTest3Response:o]; } exception:^(ICEException* e) { [cb returnTest3Exception:e]; }]; + [cb check]; + TestSlicingObjectsClientB* b1 = cb.r; + + test(b1); + test([b1.sb isEqualToString:@"D1.sb"]); + test([[b1 ice_id:nil] isEqualToString:@"::Test::D1"]); + test([b1 isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* p1 = (TestSlicingObjectsClientD1*)b1; + test([p1.sd1 isEqualToString:@"D1.sd1"]); + test(p1.pd1 == b1.pb); + + TestSlicingObjectsClientB* b2 = b1.pb; + test(b2); + test([b2.sb isEqualToString:@"D3.sb"]); + test([[b2 ice_id:nil] isEqualToString:@"::Test::B"]); // Sliced by server + test(b2.pb == b1); + test(![b2 isKindOfClass:[TestSlicingObjectsClientD3 class]]); + + test(b1 != d1); + test(b1 != d3); + test(b2 != d1); + test(b2 != d3); + } + @catch(NSException*) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("return value identity for input params unknown first... "); + { + @try + { + TestSlicingObjectsClientD1* d1 = [TestSlicingObjectsClientD1 d1]; + d1.sb = @"D1.sb"; + d1.sd1 = @"D1.sd1"; + TestSlicingObjectsClientD3* d3 = [TestSlicingObjectsClientD3 d3]; + d3.pb = d1; + d3.sb = @"D3.sb"; + d3.sd3 = @"D3.sd3"; + d3.pd3 = d1; + d1.pb = d3; + d1.pd1 = d3; + + TestSlicingObjectsClientB* b1 = [test returnTest3:d3 p2:d1]; + + test(b1); + test([b1.sb isEqualToString:@"D3.sb"]); + test([[b1 ice_id] isEqualToString:@"::Test::B"]); // Sliced by server + test(![b1 isKindOfClass:[TestSlicingObjectsClientD3 class]]); + + TestSlicingObjectsClientB* b2 = b1.pb; + test(b2); + test([b2.sb isEqualToString:@"D1.sb"]); + test([[b2 ice_id] isEqualToString:@"::Test::D1"]); + test(b2.pb == b1); + test([b2 isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* p3 = (TestSlicingObjectsClientD1*)b2; + test([p3.sd1 isEqualToString:@"D1.sd1"]); + test(p3.pd1 == b1); + + test(b1 != d1); + test(b1 != d3); + test(b2 != d1); + test(b2 != d3); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("return value identity for input params unknown first (AMI)... "); + { + @try + { + TestSlicingObjectsClientD1* d1 = [TestSlicingObjectsClientD1 d1]; + d1.sb = @"D1.sb"; + d1.sd1 = @"D1.sd1"; + TestSlicingObjectsClientD3* d3 = [TestSlicingObjectsClientD3 d3]; + d3.pb = d1; + d3.sb = @"D3.sb"; + d3.sd3 = @"D3.sd3"; + d3.pd3 = d1; + d1.pb = d3; + d1.pd1 = d3; + + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_returnTest3:d3 p2:d1 response:^(TestSlicingObjectsClientB* o) { [cb returnTest3Response:o]; } exception:^(ICEException* e) { [cb returnTest3Exception:e]; }]; + [cb check]; + TestSlicingObjectsClientB* b1 = cb.r; + + test(b1); + test([b1.sb isEqualToString:@"D3.sb"]); + test([[b1 ice_id:nil] isEqualToString:@"::Test::B"]); // Sliced by server + test(![b1 isKindOfClass:[TestSlicingObjectsClientD3 class]]); + + TestSlicingObjectsClientB* b2 = b1.pb; + test(b2); + test([b2.sb isEqualToString:@"D1.sb"]); + test([[b2 ice_id:nil] isEqualToString:@"::Test::D1"]); + test(b2.pb == b1); + test([b2 isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* p3 = (TestSlicingObjectsClientD1*)b2; + test([p3.sd1 isEqualToString:@"D1.sd1"]); + test(p3.pd1 == b1); + + test(b1 != d1); + test(b1 != d3); + test(b2 != d1); + test(b2 != d3); + } + @catch(NSException*) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("remainder unmarshaling (3 instances)... "); + { + @try + { + TestSlicingObjectsClientB* p1; + TestSlicingObjectsClientB* p2; + TestSlicingObjectsClientB* ret = [test paramTest3:&p1 p2:&p2]; + + test(p1); + test([p1.sb isEqualToString:@"D2.sb (p1 1)"]); + test(!p1.pb); + test([[p1 ice_id] isEqualToString:@"::Test::B"]); + + test(p2); + test([p2.sb isEqualToString:@"D2.sb (p2 1)"]); + test(!p2.pb); + test([[p2 ice_id] isEqualToString:@"::Test::B"]); + + test(ret); + test([ret.sb isEqualToString:@"D1.sb (p2 2)"]); + test(!ret.pb); + test([[ret ice_id] isEqualToString:@"::Test::D1"]); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("remainder unmarshaling (3 instances) (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_paramTest3:^(TestSlicingObjectsClientB* o, TestSlicingObjectsClientB* b1, TestSlicingObjectsClientB* b2) { [cb paramTest3Response:o p1:b1 p2:b2]; } exception:^(ICEException* e) { [cb paramTest3Exception:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("remainder unmarshaling (4 instances)... "); + { + @try + { + TestSlicingObjectsClientB* b; + TestSlicingObjectsClientB* ret = [test paramTest4:&b]; + + test(b); + test([b.sb isEqualToString:@"D4.sb (1)"]); + test(!b.pb); + test([[b ice_id] isEqualToString:@"::Test::B"]); + + test(ret); + test([ret.sb isEqualToString:@"B.sb (2)"]); + test(!ret.pb); + test([[ret ice_id] isEqualToString:@"::Test::B"]); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("remainder unmarshaling (4 instances) (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_paramTest4:^(TestSlicingObjectsClientB* o, TestSlicingObjectsClientB* b) { [cb paramTest4Response:o p1:b]; } exception:^(ICEException* e) { [cb paramTest4Exception:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("param ptr slicing, instance marshaled in unknown derived as base... "); + { + @try + { + TestSlicingObjectsClientB* b1 = [TestSlicingObjectsClientB b]; + b1.sb = @"B.sb(1)"; + b1.pb = b1; + + TestSlicingObjectsClientD3* d3 = [TestSlicingObjectsClientD3 d3]; + d3.sb = @"D3.sb"; + d3.pb = d3; + d3.sd3 = @"D3.sd3"; + d3.pd3 = b1; + + TestSlicingObjectsClientB* b2 = [TestSlicingObjectsClientB b]; + b2.sb = @"B.sb(2)"; + b2.pb = b1; + + TestSlicingObjectsClientB* r = [test returnTest3:d3 p2:b2]; + + test(r); + test([[r ice_id] isEqualToString:@"::Test::B"]); + test([r.sb isEqualToString:@"D3.sb"]); + test(r.pb == r); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("param ptr slicing, instance marshaled in unknown derived as base (AMI)... "); + { + @try + { + TestSlicingObjectsClientB* b1 = [TestSlicingObjectsClientB b]; + b1.sb = @"B.sb(1)"; + b1.pb = b1; + + TestSlicingObjectsClientD3* d3 = [TestSlicingObjectsClientD3 d3]; + d3.sb = @"D3.sb"; + d3.pb = d3; + d3.sd3 = @"D3.sd3"; + d3.pd3 = b1; + + TestSlicingObjectsClientB* b2 = [TestSlicingObjectsClientB b]; + b2.sb = @"B.sb(2)"; + b2.pb = b1; + + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_returnTest3:d3 p2:b2 response:^(TestSlicingObjectsClientB* o) { [cb returnTest3Response:o]; } exception:^(ICEException* e) { [cb returnTest3Exception:e]; }]; + [cb check]; + TestSlicingObjectsClientB* r = cb.r; + + test(r); + test([[r ice_id:nil] isEqualToString:@"::Test::B"]); + test([r.sb isEqualToString:@"D3.sb"]); + test(r.pb == r); + } + @catch(NSException*) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("param ptr slicing, instance marshaled in unknown derived as derived... "); + { + @try + { + TestSlicingObjectsClientD1* d11 = [TestSlicingObjectsClientD1 d1]; + d11.sb = @"D1.sb(1)"; + d11.pb = d11; + d11.sd1 = @"D1.sd1(1)"; + + TestSlicingObjectsClientD3* d3 = [TestSlicingObjectsClientD3 d3]; + d3.sb = @"D3.sb"; + d3.pb = d3; + d3.sd3 = @"D3.sd3"; + d3.pd3 = d11; + + TestSlicingObjectsClientD1* d12 = [TestSlicingObjectsClientD1 d1]; + d12.sb = @"D1.sb(2)"; + d12.pb = d12; + d12.sd1 = @"D1.sd1(2)"; + d12.pd1 = d11; + + TestSlicingObjectsClientB* r = [test returnTest3:d3 p2:d12]; + test(r); + test([[r ice_id] isEqualToString:@"::Test::B"]); + test([r.sb isEqualToString:@"D3.sb"]); + test(r.pb == r); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("param ptr slicing, instance marshaled in unknown derived as derived (AMI)... "); + { + @try + { + TestSlicingObjectsClientD1* d11 = [TestSlicingObjectsClientD1 d1]; + d11.sb = @"D1.sb(1)"; + d11.pb = d11; + d11.sd1 = @"D1.sd1(1)"; + + TestSlicingObjectsClientD3* d3 = [TestSlicingObjectsClientD3 d3]; + d3.sb = @"D3.sb"; + d3.pb = d3; + d3.sd3 = @"D3.sd3"; + d3.pd3 = d11; + + TestSlicingObjectsClientD1* d12 = [TestSlicingObjectsClientD1 d1]; + d12.sb = @"D1.sb(2)"; + d12.pb = d12; + d12.sd1 = @"D1.sd1(2)"; + d12.pd1 = d11; + + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_returnTest3:d3 p2:d12 response:^(TestSlicingObjectsClientB* o) { [cb returnTest3Response:o]; } exception:^(ICEException* e) { [cb returnTest3Exception:e]; }]; + [cb check]; + TestSlicingObjectsClientB* r = cb.r; + test(r); + test([[r ice_id:nil] isEqualToString:@"::Test::B"]); + test([r.sb isEqualToString:@"D3.sb"]); + test(r.pb == r); + } + @catch(NSException*) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("sequence slicing... "); + { + @try + { + TestSlicingObjectsClientSS* ss; + { + TestSlicingObjectsClientB* ss1b = [TestSlicingObjectsClientB b]; + ss1b.sb = @"B.sb"; + ss1b.pb = ss1b; + + TestSlicingObjectsClientD1* ss1d1 = [TestSlicingObjectsClientD1 d1]; + ss1d1.sb = @"D1.sb"; + ss1d1.sd1 = @"D1.sd1"; + ss1d1.pb = ss1b; + + TestSlicingObjectsClientD3* ss1d3 = [TestSlicingObjectsClientD3 d3]; + ss1d3.sb = @"D3.sb"; + ss1d3.sd3 = @"D3.sd3"; + ss1d3.pb = ss1b; + + TestSlicingObjectsClientB* ss2b = [TestSlicingObjectsClientB b]; + ss2b.sb = @"B.sb"; + ss2b.pb = ss1b; + + TestSlicingObjectsClientD1* ss2d1 = [TestSlicingObjectsClientD1 d1]; + ss2d1.sb = @"D1.sb"; + ss2d1.sd1 = @"D1.sd1"; + ss2d1.pb = ss2b; + + TestSlicingObjectsClientD3* ss2d3 = [TestSlicingObjectsClientD3 d3]; + ss2d3.sb = @"D3.sb"; + ss2d3.sd3 = @"D3.sd3"; + ss2d3.pb = ss2b; + + ss1d1.pd1 = ss2b; + ss1d3.pd3 = ss2d1; + + ss2d1.pd1 = ss1d3; + ss2d3.pd3 = ss1d1; + + TestSlicingObjectsClientSS1* ss1 = [TestSlicingObjectsClientSS1 sS1]; + ss1.s = [TestSlicingObjectsClientMutableBSeq arrayWithCapacity:0]; + [(TestSlicingObjectsClientMutableBSeq*)ss1.s addObject:ss1b]; + [(TestSlicingObjectsClientMutableBSeq*)ss1.s addObject:ss1d1]; + [(TestSlicingObjectsClientMutableBSeq*)ss1.s addObject:ss1d3]; + + TestSlicingObjectsClientSS2* ss2 = [TestSlicingObjectsClientSS2 sS2]; + ss2.s = [TestSlicingObjectsClientMutableBSeq arrayWithCapacity:0]; + [(TestSlicingObjectsClientMutableBSeq*)ss2.s addObject:ss2b]; + [(TestSlicingObjectsClientMutableBSeq*)ss2.s addObject:ss2d1]; + [(TestSlicingObjectsClientMutableBSeq*)ss2.s addObject:ss2d3]; + + ss = [test sequenceTest:ss1 p2:ss2]; + } + + test(ss.c1); + TestSlicingObjectsClientB* ss1b = [ss.c1.s objectAtIndex:0]; + TestSlicingObjectsClientB* ss1d1 = [ss.c1.s objectAtIndex:1]; + test(ss.c2); + TestSlicingObjectsClientB* ss1d3 = [ss.c1.s objectAtIndex:2]; + + test(ss.c2); + TestSlicingObjectsClientB* ss2b = [ss.c2.s objectAtIndex:0]; + TestSlicingObjectsClientB* ss2d1 = [ss.c2.s objectAtIndex:1]; + TestSlicingObjectsClientB* ss2d3 = [ss.c2.s objectAtIndex:2]; + + test(ss1b.pb == ss1b); + test(ss1d1.pb == ss1b); + test(ss1d3.pb == ss1b); + + test(ss2b.pb == ss1b); + test(ss2d1.pb == ss2b); + test(ss2d3.pb == ss2b); + + test([[ss1b ice_id] isEqualToString:@"::Test::B"]); + test([[ss1d1 ice_id] isEqualToString:@"::Test::D1"]); + test([[ss1d3 ice_id] isEqualToString:@"::Test::B"]); + + test([[ss2b ice_id] isEqualToString:@"::Test::B"]); + test([[ss2d1 ice_id] isEqualToString:@"::Test::D1"]); + test([[ss2d3 ice_id] isEqualToString:@"::Test::B"]); + } + @catch(ICEException*) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("sequence slicing (AMI)... "); + { + @try + { + TestSlicingObjectsClientSS* ss; + { + TestSlicingObjectsClientB* ss1b = [TestSlicingObjectsClientB b]; + ss1b.sb = @"B.sb"; + ss1b.pb = ss1b; + + TestSlicingObjectsClientD1* ss1d1 = [TestSlicingObjectsClientD1 d1]; + ss1d1.sb = @"D1.sb"; + ss1d1.sd1 = @"D1.sd1"; + ss1d1.pb = ss1b; + + TestSlicingObjectsClientD3* ss1d3 = [TestSlicingObjectsClientD3 d3]; + ss1d3.sb = @"D3.sb"; + ss1d3.sd3 = @"D3.sd3"; + ss1d3.pb = ss1b; + + TestSlicingObjectsClientB* ss2b = [TestSlicingObjectsClientB b]; + ss2b.sb = @"B.sb"; + ss2b.pb = ss1b; + + TestSlicingObjectsClientD1* ss2d1 = [TestSlicingObjectsClientD1 d1]; + ss2d1.sb = @"D1.sb"; + ss2d1.sd1 = @"D1.sd1"; + ss2d1.pb = ss2b; + + TestSlicingObjectsClientD3* ss2d3 = [TestSlicingObjectsClientD3 d3]; + ss2d3.sb = @"D3.sb"; + ss2d3.sd3 = @"D3.sd3"; + ss2d3.pb = ss2b; + + ss1d1.pd1 = ss2b; + ss1d3.pd3 = ss2d1; + + ss2d1.pd1 = ss1d3; + ss2d3.pd3 = ss1d1; + + TestSlicingObjectsClientSS1* ss1 = [TestSlicingObjectsClientSS1 sS1]; + ss1.s = [TestSlicingObjectsClientMutableBSeq array]; + [(NSMutableArray*)ss1.s addObject:ss1b]; + [(NSMutableArray*)ss1.s addObject:ss1d1]; + [(NSMutableArray*)ss1.s addObject:ss1d3]; + + TestSlicingObjectsClientSS2* ss2 = [TestSlicingObjectsClientSS2 sS2]; + ss2.s = [TestSlicingObjectsClientMutableBSeq array]; + [(NSMutableArray*)ss2.s addObject:ss2b]; + [(NSMutableArray*)ss2.s addObject:ss2d1]; + [(NSMutableArray*)ss2.s addObject:ss2d3]; + + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_sequenceTest:ss1 p2:ss2 response:^(TestSlicingObjectsClientSS* o) { [cb sequenceTestResponse:o]; } exception:^(ICEException* e) { [cb sequenceTestException:e]; }]; + [cb check]; + ss = cb.r; + } + + test(ss.c1); + TestSlicingObjectsClientB* ss1b = [ss.c1.s objectAtIndex:0]; + TestSlicingObjectsClientB* ss1d1 = [ss.c1.s objectAtIndex:1]; + test(ss.c2); + TestSlicingObjectsClientB* ss1d3 = [ss.c1.s objectAtIndex:2]; + + test(ss.c2); + TestSlicingObjectsClientB* ss2b = [ss.c2.s objectAtIndex:0]; + TestSlicingObjectsClientB* ss2d1 = [ss.c2.s objectAtIndex:1]; + TestSlicingObjectsClientB* ss2d3 = [ss.c2.s objectAtIndex:2]; + + test(ss1b.pb == ss1b); + test(ss1d1.pb == ss1b); + test(ss1d3.pb == ss1b); + + test(ss2b.pb == ss1b); + test(ss2d1.pb == ss2b); + test(ss2d3.pb == ss2b); + + test([[ss1b ice_id:nil] isEqualToString:@"::Test::B"]); + test([[ss1d1 ice_id:nil] isEqualToString:@"::Test::D1"]); + test([[ss1d3 ice_id:nil] isEqualToString:@"::Test::B"]); + + test([[ss2b ice_id:nil] isEqualToString:@"::Test::B"]); + test([[ss2d1 ice_id:nil] isEqualToString:@"::Test::D1"]); + test([[ss2d3 ice_id:nil] isEqualToString:@"::Test::B"]); + } + @catch(ICEException*) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("dictionary slicing... "); + { + @try + { + TestSlicingObjectsClientMutableBDict* bin = [TestSlicingObjectsClientMutableBDict dictionary]; + TestSlicingObjectsClientMutableBDict* bout; + TestSlicingObjectsClientBDict* r; + int i; + for(i = 0; i < 10; ++i) + { + TestSlicingObjectsClientD1* d1 = [TestSlicingObjectsClientD1 d1]; + NSString *s = [@"D1." stringByAppendingString:[NSString stringWithFormat:@"%d", i]]; + d1.sb = s; + d1.pb = d1; + d1.sd1 = s; + [bin setObject:d1 forKey:[NSNumber numberWithInt:i]]; + } + + r = [test dictionaryTest:bin bout:&bout]; + + test([bout count] == 10); + for(i = 0; i < 10; ++i) + { + TestSlicingObjectsClientB* b = [bout objectForKey:[NSNumber numberWithInt:i * 10]]; + test(b); + NSString *s = [@"D1." stringByAppendingString:[NSString stringWithFormat:@"%d", i]]; + test([b.sb isEqualToString:s]); + test(b.pb); + test(b.pb != b); + test([b.pb.sb isEqualToString:s]); + test(b.pb.pb == b.pb); + } + + test([r count] == 10); + for(i = 0; i < 10; ++i) + { + TestSlicingObjectsClientB* b = [r objectForKey:[NSNumber numberWithInt:i * 20]]; + test(b); + NSString *s = [@"D1." stringByAppendingString:[NSString stringWithFormat:@"%d", i * 20]]; + test([b.sb isEqualToString:s]); + test(b.pb == (i == 0 ? nil : [r objectForKey:[NSNumber numberWithInt:(i - 1) * 20]])); + test([b isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* d1 = (TestSlicingObjectsClientD1*)b; + test([d1.sd1 isEqualToString:s]); + test(d1.pd1 == d1); + } + } + @catch(ICEException*) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("dictionary slicing (AMI)... "); + { + @try + { + TestSlicingObjectsClientMutableBDict* bin = [TestSlicingObjectsClientMutableBDict dictionary]; + TestSlicingObjectsClientMutableBDict* bout; + TestSlicingObjectsClientMutableBDict* r; + int i; + for(i = 0; i < 10; ++i) + { + TestSlicingObjectsClientD1* d1 = [TestSlicingObjectsClientD1 d1]; + d1.sb = [NSString stringWithFormat:@"D1.%d",i]; + d1.pb = d1; + d1.sd1 = d1.sb; + [bin setObject:d1 forKey:[NSNumber numberWithInt:i]]; + } + + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_dictionaryTest:bin response:^(TestSlicingObjectsClientMutableBDict* o, TestSlicingObjectsClientMutableBDict* bout) { [cb dictionaryTestResponse:o bout:bout]; } exception:^(ICEException* e) { [cb dictionaryTestException:e]; }]; + [cb check]; + bout = cb.bout; + r = cb.r; + + test([bout count] == 10); + for(i = 0; i < 10; ++i) + { + TestSlicingObjectsClientB* b = [bout objectForKey:[NSNumber numberWithInt:(i * 10)]]; + test(b); + NSString* s = [NSString stringWithFormat:@"D1.%d",i]; + test([b.sb isEqualToString:s]); + test(b.pb); + test(b.pb != b); + test([b.pb.sb isEqualToString:s]); + test(b.pb.pb == b.pb); + } + + test([r count] == 10); + for(i = 0; i < 10; ++i) + { + TestSlicingObjectsClientB* b = [r objectForKey:[NSNumber numberWithInt:(i * 20)]]; + test(b); + NSString* s = [NSString stringWithFormat:@"D1.%d",(i * 20)]; + test([b.sb isEqualToString:s]); + test(b.pb == (i == 0 ? nil : [r objectForKey:[NSNumber numberWithInt:((i - 1) * 20)]])); + test([b isKindOfClass:[TestSlicingObjectsClientD1 class]]); + TestSlicingObjectsClientD1* d1 = (TestSlicingObjectsClientD1*)b; + test([d1.sd1 isEqualToString:s]); + test(d1.pd1 == d1); + } + } + @catch(ICEException*) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("base exception thrown as base exception... "); + { + @try + { + [test throwBaseAsBase]; + test(0); + } + @catch(TestSlicingObjectsClientBaseException* e) + { + test([[e ice_name] isEqualToString: @"Test::BaseException"]); + test([e.sbe isEqualToString:@"sbe"]); + test(e.pb); + test([e.pb.sb isEqualToString:@"sb"]); + test(e.pb.pb == e.pb); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("base exception thrown as base exception (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_throwBaseAsBase:^ { [cb throwBaseAsBaseResponse]; } exception:^(ICEException* e) { [cb throwBaseAsBaseException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("derived exception thrown as base exception... "); + { + @try + { + [test throwDerivedAsBase]; + test(0); + } + @catch(TestSlicingObjectsClientDerivedException* e) + { + test([[e ice_name] isEqualToString:@"Test::DerivedException"]); + test([e.sbe isEqualToString:@"sbe"]); + test(e.pb); + test([e.pb.sb isEqualToString:@"sb1"]); + test(e.pb.pb == e.pb); + test([e.sde isEqualToString:@"sde1"]); + test(e.pd1); + test([e.pd1.sb isEqualToString:@"sb2"]); + test(e.pd1.pb == e.pd1); + test([e.pd1.sd1 isEqualToString:@"sd2"]); + test(e.pd1.pd1 == e.pd1); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("derived exception thrown as base exception (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_throwDerivedAsBase:^ { [cb throwDerivedAsBaseResponse]; } exception:^(ICEException* e) { [cb throwDerivedAsBaseException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("derived exception thrown as derived exception... "); + { + @try + { + [test throwDerivedAsDerived]; + test(0); + } + @catch(TestSlicingObjectsClientDerivedException* e) + { + test([[e ice_name] isEqualToString:@"Test::DerivedException"]); + test([e.sbe isEqualToString:@"sbe"]); + test(e.pb); + test([e.pb.sb isEqualToString:@"sb1"]); + test(e.pb.pb == e.pb); + test([e.sde isEqualToString:@"sde1"]); + test(e.pd1); + test([e.pd1.sb isEqualToString:@"sb2"]); + test(e.pd1.pb == e.pd1); + test([e.pd1.sd1 isEqualToString:@"sd2"]); + test(e.pd1.pd1 == e.pd1); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("derived exception thrown as derived exception (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_throwDerivedAsDerived:^ { [cb throwDerivedAsDerivedResponse]; } exception:^(ICEException* e) { [cb throwDerivedAsDerivedException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("unknown derived exception thrown as base exception... "); + { + @try + { + [test throwUnknownDerivedAsBase]; + test(0); + } + @catch(TestSlicingObjectsClientBaseException* e) + { + test([[e ice_name] isEqualToString:@"Test::BaseException"]); + test([e.sbe isEqualToString:@"sbe"]); + test(e.pb); + test([e.pb.sb isEqualToString:@"sb d2"]); + test(e.pb.pb == e.pb); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("unknown derived exception thrown as base exception (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_throwUnknownDerivedAsBase:^ { [cb throwUnknownDerivedAsBaseResponse]; } exception:^(ICEException* e) { [cb throwUnknownDerivedAsBaseException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("forward-declared class... "); + { + @try + { + TestSlicingObjectsClientForward* f; + [test useForward:&f]; + test(f); + } + @catch(...) + { + test(0); + } + } + tprintf("ok\n"); + + tprintf("forward-declared class (AMI)... "); + { + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_useForward:^(TestSlicingObjectsClientForward* o) { [cb useForwardResponse:o]; } exception:^(ICEException* e) { [cb useForwardException:e]; }]; + [cb check]; + } + tprintf("ok\n"); + + tprintf("preserved classes... "); + @try + { + // + // Server knows the most-derived class PDerived. + // + TestSlicingObjectsClientPDerived* pd = [TestSlicingObjectsClientPDerived pDerived]; + pd.pi = 3; + pd.ps = @"preserved"; + pd.pb = pd; + + TestSlicingObjectsClientPBase* r = [test exchangePBase:pd]; + TestSlicingObjectsClientPDerived* p2 = (TestSlicingObjectsClientPDerived*)r; + test(p2); + test(p2.pi == 3); + test([p2.ps isEqual:@"preserved"]); + test(p2.pb == p2); + } + @catch(ICEOperationNotExistException*) + { + } + + @try + { + // + // Server only knows the base (non-preserved) type, so the object is sliced. + // + TestSlicingObjectsClientPCUnknown* pu = [TestSlicingObjectsClientPCUnknown pCUnknown]; + pu.pi = 3; + pu.pu = @"preserved"; + + TestSlicingObjectsClientPBase* r = [test exchangePBase:pu]; + test(![r isKindOfClass:[TestSlicingObjectsClientPCUnknown class]]); + test(r.pi == 3); + } + @catch(ICEOperationNotExistException*) + { + } + + @try + { + // + // Server only knows the intermediate type Preserved. The object will be sliced to + // Preserved for the 1.0 encoding; otherwise it should be returned intact. + // + TestSlicingObjectsClientPCDerived* pcd = [TestSlicingObjectsClientPCDerived pCDerived]; + pcd.pi = 3; + pcd.pbs = [NSArray arrayWithObjects:pcd, nil]; + + TestSlicingObjectsClientPBase* r = [test exchangePBase:pcd]; + + if([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]) + { + test(![r isKindOfClass:[TestSlicingObjectsClientPCDerived class]]); + test(r.pi == 3); + } + else + { + test([r isKindOfClass:[TestSlicingObjectsClientPCDerived class]]); + TestSlicingObjectsClientPCDerived* p2 = (TestSlicingObjectsClientPCDerived*)r; + test(p2); + test(p2.pi == 3); + test([[[p2 pbs] objectAtIndex:0] isEqual:p2]); + } + } + @catch(ICEOperationNotExistException*) + { + } + + @try + { + // + // Server only knows the intermediate type CompactPDerived. The object will be sliced to + // CompactPDerived for the 1.0 encoding; otherwise it should be returned intact. + // + TestSlicingObjectsClientCompactPCDerived* pcd = [TestSlicingObjectsClientCompactPCDerived compactPCDerived]; + pcd.pi = 3; + pcd.pbs = [NSArray arrayWithObjects:pcd, nil]; + + TestSlicingObjectsClientPBase* r = [test exchangePBase:pcd]; + + if([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]) + { + test(![r isKindOfClass:[TestSlicingObjectsClientCompactPCDerived class]]); + test(r.pi == 3); + } + else + { + test([r isKindOfClass:[TestSlicingObjectsClientCompactPCDerived class]]); + TestSlicingObjectsClientCompactPCDerived* p2 = (TestSlicingObjectsClientCompactPCDerived*)r; + test(p2); + test(p2.pi == 3); + test([p2.pbs objectAtIndex:0] == p2); + } + } + @catch(ICEOperationNotExistException*) + { + } + + @try + { + // + // Send an object that will have multiple preserved slices in the server. + // The object will be sliced to Preserved for the 1.0 encoding. + // + TestSlicingObjectsClientPCDerived3* pcd = [TestSlicingObjectsClientPCDerived3 pCDerived3]; + pcd.pi = 3; + // + // Sending more than 254 objects exercises the encoding for object ids. + // + int i; + pcd.pbs = [NSArray array]; + for(i = 0; i < 300; ++i) + { + TestSlicingObjectsClientPCDerived2* p2 = [TestSlicingObjectsClientPCDerived2 pCDerived2]; + p2.pi = i; + p2.pbs = [NSArray arrayWithObjects:[NSNull null], nil]; // Nil reference. This slice should not have an indirection table. + p2.pcd2 = i; + pcd.pbs = [pcd.pbs arrayByAddingObject:p2]; + } + pcd.pcd2 = pcd.pi; + pcd.pcd3 = [pcd.pbs objectAtIndex:10]; + + TestSlicingObjectsClientPBase* r = [test exchangePBase:pcd]; + if([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]) + { + test(![r isKindOfClass:[TestSlicingObjectsClientPCDerived3 class]]); + test([r isKindOfClass:[TestSlicingObjectsClientPreserved class]]); + test(r.pi == 3); + } + else + { + test([r isKindOfClass:[TestSlicingObjectsClientPCDerived3 class]]); + TestSlicingObjectsClientPCDerived3* p3 = (TestSlicingObjectsClientPCDerived3*)r; + test(p3.pi == 3); + for(i = 0; i < 300; ++i) + { + TestSlicingObjectsClientPCDerived2* p2 = (TestSlicingObjectsClientPCDerived2*)[p3.pbs objectAtIndex:i]; + test(p2.pi == i); + test([p2.pbs count] == 1); + test([[p2.pbs objectAtIndex:0] isEqual:[NSNull null]]); + test(p2.pcd2 == i); + } + test(p3.pcd2 == p3.pi); + test(p3.pcd3 == [p3.pbs objectAtIndex:10]); + } + } + @catch(ICEOperationNotExistException*) + { + } + + @try + { + // + // Obtain an object with preserved slices and send it back to the server. + // The preserved slices should be excluded for the 1.0 encoding, otherwise + // they should be included. + // + TestSlicingObjectsClientPreserved* p = [test PBSUnknownAsPreserved]; + [test checkPBSUnknown:p]; + if(![[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]) + { + [[test ice_encodingVersion:ICEEncoding_1_0] checkPBSUnknown:p]; + } + } + @catch(ICEOperationNotExistException*) + { + } + + tprintf("ok\n"); + + tprintf("preserved classes (AMI)... "); + { + // + // Server knows the most-derived class PDerived. + // + TestSlicingObjectsClientPDerived* pd = [TestSlicingObjectsClientPDerived pDerived]; + pd.pi = 3; + pd.ps = @"preserved"; + pd.pb = pd; + + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_exchangePBase:pd + response:^(TestSlicingObjectsClientPBase* o) { [cb responsePreserved1:o]; } + exception:^(ICEException* ex) { [cb exception:ex]; }]; + [cb check]; + } + + { + TestSlicingObjectsClientPCUnknown* pu = [TestSlicingObjectsClientPCUnknown pCUnknown]; + pu.pi = 3; + pu.pu = @"preserved"; + + // + // Server only knows the base (non-preserved) type, so the object is sliced. + // + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + [test begin_exchangePBase:pu + response:^(TestSlicingObjectsClientPBase* o) { [cb responsePreserved2:o]; } + exception:^(ICEException* ex) { [cb exception:ex]; }]; + [cb check]; + } + + { + // + // Server only knows the intermediate type Preserved. The object will be sliced to + // Preserved for the 1.0 encoding; otherwise it should be returned intact. + // + TestSlicingObjectsClientPCDerived* pcd = [TestSlicingObjectsClientPCDerived pCDerived]; + pcd.pi = 3; + pcd.pbs = [NSArray arrayWithObjects:pcd, nil]; + + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + if([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]) + { + [test begin_exchangePBase:pcd + response:^(TestSlicingObjectsClientPBase* o) { [cb responsePreserved3:o]; } + exception:^(ICEException* ex) { [cb exception:ex]; }]; + } + else + { + [test begin_exchangePBase:pcd + response:^(TestSlicingObjectsClientPBase* o) { [cb responsePreserved4:o]; } + exception:^(ICEException* ex) { [cb exception:ex]; }]; + } + [cb check]; + } + + { + // + // Server only knows the intermediate type CompactPDerived. The object will be sliced to + // CompactPDerived for the 1.0 encoding; otherwise it should be returned intact. + // + TestSlicingObjectsClientCompactPCDerived* pcd = [TestSlicingObjectsClientCompactPCDerived compactPCDerived]; + pcd.pi = 3; + pcd.pbs = [NSArray arrayWithObjects:pcd, nil]; + + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + if([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]) + { + [test begin_exchangePBase:pcd + response:^(TestSlicingObjectsClientPBase* o) { [cb responseCompactPreserved1:o]; } + exception:^(ICEException* ex) { [cb exception:ex]; }]; + } + else + { + [test begin_exchangePBase:pcd + response:^(TestSlicingObjectsClientPBase* o) { [cb responseCompactPreserved2:o]; } + exception:^(ICEException* ex) { [cb exception:ex]; }]; + } + [cb check]; + } + + { + // + // Send an object that will have multiple preserved slices in the server. + // The object will be sliced to Preserved for the 1.0 encoding. + // + TestSlicingObjectsClientPCDerived3* pcd = [TestSlicingObjectsClientPCDerived3 pCDerived3]; + pcd.pi = 3; + + // + // Sending more than 254 objects exercises the encoding for object ids. + // + int i; + pcd.pbs = [NSArray array]; + for(i = 0; i < 300; ++i) + { + TestSlicingObjectsClientPCDerived2* p2 = [TestSlicingObjectsClientPCDerived2 pCDerived2]; + p2.pi = i; + p2.pbs = [NSArray arrayWithObjects:[NSNull null], nil]; // Nil reference. This slice should not have an indirection table. + p2.pcd2 = i; + pcd.pbs = [pcd.pbs arrayByAddingObject:p2]; + } + pcd.pcd2 = pcd.pi; + pcd.pcd3 = [pcd.pbs objectAtIndex:10]; + + TestSlicingObjectsClientCallback* cb = [TestSlicingObjectsClientCallback create]; + if([[test ice_getEncodingVersion] isEqual:ICEEncoding_1_0]) + { + [test begin_exchangePBase:pcd + response:^(TestSlicingObjectsClientPBase* o) { [cb responsePreserved3:o]; } + exception:^(ICEException* ex) { [cb exception:ex]; }]; + } + else + { + [test begin_exchangePBase:pcd + response:^(TestSlicingObjectsClientPBase* o) { [cb responsePreserved5:o]; } + exception:^(ICEException* ex) { [cb exception:ex]; }]; + } + [cb check]; + } + + tprintf("ok\n"); + + return test; +} diff --git a/objc/test/Ice/slicing/objects/Client.m b/objc/test/Ice/slicing/objects/Client.m new file mode 100644 index 00000000000..89fe3a4e165 --- /dev/null +++ b/objc/test/Ice/slicing/objects/Client.m @@ -0,0 +1,77 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <SlicingObjectsTestClient.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + id<TestSlicingObjectsClientTestIntfPrx> slicingObjectsAllTests(id<ICECommunicator>); + id<TestSlicingObjectsClientTestIntfPrx> TestSlicingObjectsClient = slicingObjectsAllTests(communicator); + [TestSlicingObjectsClient shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main slicingObjectsClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestSlicingObjectsClient", @"::Test", + @"TestSlicingObjectsShared", @"::TestShared", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/slicing/objects/Makefile b/objc/test/Ice/slicing/objects/Makefile new file mode 100644 index 00000000000..12373f955af --- /dev/null +++ b/objc/test/Ice/slicing/objects/Makefile @@ -0,0 +1,45 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = SlicingObjectsTestClient.o \ + SlicingObjectsForwardClient.o \ + SlicingObjectsTestServer.o \ + SlicingObjectsForwardServer.o + +COBJS = SlicingObjectsTestClient.o \ + SlicingObjectsForwardClient.o \ + Client.o \ + AllTests.o + +SOBJS = SlicingObjectsTestServer.o \ + SlicingObjectsForwardServer.o \ + TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I../.. -I../../../include $(CPPFLAGS) +SLICE2OBJCFLAGS := -I. $(SLICE2OBJCFLAGS) + +$(CLIENT): $(COBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/slicing/objects/Server.m b/objc/test/Ice/slicing/objects/Server.m new file mode 100644 index 00000000000..73d4eb89bf0 --- /dev/null +++ b/objc/test/Ice/slicing/objects/Server.m @@ -0,0 +1,85 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <slicing/objects/TestI.h> +#include <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + id<ICEProperties> properties = [communicator getProperties]; + [properties setProperty:@"Ice.Warn.Dispatch" value:@"0"]; + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; + ICEObject* object = [[TestSlicingObjectsServerI alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [object autorelease]; +#endif + [adapter add:object identity:[communicator stringToIdentity:@"Test"]]; + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main slicingObjectsServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestSlicingObjectsServer", @"::Test", + @"TestSlicingObjectsShared", @"::TestShared", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/slicing/objects/SlicingObjectsForwardClient.ice b/objc/test/Ice/slicing/objects/SlicingObjectsForwardClient.ice new file mode 100644 index 00000000000..f472b42ef9e --- /dev/null +++ b/objc/test/Ice/slicing/objects/SlicingObjectsForwardClient.ice @@ -0,0 +1,28 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestSlicingObjectsClient"] +module Test +{ + +class Forward; + +class Hidden +{ + Forward f; +}; + +class Forward +{ + Hidden h; +}; + +}; diff --git a/objc/test/Ice/slicing/objects/SlicingObjectsForwardServer.ice b/objc/test/Ice/slicing/objects/SlicingObjectsForwardServer.ice new file mode 100644 index 00000000000..ea21fd37f2d --- /dev/null +++ b/objc/test/Ice/slicing/objects/SlicingObjectsForwardServer.ice @@ -0,0 +1,28 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestSlicingObjectsServer"] +module Test +{ + +class Forward; + +class Hidden +{ + Forward f; +}; + +class Forward +{ + Hidden h; +}; + +}; diff --git a/objc/test/Ice/slicing/objects/SlicingObjectsTestClient.ice b/objc/test/Ice/slicing/objects/SlicingObjectsTestClient.ice new file mode 100644 index 00000000000..f8145e5566e --- /dev/null +++ b/objc/test/Ice/slicing/objects/SlicingObjectsTestClient.ice @@ -0,0 +1,196 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestSlicingObjectsClient"] +module Test +{ + +class SBase +{ + string sb; +}; + +class SBSKnownDerived extends SBase +{ + string sbskd; +}; + +class B +{ + string sb; + B pb; +}; + +class D1 extends B +{ + string sd1; + B pd1; +}; + +sequence<B> BSeq; + +class SS1 +{ + BSeq s; +}; + +class SS2 +{ + BSeq s; +}; + +struct SS +{ + SS1 c1; + SS2 c2; +}; + +dictionary<int, B> BDict; + +exception BaseException +{ + string sbe; + B pb; +}; + +exception DerivedException extends BaseException +{ + string sde; + D1 pd1; +}; + +class Forward; /* Forward-declared class defined in another compilation unit */ + +class PBase +{ + int pi; +}; + +sequence<PBase> PBaseSeq; + +["preserve-slice"] +class Preserved extends PBase +{ + string ps; +}; + +class PDerived extends Preserved +{ + PBase pb; +}; + +class CompactPDerived(56) extends Preserved +{ + PBase pb; +}; + +["preserve-slice"] +class PNode +{ + PNode next; +}; + +["preserve-slice"] +exception PreservedException +{ +}; + +["preserve-slice"] +class PCUnknown extends PBase +{ + string pu; +}; + +class PCDerived extends PDerived +{ + PBaseSeq pbs; +}; + +class PCDerived2 extends PCDerived +{ + int pcd2; +}; + +class PCDerived3 extends PCDerived2 +{ + Object pcd3; +}; + +class CompactPCDerived(57) extends CompactPDerived +{ + PBaseSeq pbs; +}; + +["format:sliced"] interface TestIntf +{ + Object SBaseAsObject(); + SBase SBaseAsSBase(); + SBase SBSKnownDerivedAsSBase(); + SBSKnownDerived SBSKnownDerivedAsSBSKnownDerived(); + + SBase SBSUnknownDerivedAsSBase(); + ["format:compact"] SBase SBSUnknownDerivedAsSBaseCompact(); + + Object SUnknownAsObject(); + void checkSUnknown(Object o); + + B oneElementCycle(); + B twoElementCycle(); + B D1AsB(); + D1 D1AsD1(); + B D2AsB(); + + void paramTest1(out B p1, out B p2); + void paramTest2(out B p2, out B p1); + B paramTest3(out B p1, out B p2); + B paramTest4(out B p); + + B returnTest1(out B p1, out B p2); + B returnTest2(out B p2, out B p1); + B returnTest3(B p1, B p2); + + SS sequenceTest(SS1 p1, SS2 p2); + + BDict dictionaryTest(BDict bin, out BDict bout); + + PBase exchangePBase(PBase pb); + + Preserved PBSUnknownAsPreserved(); + void checkPBSUnknown(Preserved p); + + Preserved PBSUnknownAsPreservedWithGraph(); + void checkPBSUnknownWithGraph(Preserved p); + + Preserved PBSUnknown2AsPreservedWithGraph(); + void checkPBSUnknown2WithGraph(Preserved p); + + PNode exchangePNode(PNode pn); + + void throwBaseAsBase() throws BaseException; + void throwDerivedAsBase() throws BaseException; + void throwDerivedAsDerived() throws DerivedException; + void throwUnknownDerivedAsBase() throws BaseException; + ["amd"] void throwPreservedException() throws PreservedException; + + void useForward(out Forward f); // Use of forward-declared class to verify that code is generated correctly. + + void shutdown(); +}; + +// Things private to the client. + +class D3 extends B +{ + string sd3; + B pd3; +}; + +}; diff --git a/objc/test/Ice/slicing/objects/SlicingObjectsTestServer.ice b/objc/test/Ice/slicing/objects/SlicingObjectsTestServer.ice new file mode 100644 index 00000000000..e3e09fa6781 --- /dev/null +++ b/objc/test/Ice/slicing/objects/SlicingObjectsTestServer.ice @@ -0,0 +1,215 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestSlicingObjectsServer"] +module Test +{ + +class SBase +{ + string sb; +}; + +class SBSKnownDerived extends SBase +{ + string sbskd; +}; + +class B +{ + string sb; + B pb; +}; + +class D1 extends B +{ + string sd1; + B pd1; +}; + +sequence<B> BSeq; + +class SS1 +{ + BSeq s; +}; + +class SS2 +{ + BSeq s; +}; + +struct SS +{ + SS1 c1; + SS2 c2; +}; + +dictionary<int, B> BDict; + +exception BaseException +{ + string sbe; + B pb; +}; + +exception DerivedException extends BaseException +{ + string sde; + D1 pd1; +}; + +class Forward; /* Forward-declared class defined in another compilation unit */ + +class PBase +{ + int pi; +}; + +sequence<PBase> PBaseSeq; + +["preserve-slice"] +class Preserved extends PBase +{ + string ps; +}; + +class PDerived extends Preserved +{ + PBase pb; +}; + +class CompactPDerived(56) extends Preserved +{ + PBase pb; +}; + +["preserve-slice"] +class PNode +{ + PNode next; +}; + +class MyClass +{ + int i; +}; + +class PSUnknown extends Preserved +{ + string psu; + PNode graph; + MyClass cl; +}; + +class PSUnknown2 extends Preserved +{ + PBase pb; +}; + +["preserve-slice"] +exception PreservedException +{ +}; + +exception PSUnknownException extends PreservedException +{ + PSUnknown2 p; +}; + +["format:sliced"] interface TestIntf +{ + Object SBaseAsObject(); + SBase SBaseAsSBase(); + SBase SBSKnownDerivedAsSBase(); + SBSKnownDerived SBSKnownDerivedAsSBSKnownDerived(); + + SBase SBSUnknownDerivedAsSBase(); + ["format:compact"] SBase SBSUnknownDerivedAsSBaseCompact(); + + Object SUnknownAsObject(); + void checkSUnknown(Object o); + + B oneElementCycle(); + B twoElementCycle(); + B D1AsB(); + D1 D1AsD1(); + B D2AsB(); + + void paramTest1(out B p1, out B p2); + void paramTest2(out B p2, out B p1); + B paramTest3(out B p1, out B p2); + B paramTest4(out B p); + + B returnTest1(out B p1, out B p2); + B returnTest2(out B p2, out B p1); + B returnTest3(B p1, B p2); + + SS sequenceTest(SS1 p1, SS2 p2); + + BDict dictionaryTest(BDict bin, out BDict bout); + + PBase exchangePBase(PBase pb); + + Preserved PBSUnknownAsPreserved(); + void checkPBSUnknown(Preserved p); + + Preserved PBSUnknownAsPreservedWithGraph(); + void checkPBSUnknownWithGraph(Preserved p); + + Preserved PBSUnknown2AsPreservedWithGraph(); + void checkPBSUnknown2WithGraph(Preserved p); + + PNode exchangePNode(PNode pn); + + void throwBaseAsBase() throws BaseException; + void throwDerivedAsBase() throws BaseException; + void throwDerivedAsDerived() throws DerivedException; + void throwUnknownDerivedAsBase() throws BaseException; + ["amd"] void throwPreservedException() throws PreservedException; + + void useForward(out Forward f); // Use of forward-declared class to verify that code is generated correctly. + + void shutdown(); +}; + + +// Things private to the server. + +class SBSUnknownDerived extends SBase +{ + string sbsud; +}; + +class SUnknown +{ + string su; +}; + +class D2 extends B +{ + string sd2; + B pd2; +}; + +class D4 extends B +{ + B p1; + B p2; +}; + +exception UnknownDerivedException extends BaseException +{ + string sude; + D2 pd2; +}; + +}; diff --git a/objc/test/Ice/slicing/objects/TestI.h b/objc/test/Ice/slicing/objects/TestI.h new file mode 100644 index 00000000000..208d8d02c6a --- /dev/null +++ b/objc/test/Ice/slicing/objects/TestI.h @@ -0,0 +1,18 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <SlicingObjectsTestServer.h> +#import <SlicingObjectsForwardServer.h> + +@interface TestSlicingObjectsServerI : TestSlicingObjectsServerTestIntf<TestSlicingObjectsServerTestIntf> +{ +@private + TestSlicingObjectsServerPSUnknownException* ex_; +} +@end diff --git a/objc/test/Ice/slicing/objects/TestI.m b/objc/test/Ice/slicing/objects/TestI.m new file mode 100644 index 00000000000..8e42d431a92 --- /dev/null +++ b/objc/test/Ice/slicing/objects/TestI.m @@ -0,0 +1,539 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <slicing/objects/TestI.h> +#import <TestCommon.h> + +@implementation TestSlicingObjectsServerI +-(ICEObject*) SBaseAsObject:(ICECurrent*)current +{ + return [TestSlicingObjectsServerSBase sBase:@"SBase.sb"]; +} + +-(TestSlicingObjectsServerSBase*) SBaseAsSBase:(ICECurrent*)current +{ + return [TestSlicingObjectsServerSBase sBase:@"SBase.sb"]; +} + +-(TestSlicingObjectsServerSBase*) SBSKnownDerivedAsSBase:(ICECurrent*)current +{ + return [TestSlicingObjectsServerSBSKnownDerived sBSKnownDerived:@"SBSKnownDerived.sb" + sbskd:@"SBSKnownDerived.sbskd"]; +} + +-(TestSlicingObjectsServerSBSKnownDerived*) SBSKnownDerivedAsSBSKnownDerived:(ICECurrent*)current +{ + return [TestSlicingObjectsServerSBSKnownDerived sBSKnownDerived:@"SBSKnownDerived.sb" + sbskd:@"SBSKnownDerived.sbskd"]; +} + +-(TestSlicingObjectsServerSBase*) SBSUnknownDerivedAsSBase:(ICECurrent*)current +{ + return [TestSlicingObjectsServerSBSUnknownDerived sBSUnknownDerived:@"SBSUnknownDerived.sb" + sbsud:@"SBSUnknownDerived.sbsud"]; +} + +-(TestSlicingObjectsServerSBase*) SBSUnknownDerivedAsSBaseCompact:(ICECurrent*)current +{ + return [TestSlicingObjectsServerSBSUnknownDerived sBSUnknownDerived:@"SBSUnknownDerived.sb" + sbsud:@"SBSUnknownDerived.sbsud"]; +} + +-(ICEObject*) SUnknownAsObject:(ICECurrent*)current +{ + return [TestSlicingObjectsServerSUnknown sUnknown:@"SUnknown.su"]; +} + +-(void) checkSUnknown:(ICEObject*) object current:(ICECurrent*)current +{ + if([current encoding] == ICEEncoding_1_0) + { + test(![object isKindOfClass:[TestSlicingObjectsServerSUnknown class]]); + } + else + { + test([object isKindOfClass:[TestSlicingObjectsServerSUnknown class]]); + TestSlicingObjectsServerSUnknown* su = (TestSlicingObjectsServerSUnknown*)object; + test([[su su] isEqual:@"SUnknown.su"]); + } +} + +-(TestSlicingObjectsServerB*) oneElementCycle:(ICECurrent*)current +{ + TestSlicingObjectsServerB* b1 = [[TestSlicingObjectsServerB alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [b1 autorelease]; +#endif + b1.sb = @"B1.sb"; + b1.pb = b1; + return b1; +} +-(TestSlicingObjectsServerB*) twoElementCycle:(ICECurrent*)current +{ + TestSlicingObjectsServerB* b1 = [[TestSlicingObjectsServerB alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [b1 autorelease]; +#endif + b1.sb = @"B1.sb"; + TestSlicingObjectsServerB* b2 = [[TestSlicingObjectsServerB alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [b2 autorelease]; +#endif + b2.sb = @"B2.sb"; + b2.pb = b1; + b1.pb = b2; + return b1; +} +-(TestSlicingObjectsServerB*) D1AsB:(ICECurrent*)current +{ + TestSlicingObjectsServerD1* d1 = [[TestSlicingObjectsServerD1 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d1 autorelease]; +#endif + d1.sb = @"D1.sb"; + d1.sd1 = @"D1.sd1"; + + TestSlicingObjectsServerD2* d2 = [[TestSlicingObjectsServerD2 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d2 autorelease]; +#endif + d2.pb = d1; + d2.sb = @"D2.sb"; + d2.sd2 = @"D2.sd2"; + d2.pd2 = d1; + d1.pb = d2; + d1.pd1 = d2; + return d1; +} +-(TestSlicingObjectsServerD1*) D1AsD1:(ICECurrent*)current +{ + TestSlicingObjectsServerD1* d1 = [[TestSlicingObjectsServerD1 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d1 autorelease]; +#endif + d1.sb = @"D1.sb"; + d1.sd1 = @"D1.sd1"; + TestSlicingObjectsServerD2* d2 = [[TestSlicingObjectsServerD2 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d2 autorelease]; +#endif + d2.pb = d1; + d2.sb = @"D2.sb"; + d2.sd2 = @"D2.sd2"; + d2.pd2 = d1; + d1.pb = d2; + d1.pd1 = d2; + return d1; +} +-(TestSlicingObjectsServerB*) D2AsB:(ICECurrent*)current +{ + TestSlicingObjectsServerD2* d2 = [[TestSlicingObjectsServerD2 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d2 autorelease]; +#endif + d2.sb = @"D2.sb"; + d2.sd2 = @"D2.sd2"; + TestSlicingObjectsServerD1* d1 = [[TestSlicingObjectsServerD1 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d1 autorelease]; +#endif + d1.pb = d2; + d1.sb = @"D1.sb"; + d1.sd1 = @"D1.sd1"; + d1.pd1 = d2; + d2.pb = d1; + d2.pd2 = d1; + return d2; +} +-(void) paramTest1:(TestSlicingObjectsServerB**)p1 p2:(TestSlicingObjectsServerB**)p2 current:(ICECurrent*)current +{ + TestSlicingObjectsServerD1* d1 = [[TestSlicingObjectsServerD1 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d1 autorelease]; +#endif + d1.sb = @"D1.sb"; + d1.sd1 = @"D1.sd1"; + TestSlicingObjectsServerD2* d2 = [[TestSlicingObjectsServerD2 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d2 autorelease]; +#endif + d2.pb = d1; + d2.sb = @"D2.sb"; + d2.sd2 = @"D2.sd2"; + d2.pd2 = d1; + d1.pb = d2; + d1.pd1 = d2; + *p1 = d1; + *p2 = d2; +} +-(void) paramTest2:(TestSlicingObjectsServerB**)p1 p1:(TestSlicingObjectsServerB**)p2 current:(ICECurrent*)current +{ + [self paramTest1:p2 p2:p1 current:current]; +} +-(TestSlicingObjectsServerB*) paramTest3:(TestSlicingObjectsServerB**)p1 p2:(TestSlicingObjectsServerB**)p2 current:(ICECurrent*)current +{ + TestSlicingObjectsServerD2* d2 = [[TestSlicingObjectsServerD2 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d2 autorelease]; +#endif + d2.sb = @"D2.sb (p1 1)"; + d2.pb = 0; + d2.sd2 = @"D2.sd2 (p1 1)"; + *p1 = d2; + + TestSlicingObjectsServerD1* d1 = [[TestSlicingObjectsServerD1 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d1 autorelease]; +#endif + d1.sb = @"D1.sb (p1 2)"; + d1.pb = 0; + d1.sd1 = @"D1.sd2 (p1 2)"; + d1.pd1 = 0; + d2.pd2 = d1; + + TestSlicingObjectsServerD2* d4 = [[TestSlicingObjectsServerD2 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d4 autorelease]; +#endif + d4.sb = @"D2.sb (p2 1)"; + d4.pb = 0; + d4.sd2 = @"D2.sd2 (p2 1)"; + *p2 = d4; + + TestSlicingObjectsServerD1* d3 = [[TestSlicingObjectsServerD1 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d3 autorelease]; +#endif + d3.sb = @"D1.sb (p2 2)"; + d3.pb = 0; + d3.sd1 = @"D1.sd2 (p2 2)"; + d3.pd1 = 0; + d4.pd2 = d3; + + return d3; +} +-(TestSlicingObjectsServerB*) paramTest4:(TestSlicingObjectsServerB**)p1 current:(ICECurrent*)current +{ + TestSlicingObjectsServerD4* d4 = [[TestSlicingObjectsServerD4 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d4 autorelease]; +#endif + d4.sb = @"D4.sb (1)"; + d4.pb = 0; + d4.p1 = [[TestSlicingObjectsServerB alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d4.p1 autorelease]; +#endif + d4.p1.sb = @"B.sb (1)"; + d4.p2 = [[TestSlicingObjectsServerB alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d4.p2 autorelease]; +#endif + d4.p2.sb = @"B.sb (2)"; + *p1 = d4; + return d4.p2; +} +-(TestSlicingObjectsServerB*) returnTest1:(TestSlicingObjectsServerB**)p1 p2:(TestSlicingObjectsServerB**)p2 current:(ICECurrent*)current +{ + [self paramTest1:p1 p2:p2 current:current]; + return *p1; +} +-(TestSlicingObjectsServerB*) returnTest2:(TestSlicingObjectsServerB**)p1 p1:(TestSlicingObjectsServerB**)p2 current:(ICECurrent*)current +{ + [self paramTest1:p2 p2:p1 current:current]; + return *p1; +} +-(TestSlicingObjectsServerB*) returnTest3:(TestSlicingObjectsServerB*)p1 p2:(TestSlicingObjectsServerB*)p2 current:(ICECurrent*)current +{ + return p1; +} +-(TestSlicingObjectsServerSS*) sequenceTest:(TestSlicingObjectsServerSS1*)p1 p2:(TestSlicingObjectsServerSS2*)p2 current:(ICECurrent*)current +{ + TestSlicingObjectsServerSS* ss = [TestSlicingObjectsServerSS sS]; + ss.c1 = p1; + ss.c2 = p2; + return ss; +} +-(TestSlicingObjectsServerBDict*) dictionaryTest:(TestSlicingObjectsServerMutableBDict*)bin + bout:(TestSlicingObjectsServerBDict**)bout current:(ICECurrent*)current +{ + int i; + *bout = [TestSlicingObjectsServerMutableBDict dictionary]; + for(i = 0; i < 10; ++i) + { + TestSlicingObjectsServerB* b = [bin objectForKey:[NSNumber numberWithInt:i]]; + TestSlicingObjectsServerD2* d2 = [[TestSlicingObjectsServerD2 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d2 autorelease]; +#endif + d2.sb = b.sb; + d2.pb = b.pb; + d2.sd2 = @"D2"; + d2.pd2 = d2; + [(NSMutableDictionary*)*bout setObject:d2 forKey:[NSNumber numberWithInt:(i * 10)]]; + } + TestSlicingObjectsServerMutableBDict* r = [TestSlicingObjectsServerMutableBDict dictionary]; + for(i = 0; i < 10; ++i) + { + TestSlicingObjectsServerD1* d1 = [[TestSlicingObjectsServerD1 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d1 autorelease]; +#endif + d1.sb = [NSString stringWithFormat:@"D1.%d",(i * 20)]; + d1.pb = (i == 0 ? nil : [r objectForKey:[NSNumber numberWithInt:((i - 1) * 20)]]); + d1.sd1 = d1.sb; + d1.pd1 = d1; + [r setObject:d1 forKey:[NSNumber numberWithInt:(i * 20)]]; + } + return r; +} + +-(TestSlicingObjectsServerPBase*) exchangePBase:(TestSlicingObjectsServerPBase*)pb + current:(ICECurrent*)current +{ + return pb; +} + +-(TestSlicingObjectsServerPreserved*) PBSUnknownAsPreserved:(ICECurrent*)current +{ + if([current.encoding isEqual:ICEEncoding_1_0]) + { + // + // 1.0 encoding doesn't support unmarshaling unknown classes even if referenced + // from unread slice. + // + return [[TestSlicingObjectsServerPSUnknown alloc] init:5 + ps:@"preserved" + psu:@"unknown" + graph:0 + cl:nil]; + } + else + { + return [[TestSlicingObjectsServerPSUnknown alloc] init:5 + ps:@"preserved" + psu:@"unknown" + graph:0 + cl:[[TestSlicingObjectsServerMyClass alloc] init:15]]; + } +} + +-(void) checkPBSUnknown:(TestSlicingObjectsServerPreserved*)p current:(ICECurrent*)current +{ + if([current.encoding isEqual:ICEEncoding_1_0]) + { + test(![p isKindOfClass:[TestSlicingObjectsServerPSUnknown class]]); + test(p.pi == 5); + test([p.ps isEqual:@"preserved"]); + } + else + { + test([p isKindOfClass:[TestSlicingObjectsServerPSUnknown class]]); + TestSlicingObjectsServerPSUnknown* pu = (TestSlicingObjectsServerPSUnknown*)p; + test(pu.pi == 5); + test([pu.ps isEqual:@"preserved"]); + test([pu.psu isEqual:@"unknown"]); + test(!pu.graph); + test(pu.cl && pu.cl.i == 15); + } +} + +-(TestSlicingObjectsServerPreserved*) PBSUnknownAsPreservedWithGraph:(ICECurrent*)current +{ + TestSlicingObjectsServerPSUnknown* r = [TestSlicingObjectsServerPSUnknown alloc]; + r.pi = 5; + r.ps = @"preserved"; + r.psu = @"unknown"; + r.graph = [TestSlicingObjectsServerPNode alloc]; + r.graph.next = [TestSlicingObjectsServerPNode alloc]; + r.graph.next.next = [TestSlicingObjectsServerPNode alloc]; + r.graph.next.next.next = r.graph; + return r; +} + +-(void) checkPBSUnknownWithGraph:(TestSlicingObjectsServerPreserved*) p current:(ICECurrent*)current +{ + if([current.encoding isEqual:ICEEncoding_1_0]) + { + test(![p isKindOfClass:[TestSlicingObjectsServerPSUnknown class]]); + test(p.pi == 5); + test([p.ps isEqual:@"preserved"]); + } + else + { + test([p isKindOfClass:[TestSlicingObjectsServerPSUnknown class]]); + TestSlicingObjectsServerPSUnknown* pu = (TestSlicingObjectsServerPSUnknown*)p; + test(pu.pi == 5); + test([pu.ps isEqual:@"preserved"]); + test([pu.psu isEqual:@"unknown"]); + test(pu.graph != pu.graph.next); + test(pu.graph.next != pu.graph.next.next); + test(pu.graph.next.next.next == pu.graph); + pu.graph.next.next.next = nil; // Break the cycle. + } +} + +-(TestSlicingObjectsServerPreserved*) PBSUnknown2AsPreservedWithGraph:(ICECurrent*)current +{ + TestSlicingObjectsServerPSUnknown2* r = [TestSlicingObjectsServerPSUnknown2 alloc]; + r.pi = 5; + r.ps = @"preserved"; + r.pb = r; + return r; +} + +-(void) checkPBSUnknown2WithGraph:(TestSlicingObjectsServerPreserved*) p current:(ICECurrent*)current +{ + if([current.encoding isEqual:ICEEncoding_1_0]) + { + test(![p isKindOfClass:[TestSlicingObjectsServerPSUnknown2 class]]); + test(p.pi == 5); + test([p.ps isEqual:@"preserved"]); + } + else + { + test([p isKindOfClass:[TestSlicingObjectsServerPSUnknown2 class]]); + TestSlicingObjectsServerPSUnknown2* pu = (TestSlicingObjectsServerPSUnknown2*)p; + test(pu.pi == 5); + test([pu.ps isEqual:@"preserved"]); + test(pu.pb == pu); + pu.pb = 0; // Break the cycle. + } +} + +-(TestSlicingObjectsServerPNode*) exchangePNode:(TestSlicingObjectsServerPNode*)pn current:(ICECurrent*)current +{ + return pn; +} + +-(void) throwBaseAsBase:(ICECurrent*)current +{ + TestSlicingObjectsServerBaseException* be = [[TestSlicingObjectsServerBaseException alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [be autorelease]; +#endif + be.sbe = @"sbe"; + be.pb = [[TestSlicingObjectsServerB alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [be.pb autorelease]; +#endif + be.pb.sb = @"sb"; + be.pb.pb = be.pb; + @throw be; +} +-(void) throwDerivedAsBase:(ICECurrent*)current +{ + TestSlicingObjectsServerDerivedException* de = [[TestSlicingObjectsServerDerivedException alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [de autorelease]; +#endif + de.sbe = @"sbe"; + de.pb = [[TestSlicingObjectsServerB alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [de.pb autorelease]; +#endif + de.pb.sb = @"sb1"; + de.pb.pb = de.pb; + de.sde = @"sde1"; + de.pd1 = [[TestSlicingObjectsServerD1 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [de.pd1 autorelease]; +#endif + de.pd1.sb = @"sb2"; + de.pd1.pb = de.pd1; + de.pd1.sd1 = @"sd2"; + de.pd1.pd1 = de.pd1; + @throw de; +} +-(void) throwDerivedAsDerived:(ICECurrent*)current +{ + TestSlicingObjectsServerDerivedException* de = [[TestSlicingObjectsServerDerivedException alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [de autorelease]; +#endif + de.sbe = @"sbe"; + de.pb = [[TestSlicingObjectsServerB alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [de.pb autorelease]; +#endif + de.pb.sb = @"sb1"; + de.pb.pb = de.pb; + de.sde = @"sde1"; + de.pd1 = [[TestSlicingObjectsServerD1 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [de.pd1 autorelease]; +#endif + de.pd1.sb = @"sb2"; + de.pd1.pb = de.pd1; + de.pd1.sd1 = @"sd2"; + de.pd1.pd1 = de.pd1; + @throw de; +} +-(void) throwUnknownDerivedAsBase:(ICECurrent*)current +{ + TestSlicingObjectsServerD2* d2 = [[TestSlicingObjectsServerD2 alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [d2 autorelease]; +#endif + d2.sb = @"sb d2"; + d2.pb = d2; + d2.sd2 = @"sd2 d2"; + d2.pd2 = d2; + + TestSlicingObjectsServerUnknownDerivedException* ude = [[TestSlicingObjectsServerUnknownDerivedException alloc] init]; +#if defined(__clang__) && !__has_feature(objc_arc) + [ude autorelease]; +#endif + ude.sbe = @"sbe"; + ude.pb = d2; + ude.sude = @"sude"; + ude.pd2 = d2; + @throw ude; +} +-(void) throwPreservedException:(ICECurrent*)current +{ + TestSlicingObjectsServerPSUnknownException* ue = [TestSlicingObjectsServerPSUnknownException pSUnknownException]; + ue.p = [TestSlicingObjectsServerPSUnknown2 pSUnknown2]; + ue.p.pi = 5; + ue.p.ps = @"preserved"; + ue.p.pb = ue.p; +#if defined(__clang__) && !__has_feature(objc_arc) + if(ex_ != nil) + { + ex_.p.pb = nil; + [ex_ release]; + } + ex_ = [ue retain]; +#else + if(ex_ != nil) + { + ex_.p.pb = nil; + } +#endif + @throw ue; +} +-(void) useForward:(TestSlicingObjectsServerForward**)f current:(ICECurrent*)current +{ + *f = [TestSlicingObjectsServerForward forward]; + (*f).h = [TestSlicingObjectsServerHidden hidden]; + (*f).h.f = *f; +} +-(void) shutdown:(ICECurrent*)current +{ + if(ex_ != nil) + { + ex_.p.pb = nil; +#if defined(__clang__) && !__has_feature(objc_arc) + [ex_ release]; +#endif + } + [[current.adapter getCommunicator] shutdown]; +} +@end diff --git a/objc/test/Ice/slicing/objects/run.py b/objc/test/Ice/slicing/objects/run.py new file mode 100755 index 00000000000..bfdb6603e5b --- /dev/null +++ b/objc/test/Ice/slicing/objects/run.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../..", "../../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +print("Running test with sliced format.") +TestUtil.clientServerTest() + +print("Running test with 1.0 encoding.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", + additionalServerOptions="--Ice.Default.EncodingVersion=1.0") diff --git a/objc/test/Ice/stream/.gitignore b/objc/test/Ice/stream/.gitignore new file mode 100644 index 00000000000..deeebc026e0 --- /dev/null +++ b/objc/test/Ice/stream/.gitignore @@ -0,0 +1,7 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +.depend +StreamTest.m +StreamTest.h diff --git a/objc/test/Ice/stream/Client.m b/objc/test/Ice/stream/Client.m new file mode 100644 index 00000000000..a189fc01e89 --- /dev/null +++ b/objc/test/Ice/stream/Client.m @@ -0,0 +1,979 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <StreamTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + id<ICEInputStream> in; + id<ICEOutputStream> out; + NSMutableData* data; + + // + // Test the stream api. + // + tprintf("testing primitive types... "); + + { + NSData* byte = [NSData data]; + in = [ICEUtil createInputStream:communicator data:byte]; + } + + { + out = [ICEUtil createOutputStream:communicator]; + [out startEncapsulation]; + [out writeBool:YES]; + [out endEncapsulation]; + data = [out finished]; + NSData* d = [out finishedNoCopy]; + test([d isEqual:data]); + out = nil; + + in = [ICEUtil createInputStream:communicator data:data]; + [in startEncapsulation]; + BOOL v; + v = [in readBool]; + test(v); + [in endEncapsulation]; + + in = [ICEUtil wrapInputStream:communicator data:data]; + [in startEncapsulation]; + v = [in readBool]; + test(v); + [in endEncapsulation]; + } + + { + NSData* byte = [NSData data]; + in = [ICEUtil createInputStream:communicator data:byte]; + @try + { + BOOL v; + v = [in readBool]; + test(NO); + } + @catch(ICEUnmarshalOutOfBoundsException* ex) + { + } + } + + { + out = [ICEUtil createOutputStream:communicator]; + [out writeBool:YES]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + BOOL v = [in readBool]; + test(v); + } + + { + out = [ICEUtil createOutputStream:communicator]; + [out writeByte:(ICEByte)1]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICEByte v = [in readByte]; + test(v == 1); + } + + { + out = [ICEUtil createOutputStream:communicator]; + [out writeShort:(ICEShort)2]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICEShort v = [in readShort]; + test(v == 2); + } + + { + out = [ICEUtil createOutputStream:communicator]; + [out writeInt:(ICEInt)3]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICEInt v; + v = [in readInt]; + test(v == 3); + } + + { + out = [ICEUtil createOutputStream:communicator]; + [out writeLong:(ICELong)4]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICELong v; + v = [in readLong]; + test(v == 4); + } + + { + out = [ICEUtil createOutputStream:communicator]; + [out writeFloat:(ICEFloat)5.0]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICEFloat v; + v = [in readFloat]; + test(v == 5.0); + } + + { + out = [ICEUtil createOutputStream:communicator]; + [out writeDouble:(ICEDouble)6.0]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICEDouble v; + v = [in readDouble]; + test(v == 6.0); + } + + { + out = [ICEUtil createOutputStream:communicator]; + [out writeString:@"hello world"]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + NSString* v; + v = [in readString]; + test([v isEqualToString:@"hello world"]); + } + + tprintf("ok\n"); + + tprintf("testing constructed types... "); + + { + out = [ICEUtil createOutputStream:communicator]; + [TestStreamMyEnumHelper write:@(TestStreamenum3) stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + id e = [TestStreamMyEnumHelper read:in]; + test([e isEqual:@(TestStreamenum3)]); + } + + { + out = [ICEUtil createOutputStream:communicator]; + TestStreamSmallStruct* s = [TestStreamSmallStruct smallStruct]; + s.bo = YES; + s.by = 1; + s.sh = 2; + s.i = 3; + s.l = 4; + s.f = 5.0; + s.d = 6.0; + s.str = @"7"; + s.e = TestStreamenum2; + s.p = [TestStreamMyClassPrx uncheckedCast:[communicator stringToProxy:@"test:default"]]; + [TestStreamSmallStructHelper write:s stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamSmallStruct* s2 = [TestStreamSmallStructHelper read:in]; + test([s2 isEqual:s]); + } + + { + out = [ICEUtil createOutputStream:communicator]; + TestStreamClassStruct* s = [TestStreamClassStruct classStruct]; + s.i = 10; + [TestStreamClassStructHelper write:s stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamClassStruct* s2 = [TestStreamClassStructHelper read:in]; + test(s2.i == s.i); + } + + { + out = [ICEUtil createOutputStream:communicator]; + TestStreamOptionalClass* o = [TestStreamOptionalClass optionalClass]; + o.bo = NO; + o.by = 5; + o.sh = 4; + o.i = 3; + [TestStreamOptionalClassHelper write:o stream:out]; + [out writePendingObjects]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamOptionalClass* ICE_AUTORELEASING_QUALIFIER o2; + [TestStreamOptionalClassHelper read:&o2 stream:in]; + [in readPendingObjects]; + test(o2.bo == o.bo); + test(o2.by == o.by); + if([in getEncoding] == ICEEncoding_1_0) + { + test(![o2 hasSh]); + test(![o2 hasI]); + } + else + { + test(o2.sh == o.sh); + test(o2.i == o.i); + } + } + + { + out = [ICEUtil createOutputStream:communicator encoding:ICEEncoding_1_0]; + TestStreamOptionalClass* o = [TestStreamOptionalClass optionalClass]; + o.bo = NO; + o.by = 5; + o.sh = 4; + o.i = 3; + [TestStreamOptionalClassHelper write:o stream:out]; + [out writePendingObjects]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data encoding:ICEEncoding_1_0]; + TestStreamOptionalClass* ICE_AUTORELEASING_QUALIFIER o2; + [TestStreamOptionalClassHelper read:&o2 stream:in]; + [in readPendingObjects]; + test(o2.bo == o.bo); + test(o2.by == o.by); + test(![o2 hasSh]); + test(![o2 hasI]); + } + + { + BOOL buf[] = { YES, YES, NO, YES }; + ICEBoolSeq* arr = [ICEBoolSeq dataWithBytes:buf length:sizeof(buf)]; + + out = [ICEUtil createOutputStream:communicator]; + [ICEBoolSeqHelper write:arr stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + ICEBoolSeq* arr2 = [ICEBoolSeqHelper read:in]; + test([arr2 isEqual:arr]); + + TestStreamMutableBoolSS* arrS = [TestStreamMutableBoolSS array]; + [arrS addObject:arr]; + [arrS addObject:[ICEBoolSeq data]]; + [arrS addObject:arr]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamBoolSSHelper write:arrS stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamBoolSS* arr2S = [TestStreamBoolSSHelper read:in]; + test([arr2S isEqual:arrS]); + } + + { + ICEByte buf[] = { 0x01, 0x11, 0x12, 0x22 }; + ICEByteSeq* arr = [ICEByteSeq dataWithBytes:buf length:sizeof(buf)]; + + out = [ICEUtil createOutputStream:communicator]; + [ICEByteSeqHelper write:arr stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICEByteSeq* arr2 = [ICEByteSeqHelper read:in]; + test([arr2 isEqual:arr]); + + TestStreamMutableByteSS* arrS = [TestStreamMutableByteSS array]; + [arrS addObject:arr]; + [arrS addObject:[ICEByteSeq data]]; + [arrS addObject:arr]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamByteSSHelper write:arrS stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamByteSS* arr2S = [TestStreamByteSSHelper read:in]; + test([arr2S isEqual:arrS]); + } + + { + ICEShort buf[] = { 1, 11, 12, 22 }; + ICEShortSeq* arr = [ICEShortSeq dataWithBytes:buf length:sizeof(buf)]; + + out = [ICEUtil createOutputStream:communicator]; + [ICEShortSeqHelper write:arr stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICEShortSeq* arr2 = [ICEShortSeqHelper read:in]; + test([arr2 isEqual:arr]); + + TestStreamMutableShortSS* arrS = [TestStreamMutableShortSS array]; + [arrS addObject:arr]; + [arrS addObject:[ICEShortSeq data]]; + [arrS addObject:arr]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamShortSSHelper write:arrS stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamShortSS* arr2S = [TestStreamShortSSHelper read:in]; + test([arr2S isEqual:arrS]); + } + + { + ICEInt buf[] = { 1, 11, 12, 22 }; + ICEIntSeq* arr = [ICEIntSeq dataWithBytes:buf length:sizeof(buf)]; + + out = [ICEUtil createOutputStream:communicator]; + [ICEIntSeqHelper write:arr stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICEIntSeq* arr2 = [ICEIntSeqHelper read:in]; + test([arr2 isEqual:arr]); + + TestStreamMutableIntSS* arrS = [TestStreamMutableIntSS array]; + [arrS addObject:arr]; + [arrS addObject:[ICEIntSeq data]]; + [arrS addObject:arr]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamIntSSHelper write:arrS stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamIntSS* arr2S = [TestStreamIntSSHelper read:in]; + test([arr2S isEqual:arrS]); + } + + { + ICELong buf[] = { 1, 11, 12, 22 }; + ICELongSeq* arr = [ICELongSeq dataWithBytes:buf length:sizeof(buf)]; + + out = [ICEUtil createOutputStream:communicator]; + [ICELongSeqHelper write:arr stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICELongSeq* arr2 = [ICELongSeqHelper read:in]; + test([arr2 isEqual:arr]); + + TestStreamMutableLongSS* arrS = [TestStreamMutableLongSS array]; + [arrS addObject:arr]; + [arrS addObject:[ICELongSeq data]]; + [arrS addObject:arr]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamLongSSHelper write:arrS stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamLongSS* arr2S = [TestStreamLongSSHelper read:in]; + test([arr2S isEqual:arrS]); + } + + { + ICEFloat buf[] = { 1, 2, 3, 4 }; + ICEFloatSeq* arr = [ICEFloatSeq dataWithBytes:buf length:sizeof(buf)]; + + out = [ICEUtil createOutputStream:communicator]; + [ICEFloatSeqHelper write:arr stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICEFloatSeq* arr2 = [ICEFloatSeqHelper read:in]; + test([arr2 isEqual:arr]); + + TestStreamMutableFloatSS* arrS = [TestStreamMutableFloatSS array]; + [arrS addObject:arr]; + [arrS addObject:[ICEFloatSeq data]]; + [arrS addObject:arr]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamFloatSSHelper write:arrS stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamFloatSS* arr2S = [TestStreamFloatSSHelper read:in]; + test([arr2S isEqual:arrS]); + } + + { + ICEDouble buf[] = { 1, 2, 3, 4 }; + ICEDoubleSeq* arr = [ICEDoubleSeq dataWithBytes:buf length:sizeof(buf)]; + + out = [ICEUtil createOutputStream:communicator]; + [ICEDoubleSeqHelper write:arr stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICEDoubleSeq* arr2 = [ICEDoubleSeqHelper read:in]; + test([arr2 isEqual:arr]); + + TestStreamMutableDoubleSS* arrS = [TestStreamMutableDoubleSS array]; + [arrS addObject:arr]; + [arrS addObject:[ICEDoubleSeq data]]; + [arrS addObject:arr]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamDoubleSSHelper write:arrS stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamDoubleSS* arr2S = [TestStreamDoubleSSHelper read:in]; + test([arr2S isEqual:arrS]); + } + + { + ICEMutableStringSeq* arr = [ICEMutableStringSeq array]; + [arr addObject:@"string1"]; + [arr addObject:@"string2"]; + [arr addObject:@"string3"]; + [arr addObject:@"string4"]; + out = [ICEUtil createOutputStream:communicator]; + [ICEStringSeqHelper write:arr stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + ICEStringSeq* arr2 = [ICEStringSeqHelper read:in]; + test([arr2 isEqual:arr]); + + TestStreamMutableStringSS* arrS = [TestStreamMutableStringSS array]; + [arrS addObject:arr]; + [arrS addObject:[ICEStringSeq array]]; + [arrS addObject:arr]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamStringSSHelper write:arrS stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamStringSS* arr2S = [TestStreamStringSSHelper read:in]; + test([arr2S isEqual:arrS]); + } + + { + TestStreamMyEnum buf[] = { TestStreamenum3, TestStreamenum2, TestStreamenum1, TestStreamenum2 }; + TestStreamMutableMyEnumS* arr = [TestStreamMutableMyEnumS dataWithBytes:buf length:sizeof(buf)]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamMyEnumSHelper write:arr stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamMyEnumS* arr2 = [TestStreamMyEnumSHelper read:in]; + test([arr2 isEqual:arr]); + + TestStreamMutableMyEnumSS* arrS = [TestStreamMutableMyEnumSS array]; + [arrS addObject:arr]; + [arrS addObject:[TestStreamMyEnumS data]]; + [arrS addObject:arr]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamMyEnumSSHelper write:arrS stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamMyEnumSS* arr2S = [TestStreamMyEnumSSHelper read:in]; + test([arr2S isEqual:arrS]); + } + + { + TestStreamMutableSmallStructS* arr = [TestStreamMutableSmallStructS array]; + for(int i = 0; i < 4; ++i) + { + TestStreamSmallStruct* s = [TestStreamSmallStruct smallStruct]; + s.bo = YES; + s.by = 1; + s.sh = 2; + s.i = 3; + s.l = 4; + s.f = 5.0; + s.d = 6.0; + s.str = @"7"; + s.e = TestStreamenum2; + s.p = [TestStreamMyClassPrx uncheckedCast:[communicator stringToProxy:@"test:default"]]; + [arr addObject:s]; + } + out = [ICEUtil createOutputStream:communicator]; + [TestStreamSmallStructSHelper write:arr stream:out]; + [out writePendingObjects]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamSmallStructS* arr2 = [TestStreamSmallStructSHelper read:in]; + [in readPendingObjects]; + test([arr2 count] == [arr count]); + for(int j = 0; j < [arr2 count]; ++j) + { + test([[arr objectAtIndex:j] isEqual:[arr2 objectAtIndex:j]]); + } + + TestStreamMutableSmallStructSS* arrS = [TestStreamMutableSmallStructSS array]; + [arrS addObject:arr]; + [arrS addObject:[TestStreamSmallStructS array]]; + [arrS addObject:arr]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamSmallStructSSHelper write:arrS stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamSmallStructSS* arr2S = [TestStreamSmallStructSSHelper read:in]; + test([arr2S isEqual:arrS]); + } + + { + TestStreamMutableMyClassS* arr = [TestStreamMutableMyClassS array]; + for(int i = 0; i < 4; ++i) + { + TestStreamMyClass* c = [TestStreamMyClass myClass]; + c.c = c; + c.o = c; + c.s = [TestStreamSmallStruct smallStruct]; + c.s.e = TestStreamenum2; + + BOOL boolS[] = { YES, NO, YES, NO }; + c.seq1 = [NSMutableData dataWithBytes:boolS length:sizeof(boolS)]; + + ICEByte byteS[] = { 1, 2, 3, 4 }; + c.seq2 = [NSMutableData dataWithBytes:byteS length:sizeof(byteS)]; + + ICEShort shortS[] = { 1, 2, 3, 4 }; + c.seq3 = [NSMutableData dataWithBytes:shortS length:sizeof(shortS)]; + + ICEInt intS[] = { 1, 2, 3, 4 }; + c.seq4 = [NSMutableData dataWithBytes:intS length:sizeof(intS)]; + + ICELong longS[] = { 1, 2, 3, 4 }; + c.seq5 = [NSMutableData dataWithBytes:longS length:sizeof(longS)]; + + ICEFloat floatS[] = { 1, 2, 3, 4 }; + c.seq6 = [NSMutableData dataWithBytes:floatS length:sizeof(floatS)]; + + ICEDouble doubleS[] = { 1, 2, 3, 4 }; + c.seq7 = [NSMutableData dataWithBytes:doubleS length:sizeof(doubleS)]; + + c.seq8 = [ICEMutableStringSeq array]; + [(ICEMutableStringSeq*)c.seq8 addObject:@"string1"]; + [(ICEMutableStringSeq*)c.seq8 addObject:@"string2"]; + [(ICEMutableStringSeq*)c.seq8 addObject:@"string3"]; + [(ICEMutableStringSeq*)c.seq8 addObject:@"string4"]; + + TestStreamMyEnum enumS[] = { TestStreamenum3, TestStreamenum2, TestStreamenum1 }; + c.seq9 = [NSMutableData dataWithBytes:enumS length:sizeof(enumS)]; + + c.d = [NSDictionary dictionaryWithObject:[TestStreamMyClass myClass] forKey:@"hi"]; + [arr addObject:c]; + } + out = [ICEUtil createOutputStream:communicator]; + [TestStreamMyClassSHelper write:arr stream:out]; + [out writePendingObjects]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamMyClassS* arr2 = [TestStreamMyClassSHelper read:in]; + [in readPendingObjects]; + test([arr2 count] > 0); + test([arr2 count] == [arr count]); + for(int j = 0; j < [arr2 count]; ++j) + { + TestStreamMyClass* e = [arr2 objectAtIndex:j]; + TestStreamMyClass* f = [arr objectAtIndex:j]; + test(e); + test(e.c == e); + test(e.o == e); + test(e.s.e == TestStreamenum2); + test([e.seq1 isEqual:f.seq1]); + test([e.seq2 isEqual:f.seq2]); + test([e.seq3 isEqual:f.seq3]); + test([e.seq4 isEqual:f.seq4]); + test([e.seq5 isEqual:f.seq5]); + test([e.seq6 isEqual:f.seq6]); + test([e.seq7 isEqual:f.seq7]); + test([e.seq8 isEqual:f.seq8]); + test([e.seq9 isEqual:f.seq9]); + test([e.d objectForKey:@"hi"] != nil); + + e.c = nil; + e.o = nil; + f.c = nil; + f.o = nil; + } + + TestStreamMutableMyClassSS* arrS = [TestStreamMutableMyClassSS array]; + [arrS addObject:arr]; + [arrS addObject:[TestStreamMyClassS array]]; + [arrS addObject:arr]; + + out = [ICEUtil createOutputStream:communicator]; + [TestStreamMyClassSSHelper write:arrS stream:out]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamMyClassSS* arr2S = [TestStreamMyClassSSHelper read:in]; + test([arr2S count] == [arrS count]); + } + + { + TestStreamMyInterface ICE_AUTORELEASING_QUALIFIER * i = [TestStreamMyInterface new]; + out = [ICEUtil createOutputStream:communicator]; + [TestStreamMyInterfaceHelper write:i stream:out]; + [out writePendingObjects]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + i = nil; + [TestStreamMyInterfaceHelper read:&i stream:in]; + [in readPendingObjects]; + test(i != nil); + } + + // + // ObjectWriter/ObjectReader not supported. + // + // { + // out = [ICEUtil createOutputStream:communicator]; + // TestStreamMyClass* obj = [TestStreamMyClass myClass]; + // obj.s.e = TestStreamenum2; + // TestObjectWriterPtr writer = new TestObjectWriter:obj]; + // [out writeObject:writer]; + // [out writePendingObjects]; + // data = [out finished]; + // test([writer called); + // } + + // { + // out = [ICEUtil createOutputStream:communicator]; + // TestStreamMyClassPtr obj = new TestStreamMyClass; + // obj->s.e = TestStreamenum2; + // TestObjectWriterPtr writer = new TestObjectWriter:obj]; + // [out writeObject:writer]; + // [out writePendingObjects]; + // data = [out finished]; + // test([writer called]); + // [factoryWrapper setFactory:new TestObjectFactory]; + // in = [ICEUtil createInputStream:communicator data:data]; + // TestReadObjectCallbackPtr cb = new TestReadObjectCallback; + // [in readObject:cb]; + // [in readPendingObjects]; + // test([cb obj]); + // TestObjectReaderPtr reader = TestObjectReaderPtr::dynamicCast(cb->obj); + // test(reader); + // test([reader called]); + // test([reader obj]); + // test([reader obj]->s.e == TestStreamenum2); + // [factoryWrapper setFactory:0]; + // } + + { + out = [ICEUtil createOutputStream:communicator]; + TestStreamMyException* ex = [TestStreamMyException myException]; + TestStreamMyClass* c = [TestStreamMyClass myClass]; + c.c = c; + c.o = c; + c.s = [TestStreamSmallStruct smallStruct]; + c.s.e = TestStreamenum2; + + BOOL boolS[] = { YES, NO, YES, NO }; + c.seq1 = [NSMutableData dataWithBytes:boolS length:sizeof(boolS)]; + + ICEByte byteS[] = { 1, 2, 3, 4 }; + c.seq2 = [NSMutableData dataWithBytes:byteS length:sizeof(byteS)]; + + ICEShort shortS[] = { 1, 2, 3, 4 }; + c.seq3 = [NSMutableData dataWithBytes:shortS length:sizeof(shortS)]; + + ICEInt intS[] = { 1, 2, 3, 4 }; + c.seq4 = [NSMutableData dataWithBytes:intS length:sizeof(intS)]; + + ICELong longS[] = { 1, 2, 3, 4 }; + c.seq5 = [NSMutableData dataWithBytes:longS length:sizeof(longS)]; + + ICEFloat floatS[] = { 1, 2, 3, 4 }; + c.seq6 = [NSMutableData dataWithBytes:floatS length:sizeof(floatS)]; + + ICEDouble doubleS[] = { 1, 2, 3, 4 }; + c.seq7 = [NSMutableData dataWithBytes:doubleS length:sizeof(doubleS)]; + + c.seq8 = [ICEMutableStringSeq array]; + [(ICEMutableStringSeq*)c.seq8 addObject:@"string1"]; + [(ICEMutableStringSeq*)c.seq8 addObject:@"string2"]; + [(ICEMutableStringSeq*)c.seq8 addObject:@"string3"]; + [(ICEMutableStringSeq*)c.seq8 addObject:@"string4"]; + + TestStreamMyEnum enumS[] = { TestStreamenum3, TestStreamenum2, TestStreamenum1 }; + c.seq9 = [NSMutableData dataWithBytes:enumS length:sizeof(enumS)]; + + c.d = [NSDictionary dictionaryWithObject:[TestStreamMyClass myClass] forKey:@"hi"]; + + ex.c = c; + + [out writeException:ex]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + @try + { + [in throwException]; + test(NO); + } + @catch(TestStreamMyException* ex1) + { + test(ex1.c); + test(ex1.c.c == ex1.c); + test(ex1.c.o == ex1.c); + test(ex1.c.s.e == TestStreamenum2); + test([ex1.c.seq1 isEqual:c.seq1]); + test([ex1.c.seq2 isEqual:c.seq2]); + test([ex1.c.seq3 isEqual:c.seq3]); + test([ex1.c.seq4 isEqual:c.seq4]); + test([ex1.c.seq5 isEqual:c.seq5]); + test([ex1.c.seq6 isEqual:c.seq6]); + test([ex1.c.seq7 isEqual:c.seq7]); + test([ex1.c.seq8 isEqual:c.seq8]); + test([ex1.c.seq9 isEqual:c.seq9]); + test([ex1.c.d objectForKey:@"hi"] != nil); + + ex1.c.c = nil; + ex1.c.o = nil; + c.c = nil; + c.o = nil; + } + } + + { + TestStreamMutableByteBoolD* dict = [TestStreamMutableByteBoolD dictionary]; + [dict setObject:@YES forKey:@(0x04)]; + [dict setObject:@NO forKey:@(0x01)]; + out = [ICEUtil createOutputStream:communicator]; + [TestStreamByteBoolDHelper write:dict stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamByteBoolD* dict2 = [TestStreamByteBoolDHelper read:in]; + test([dict2 isEqual:dict]); + } + + { + TestStreamMutableShortIntD* dict = [TestStreamMutableShortIntD dictionary]; + [dict setObject:@9 forKey:@1]; + [dict setObject:@8 forKey:@4]; + out = [ICEUtil createOutputStream:communicator]; + [TestStreamShortIntDHelper write:dict stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamShortIntD* dict2 = [TestStreamShortIntDHelper read:in]; + test([dict2 isEqual:dict]); + } + + { + TestStreamMutableLongFloatD* dict = [TestStreamMutableLongFloatD dictionary]; + [dict setObject:@0.51f forKey:@123809828]; + [dict setObject:@0.56f forKey:@123809829]; + out = [ICEUtil createOutputStream:communicator]; + [TestStreamLongFloatDHelper write:dict stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamLongFloatD* dict2 = [TestStreamLongFloatDHelper read:in]; + test([dict2 isEqual:dict]); + } + + { + TestStreamMutableStringStringD* dict = [TestStreamMutableStringStringD dictionary]; + [dict setObject:@"value1" forKey:@"key1"]; + [dict setObject:@"value2" forKey:@"key2"]; + out = [ICEUtil createOutputStream:communicator]; + [TestStreamStringStringDHelper write:dict stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamStringStringD* dict2 = [TestStreamStringStringDHelper read:in]; + test([dict2 isEqual:dict]); + } + + { + TestStreamMutableStringMyClassD* dict = [TestStreamMutableStringMyClassD dictionary]; + TestStreamMyClass* c = [TestStreamMyClass myClass]; + c.s = [TestStreamSmallStruct smallStruct]; + c.s.e = TestStreamenum2; + [dict setObject:c forKey:@"key1"]; + c = [TestStreamMyClass myClass]; + c.s = [TestStreamSmallStruct smallStruct]; + c.s.e = TestStreamenum3; + [dict setObject:c forKey:@"key2"]; + out = [ICEUtil createOutputStream:communicator]; + [TestStreamStringMyClassDHelper write:dict stream:out]; + [out writePendingObjects]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamStringMyClassD* dict2 = [TestStreamStringMyClassDHelper read:in]; + [in readPendingObjects]; + test([dict2 count] == [dict count]); + test([dict2 objectForKey:@"key1"] != nil && + ((TestStreamMyClass*)[dict2 objectForKey:@"key1"]).s.e == TestStreamenum2); + test([dict2 objectForKey:@"key2"] != nil && + ((TestStreamMyClass*)[dict2 objectForKey:@"key2"]).s.e == TestStreamenum3); + + } + + { + out = [ICEUtil createOutputStream:communicator]; + [TestStreamSubNestedEnumHelper write:@(TestStreamSubnestedEnum3) stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + id e = [TestStreamSubNestedEnumHelper read:in]; + test([e isEqual:@(TestStreamSubnestedEnum3)]); + } + + { + out = [ICEUtil createOutputStream:communicator]; + TestStreamSubNestedStruct* s = [TestStreamSubNestedStruct nestedStruct]; + s.bo = YES; + s.by = 1; + s.sh = 2; + s.i = 3; + s.l = 4; + s.f = 5.0; + s.d = 6.0; + s.str = @"7"; + s.e = TestStreamSubnestedEnum2; + [TestStreamSubNestedStructHelper write:s stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamSubNestedStruct* s2 = [TestStreamSubNestedStructHelper read:in]; + test([s2 isEqual:s]); + } + + { + out = [ICEUtil createOutputStream:communicator]; + TestStreamSubNestedClassStruct* s = [TestStreamSubNestedClassStruct nestedClassStruct]; + s.i = 10; + [TestStreamSubNestedClassStructHelper write:s stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStreamSubNestedClassStruct* s2 = [TestStreamSubNestedClassStructHelper read:in]; + test(s2.i == s.i); + } + + { + out = [ICEUtil createOutputStream:communicator]; + TestStreamSubNestedException* ex = [TestStreamSubNestedException nestedException]; + ex.str = @"str"; + + [out writeException:ex]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + @try + { + [in throwException]; + test(NO); + } + @catch(TestStreamSubNestedException* ex1) + { + test([ex1.str isEqualToString:ex.str]); + } + } + + { + out = [ICEUtil createOutputStream:communicator]; + [TestStream2Sub2NestedEnum2Helper write:@(TestStream2Sub2nestedEnum4) stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + id e = [TestStream2Sub2NestedEnum2Helper read:in]; + test([e isEqual:@(TestStream2Sub2nestedEnum4)]); + } + + { + out = [ICEUtil createOutputStream:communicator]; + TestStream2Sub2NestedStruct2* s = [TestStream2Sub2NestedStruct2 nestedStruct2]; + s.bo = YES; + s.by = 1; + s.sh = 2; + s.i = 3; + s.l = 4; + s.f = 5.0; + s.d = 6.0; + s.str = @"7"; + s.e = TestStream2Sub2nestedEnum5; + [TestStream2Sub2NestedStruct2Helper write:s stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStream2Sub2NestedStruct2* s2 = [TestStream2Sub2NestedStruct2Helper read:in]; + test([s2 isEqual:s]); + } + + { + out = [ICEUtil createOutputStream:communicator]; + TestStream2Sub2NestedClassStruct2* s = [TestStream2Sub2NestedClassStruct2 nestedClassStruct2]; + s.i = 10; + [TestStream2Sub2NestedClassStruct2Helper write:s stream:out]; + data = [out finished]; + in = [ICEUtil createInputStream:communicator data:data]; + TestStream2Sub2NestedClassStruct2* s2 = [TestStream2Sub2NestedClassStruct2Helper read:in]; + test(s2.i == s.i); + } + + { + out = [ICEUtil createOutputStream:communicator]; + TestStream2Sub2NestedException2* ex = [TestStream2Sub2NestedException2 nestedException2]; + ex.str = @"str"; + + [out writeException:ex]; + data = [out finished]; + + in = [ICEUtil createInputStream:communicator data:data]; + @try + { + [in throwException]; + test(NO); + } + @catch(TestStream2Sub2NestedException2* ex1) + { + test([ex1.str isEqualToString:ex.str]); + } + } + + tprintf("ok\n"); + return 0; +} + +#if TARGET_OS_IPHONE +# define main streamClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestStream", @"::Test", + @"TestStreamSub", @"::Test::Sub", + @"TestStream2", @"::Test2", + @"TestStream2Sub2", @"::Test2::Sub2", + nil]; +#endif + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/stream/Makefile b/objc/test/Ice/stream/Makefile new file mode 100644 index 00000000000..d3ddfa58783 --- /dev/null +++ b/objc/test/Ice/stream/Makefile @@ -0,0 +1,28 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client + +TARGETS = $(CLIENT) + +SLICE_OBJS = StreamTest.o + +COBJS = Client.o + +OBJS = $(COBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/stream/StreamTest.ice b/objc/test/Ice/stream/StreamTest.ice new file mode 100644 index 00000000000..02cf9905b50 --- /dev/null +++ b/objc/test/Ice/stream/StreamTest.ice @@ -0,0 +1,175 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +#pragma once + +#include <Ice/BuiltinSequences.ice> + +["objc:prefix:TestStream"] +module Test +{ + +enum MyEnum +{ + enum1, + enum2, + enum3 +}; + +class MyClass; + +["cpp:comparable"] struct SmallStruct +{ + bool bo; + byte by; + short sh; + int i; + long l; + float f; + double d; + string str; + MyEnum e; + MyClass* p; +}; + +["cpp:class"] struct ClassStruct +{ + int i; +}; + +class OptionalClass +{ + bool bo; + byte by; + optional(1) short sh; + optional(2) int i; +}; + +sequence<MyEnum> MyEnumS; +sequence<SmallStruct> SmallStructS; +sequence<MyClass> MyClassS; + +sequence<Ice::BoolSeq> BoolSS; +sequence<Ice::ByteSeq> ByteSS; +sequence<Ice::ShortSeq> ShortSS; +sequence<Ice::IntSeq> IntSS; +sequence<Ice::LongSeq> LongSS; +sequence<Ice::FloatSeq> FloatSS; +sequence<Ice::DoubleSeq> DoubleSS; +sequence<Ice::StringSeq> StringSS; +sequence<MyEnumS> MyEnumSS; +sequence<SmallStructS> SmallStructSS; +sequence<MyClassS> MyClassSS; + +dictionary<byte, bool> ByteBoolD; +dictionary<short, int> ShortIntD; +dictionary<long, float> LongFloatD; +dictionary<string, string> StringStringD; +dictionary<string, MyClass> StringMyClassD; + +class MyClass +{ + MyClass c; + Object o; + SmallStruct s; + Ice::BoolSeq seq1; + Ice::ByteSeq seq2; + Ice::ShortSeq seq3; + Ice::IntSeq seq4; + Ice::LongSeq seq5; + Ice::FloatSeq seq6; + Ice::DoubleSeq seq7; + Ice::StringSeq seq8; + MyEnumS seq9; + MyClassS seq10; + StringMyClassD d; +}; + +interface MyInterface +{ +}; + +exception MyException +{ + MyClass c; +}; + +["objc:prefix:TestStreamSub"] +module Sub +{ + enum NestedEnum + { + nestedEnum1, + nestedEnum2, + nestedEnum3 + }; + + ["cpp:comparable"] struct NestedStruct + { + bool bo; + byte by; + short sh; + int i; + long l; + float f; + double d; + string str; + NestedEnum e; + }; + + ["cpp:class"] struct NestedClassStruct + { + int i; + }; + + exception NestedException + { + string str; + }; +}; +}; + +["objc:prefix:TestStream2"] +module Test2 +{ +["objc:prefix:TestStream2Sub2"] +module Sub2 +{ + enum NestedEnum2 + { + nestedEnum4, + nestedEnum5, + nestedEnum6 + }; + + ["cpp:comparable"] struct NestedStruct2 + { + bool bo; + byte by; + short sh; + int i; + long l; + float f; + double d; + string str; + NestedEnum2 e; + }; + + ["cpp:class"] struct NestedClassStruct2 + { + int i; + }; + + exception NestedException2 + { + string str; + }; +}; +}; + diff --git a/objc/test/Ice/stream/run.py b/objc/test/Ice/stream/run.py new file mode 100755 index 00000000000..70e3812f00b --- /dev/null +++ b/objc/test/Ice/stream/run.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +client = os.path.join(os.getcwd(), "client") + +print("Running test with default encoding...") +TestUtil.simpleTest(client) + +print("Running test with 1.0 encoding...") +TestUtil.simpleTest(client, "--Ice.Default.EncodingVersion=1.0") diff --git a/objc/test/Ice/timeout/.gitignore b/objc/test/Ice/timeout/.gitignore new file mode 100644 index 00000000000..1c18b9822c2 --- /dev/null +++ b/objc/test/Ice/timeout/.gitignore @@ -0,0 +1,8 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +server +.depend +TimeoutTest.m +TimeoutTest.h diff --git a/objc/test/Ice/timeout/AllTests.m b/objc/test/Ice/timeout/AllTests.m new file mode 100644 index 00000000000..2dd9e755f78 --- /dev/null +++ b/objc/test/Ice/timeout/AllTests.m @@ -0,0 +1,277 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <TimeoutTest.h> + +#import <Foundation/Foundation.h> + +@interface TestTimeoutCallback : NSObject +{ + BOOL called; + NSCondition* cond; +} +-(void) check; +-(void) called; +@end + +@implementation TestTimeoutCallback +-(id) init +{ + self = [super init]; + if(!self) + { + return nil; + } + cond = [[NSCondition alloc] init]; + return self; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [cond release]; + [super dealloc]; +} +#endif + +-(void) check +{ + [cond lock]; + while(!called) + { + [cond wait]; + } + called = NO; + [cond unlock]; +} +-(void) called +{ + [cond lock]; + called = YES; + [cond signal]; + [cond unlock]; +} +-(void) sendDataResponse +{ + [self called]; +} +-(void) sendDataException:(ICEException*)ex +{ + test(NO); +} +-(void) sendDataExResponse +{ + test(NO); +} +-(void) sendDataExException:(ICEException*)ex +{ + test([ex isKindOfClass:[ICETimeoutException class]]); + [self called]; +} +-(void) sleepResponse +{ + [self called]; +} +-(void) sleepException:(ICEException*)ex +{ + test(NO); +} +-(void) sleepExResponse +{ + test(NO); +} +-(void) sleepExException:(ICEException*)ex +{ + test([ex isKindOfClass:[ICETimeoutException class]]); + [self called]; +} +@end + +id<TestTimeoutTimeoutPrx> +timeoutAllTests(id<ICECommunicator> communicator) +{ + NSString* sref = @"timeout:default -p 12010"; + id<ICEObjectPrx> obj = [communicator stringToProxy:sref]; + test(obj); + + id<TestTimeoutTimeoutPrx> timeout = [TestTimeoutTimeoutPrx checkedCast:obj]; + test(timeout); + + tprintf("testing connect timeout... "); + { + // + // Expect ConnectTimeoutException. + // + id<TestTimeoutTimeoutPrx> to = [TestTimeoutTimeoutPrx uncheckedCast:[obj ice_timeout:500]]; + [to holdAdapter:1000]; + [[to ice_getConnection] close:YES]; // Force a reconnect. + @try + { + [to op]; + test(NO); + } + @catch(ICEConnectTimeoutException*) + { + // Expected. + } + } + { + // + // Expect success. + // + [timeout op]; // Ensure adapter is active. + id<TestTimeoutTimeoutPrx> to = [TestTimeoutTimeoutPrx uncheckedCast:[obj ice_timeout:1000]]; + [to holdAdapter:500]; + [[to ice_getConnection] close:YES]; // Force a reconnect. + @try + { + [to op]; + } + @catch(ICEConnectTimeoutException*) + { + test(NO); + } + } + tprintf("ok\n"); + + // The sequence needs to be large enough to fill the write/recv buffers + TestTimeoutByteSeq* seq = [TestTimeoutMutableByteSeq dataWithLength:2000000]; + + tprintf("testing connection timeout... "); + { + // + // Expect TimeoutException. + // + id<TestTimeoutTimeoutPrx> to = [TestTimeoutTimeoutPrx uncheckedCast:[obj ice_timeout:100]]; + [to holdAdapter:500]; + @try + { + [to sendData:seq]; + test(NO); + } + @catch(ICETimeoutException*) + { + // Expected. + } + } + { + // + // Expect success. + // + [timeout op]; // Ensure adapter is active. + id<TestTimeoutTimeoutPrx> to = [TestTimeoutTimeoutPrx uncheckedCast:[obj ice_timeout:1000]]; + [to holdAdapter:500]; + @try + { + TestTimeoutByteSeq* seq = [TestTimeoutMutableByteSeq dataWithLength:1000000]; + [to sendData:seq]; + } + @catch(ICETimeoutException*) + { + test(NO); + } + } + tprintf("ok\n"); + + tprintf("testing timeout overrides... "); + { + // + // TestTimeout Ice.Override.Timeout. This property overrides all + // endpoint timeouts. + // + ICEInitializationData* initData = [ICEInitializationData initializationData]; + [initData setProperties:[[communicator getProperties] clone]]; + [[initData properties] setProperty:@"Ice.Override.Timeout" value:@"100"]; + id<ICECommunicator> comm = [ICEUtil createCommunicator:initData]; + id<TestTimeoutTimeoutPrx> to = [TestTimeoutTimeoutPrx checkedCast:[comm stringToProxy:sref]]; + [timeout holdAdapter:500]; + @try + { + [to sendData:seq]; + test(NO); + } + @catch(ICETimeoutException*) + { + // Expected. + } + // + // Calling ice_timeout() should have no effect. + // + [timeout op]; // Ensure adapter is active. + to = [TestTimeoutTimeoutPrx checkedCast:[to ice_timeout:1000]]; + [timeout holdAdapter:500]; + @try + { + [to sendData:seq]; + test(NO); + } + @catch(ICETimeoutException*) + { + // Expected. + } + [comm destroy]; + } + { + // + // TestTimeout Ice.Override.ConnectTimeout. + // + ICEInitializationData* initData = [ICEInitializationData initializationData]; + [initData setProperties:[[communicator getProperties] clone]]; + [[initData properties] setProperty:@"Ice.Override.ConnectTimeout" value:@"250"]; + id<ICECommunicator> comm = [ICEUtil createCommunicator:initData]; + [timeout holdAdapter:750]; + id<TestTimeoutTimeoutPrx> to = [TestTimeoutTimeoutPrx uncheckedCast:[comm stringToProxy:sref]]; + @try + { + [to op]; + test(NO); + } + @catch(ICEConnectTimeoutException*) + { + // Expected. + } + // + // Calling ice_timeout() should have no effect on the connect timeout. + // + [timeout op]; // Ensure adapter is active. + [timeout holdAdapter:750]; + to = [TestTimeoutTimeoutPrx uncheckedCast:[to ice_timeout:1000]]; + @try + { + [to op]; + test(NO); + } + @catch(ICEConnectTimeoutException*) + { + // Expected. + } + // + // Verify that timeout set via ice_timeout() is still used for requests. + // + [timeout op]; // Ensure adapter is active. + to = [TestTimeoutTimeoutPrx uncheckedCast:[to ice_timeout:100]]; + [to ice_getConnection]; // Establish connection + [timeout holdAdapter:750]; + @try + { + [to sendData:seq]; + test(NO); + } + @catch(ICETimeoutException*) + { + // Expected. + } + [comm destroy]; + } + tprintf("ok\n"); + + return timeout; +} diff --git a/objc/test/Ice/timeout/Client.m b/objc/test/Ice/timeout/Client.m new file mode 100644 index 00000000000..70cb973c338 --- /dev/null +++ b/objc/test/Ice/timeout/Client.m @@ -0,0 +1,93 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <TimeoutTest.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + id<TestTimeoutTimeoutPrx> timeoutAllTests(id<ICECommunicator>); + id<TestTimeoutTimeoutPrx> timeout = timeoutAllTests(communicator); + [timeout shutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main timeoutClient +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); + + // + // For this test, we want to disable retries. + // + [initData.properties setProperty:@"Ice.RetryIntervals" value:@"-1"]; + + // + // COMPILERFIX: Disable connect timeout introduced for + // workaround to iOS device hangs when using SSL + // + [initData.properties setProperty:@"Ice.Override.ConnectTimeout" value:@""]; + + // + // This test kills connections, so we don't want warnings. + // + [initData.properties setProperty:@"Ice.Warn.Connections" value:@"0"]; +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestTimeout", @"::Test", + nil]; +#endif + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/timeout/Makefile b/objc/test/Ice/timeout/Makefile new file mode 100644 index 00000000000..f669c19e612 --- /dev/null +++ b/objc/test/Ice/timeout/Makefile @@ -0,0 +1,37 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client +SERVER = server + +TARGETS = $(CLIENT) $(SERVER) + +SLICE_OBJS = TimeoutTest.o + +COBJS = Client.o \ + AllTests.o + +SOBJS = TestI.o \ + Server.o + +OBJS = $(COBJS) $(SOBJS) $(SLICE_OBJS) + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(COBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(COBJS) $(SLICE_OBJS) $(TEST_LIBS) + +$(SERVER): $(SOBJS) $(SLICE_OBJS) + rm -f $@ + $(CXX) $(LDFLAGS) $(LDEXEFLAGS) -o $@ $(SOBJS) $(SLICE_OBJS) $(TEST_LIBS) diff --git a/objc/test/Ice/timeout/Server.m b/objc/test/Ice/timeout/Server.m new file mode 100644 index 00000000000..48dcd2a311b --- /dev/null +++ b/objc/test/Ice/timeout/Server.m @@ -0,0 +1,94 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <timeout/TestI.h> +#import <TestCommon.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +static int +run(id<ICECommunicator> communicator) +{ + [[communicator getProperties] setProperty:@"TestAdapter.Endpoints" value:@"default -p 12010:udp"]; + id<ICEObjectAdapter> adapter = [communicator createObjectAdapter:@"TestAdapter"]; +#if defined(__clang__) && !__has_feature(objc_arc) + ICEObject* object = [[[TimeoutI alloc] init] autorelease]; +#else + ICEObject* object = [[TimeoutI alloc] init]; +#endif + [adapter add:object identity:[communicator stringToIdentity:@"timeout"]]; + [adapter activate]; + + serverReady(communicator); + + [communicator waitForShutdown]; + return EXIT_SUCCESS; +} + +#if TARGET_OS_IPHONE +# define main timeoutServer +#endif + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultServerProperties(&argc, argv); + + // + // COMPILERFIX: Disable connect timeout introduced for + // workaround to iOS device hangs when using SSL + // + [initData.properties setProperty:@"Ice.Override.ConnectTimeout" value:@""]; + + // + // This test kills connections, so we don't want warnings. + // + [initData.properties setProperty:@"Ice.Warn.Connections" value:@"0"]; +#if TARGET_OS_IPHONE + initData.prefixTable__ = [NSDictionary dictionaryWithObjectsAndKeys: + @"TestTimeout", @"::Test", + nil]; +#endif + + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} diff --git a/objc/test/Ice/timeout/TestI.h b/objc/test/Ice/timeout/TestI.h new file mode 100644 index 00000000000..c278f32870b --- /dev/null +++ b/objc/test/Ice/timeout/TestI.h @@ -0,0 +1,18 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <TimeoutTest.h> + +@interface TimeoutI : TestTimeoutTimeout<TestTimeoutTimeout> +-(void) op:(ICECurrent *)current; +-(void) sendData:(TestTimeoutMutableByteSeq *)seq current:(ICECurrent *)current; +-(void) sleep:(ICEInt)to current:(ICECurrent *)current; +-(void) holdAdapter:(ICEInt)to current:(ICECurrent *)current; +-(void) shutdown:(ICECurrent *)current; +@end diff --git a/objc/test/Ice/timeout/TestI.m b/objc/test/Ice/timeout/TestI.m new file mode 100644 index 00000000000..fff2c216a77 --- /dev/null +++ b/objc/test/Ice/timeout/TestI.m @@ -0,0 +1,94 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <timeout/TestI.h> +#import <objc/Ice.h> + +#import <Foundation/NSThread.h> + +@interface ActivateAdapterThread : NSThread +{ + id<ICEObjectAdapter> adapter_; + int timeout_; +} +-(id) init:(id<ICEObjectAdapter>)adapter timeout:(int)timeout; ++(id) activateAdapterThread:(id<ICEObjectAdapter>)adapter timeout:(int)timeout; +-(void) main; +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc; +#endif +@end + +@implementation ActivateAdapterThread +-(id) init:(id<ICEObjectAdapter>)adapter timeout:(int)timeout +{ + self = [super init]; + if(!self) + { + return nil; + } +#if defined(__clang__) && !__has_feature(objc_arc) + adapter_ = [adapter retain]; +#else + adapter_ = adapter; +#endif + timeout_ = timeout; + return self; +} + ++(id) activateAdapterThread:(id<ICEObjectAdapter>)adapter timeout:(int)timeout +{ +#if defined(__clang__) && !__has_feature(objc_arc) + return [[[self alloc] init:adapter timeout:timeout] autorelease]; +#else + return [[self alloc] init:adapter timeout:timeout]; +#endif +} +-(void) main +{ + [NSThread sleepForTimeInterval:timeout_ / 1000.0]; + [adapter_ activate]; +} + +#if defined(__clang__) && !__has_feature(objc_arc) +-(void) dealloc +{ + [adapter_ release]; + [super dealloc]; +} +#endif + +@end + +@implementation TimeoutI +-(void) op:(ICECurrent*)current +{ +} + +-(void) sendData:(TestTimeoutMutableByteSeq*)seq current:(ICECurrent*)current +{ +} + +-(void) sleep:(ICEInt)to current:(ICECurrent*)current +{ + [NSThread sleepForTimeInterval:to / 1000.0]; +} + +-(void) holdAdapter:(ICEInt)to current:(ICECurrent*)current +{ + [current.adapter hold]; + ActivateAdapterThread* thread = [ActivateAdapterThread activateAdapterThread:current.adapter timeout:to]; + [thread start]; +} + +-(void) shutdown:(ICECurrent*)current +{ + [[current.adapter getCommunicator] shutdown]; +} +@end diff --git a/objc/test/Ice/timeout/TimeoutTest.ice b/objc/test/Ice/timeout/TimeoutTest.ice new file mode 100644 index 00000000000..6544b216567 --- /dev/null +++ b/objc/test/Ice/timeout/TimeoutTest.ice @@ -0,0 +1,29 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +["objc:prefix:TestTimeout"] +module Test +{ + +sequence<byte> ByteSeq; + +interface Timeout +{ + void op(); + void sendData(ByteSeq seq); + void sleep(int to); + + void holdAdapter(int to); + + void shutdown(); +}; + +}; diff --git a/objc/test/Ice/timeout/run.py b/objc/test/Ice/timeout/run.py new file mode 100755 index 00000000000..33fc2e8f3ac --- /dev/null +++ b/objc/test/Ice/timeout/run.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +TestUtil.clientServerTest() diff --git a/objc/test/Makefile b/objc/test/Makefile new file mode 100644 index 00000000000..02aabe19256 --- /dev/null +++ b/objc/test/Makefile @@ -0,0 +1,21 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = .. + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = Common Slice Ice + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done diff --git a/objc/test/Slice/Makefile b/objc/test/Slice/Makefile new file mode 100644 index 00000000000..f34d7c628bd --- /dev/null +++ b/objc/test/Slice/Makefile @@ -0,0 +1,21 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../.. + +include $(top_srcdir)/config/Make.rules + +SUBDIRS = keyword + +$(EVERYTHING):: + @for subdir in $(SUBDIRS); \ + do \ + echo "making $@ in $$subdir"; \ + ( cd $$subdir && $(MAKE) $@ ) || exit 1; \ + done diff --git a/objc/test/Slice/keyword/.gitignore b/objc/test/Slice/keyword/.gitignore new file mode 100644 index 00000000000..f5c78eb09c4 --- /dev/null +++ b/objc/test/Slice/keyword/.gitignore @@ -0,0 +1,9 @@ +// Generated by makegitignore.py + +// IMPORTANT: Do not edit this file -- any edits made here will be lost! +client +.depend +Key.m +Inherit.m +Key.h +Inherit.h diff --git a/objc/test/Slice/keyword/Client.m b/objc/test/Slice/keyword/Client.m new file mode 100644 index 00000000000..dbabff1fd55 --- /dev/null +++ b/objc/test/Slice/keyword/Client.m @@ -0,0 +1,223 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <objc/Ice.h> +#import <TestCommon.h> +#import <Key.h> +#import <Inherit.h> +#ifdef ICE_OBJC_GC +# import <Foundation/NSGarbageCollector.h> +#endif + +// Verify that the expected symbols are present +@interface andbreakI : andbreak<andbreak> +@end + +@interface andcharI : andchar<andchar> +@end + +@interface andswitchI : andswitch<andswitch> +@end + +@interface anddoI : anddo<anddo> +@end + +@interface andfriendI : andfriend<andfriend> +@end + +// +// This section of the test is present to ensure that the C++ types +// are named correctly. It is not expected to run. +// +static void +testSymbols() +{ + andbreakPrx* prx1 = 0; + [prx1 case_:0 try:0]; + test(prx1 == 0); + + andcharPrx* prx2 = 0; + [prx2 explicit]; + test(prx2 == 0); + + andswitchPrx* prx3 = 0; + [prx3 foo:0 volatile_:0]; + test(prx3 == 0); + + anddoPrx* prx4 = 0; + test(prx4 == 0); + + anddoPrx* prx5 = 0; + test(prx5 == 0); + + andfriendPrx* prx6 = 0; + test(prx6 == 0); + + andcontinue c1 = andasm; + test(c1 == andasm); + + andauto* cl1 = 0; + test(cl1 == 0); + + anddelete* cl2 = 0; + test(cl2 == 0); + + andswitch* cl3 = 0; + test(cl3.if_ == 0); + test(cl3 == 0); + + anddo* cl4 = 0; + test(cl4 == 0); + + andreturn* ex1 = 0; + test(ex1.signed_ == 0); + test(ex1 == 0); + + andsizeof* ex2 = 0; + test(ex2.signed_ == 0); + test(ex2.static_ == 0); + test(ex2 == 0); + + test(andtemplate == 0); + test(andthis == 0); + test(andthrow == 0); + test(andtypedef == 0); + test(andtypeid == 0); + test(andtypename == 0); + test(andunion == 0); + test(andunsigned == 0); + test(andusing == 0); + test(andvirtual == 0); + test(andwhile == 0); + test(andxor == 0); + + TestStruct1* ds1 = 0; + test(ds1.retainCount_ == 0); + + TestException1 *dex1 = 0; + test(dex1.isa_ == 0); + test(dex1.reason_ == 0); + test(dex1.raise_ == 0); + test(dex1.name_ == 0); + test(dex1.callStackReturnAddresses_ == 0); + test(dex1.userInfo_ == 0); + test(dex1.reserved_ == 0); + + TestClass1* dcl1 = 0; + test(dcl1.reason == 0); + test(dcl1.autorelease_ == 0); + test(dcl1.isa_ == 0); + test(dcl1.classForCoder_ == 0); + test(dcl1.copy_ == 0); + test(dcl1.dealloc_ == 0); + test(dcl1.description_ == 0); + test(dcl1.hash_ == 0); + test(dcl1.init_ == 0); + test(dcl1.isProxy_ == 0); + test(dcl1.mutableCopy_ == 0); + test(dcl1.release_ == 0); + test(dcl1.retain_ == 0); + test(dcl1.retainCount_ == 0); + test(dcl1.self_ == 0); + test(dcl1.superclass_ == 0); + test(dcl1.zone_ == 0); + + TestIntf1Prx* dif1 = 0; + [dif1 reason]; + [dif1 isa_]; + [dif1 autorelease_]; + [dif1 classForCoder_]; + [dif1 copy_]; + [dif1 dealloc_]; + [dif1 description_]; + [dif1 hash_]; + [dif1 init_]; + [dif1 isProxy_]; + [dif1 mutableCopy_]; + [dif1 release_]; + [dif1 retain_]; + [dif1 retainCount_]; + [dif1 self_]; + [dif1 superclass_]; + [dif1 zone_]; + + TestIntf2Prx* dif2 = 0; + [dif2 reason:0]; + [dif2 isa:0]; + [dif2 autorelease:0]; + [dif2 classForCoder:0]; + [dif2 copy:0]; + [dif2 dealloc:0]; + [dif2 description:0]; + [dif2 hash:0]; + [dif2 init:0]; + [dif2 isProxy:0]; + [dif2 mutableCopy:0]; + [dif2 release:0]; + [dif2 retain:0]; + [dif2 retainCount:0]; + [dif2 self_:0]; + [dif2 superclass:0]; + [dif2 zone:0]; +} + +static int +run(id<ICECommunicator> communicator) +{ + if(0) + { + testSymbols(); + } + return 0; +} + +int +main(int argc, char* argv[]) +{ + int status; + @autoreleasepool + { + id<ICECommunicator> communicator = nil; + + @try + { + ICEInitializationData* initData = [ICEInitializationData initializationData]; + initData.properties = defaultClientProperties(&argc, argv); + communicator = [ICEUtil createCommunicator:&argc argv:argv initData:initData]; + status = run(communicator); + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + @catch(TestFailedException* ex) + { + status = EXIT_FAILURE; + } + + if(communicator) + { + @try + { + [communicator destroy]; + } + @catch(ICEException* ex) + { + tprintf("%@\n", ex); + status = EXIT_FAILURE; + } + } + } +#ifdef ICE_OBJC_GC + [[NSGarbageCollector defaultCollector] collectExhaustively]; +#endif + return status; +} + diff --git a/objc/test/Slice/keyword/Inherit.ice b/objc/test/Slice/keyword/Inherit.ice new file mode 100644 index 00000000000..3cd8392db10 --- /dev/null +++ b/objc/test/Slice/keyword/Inherit.ice @@ -0,0 +1,95 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +// Test overridding interherited names +module Test +{ + +struct Struct1 +{ + int isa; + int retainCount; +}; + +exception Exception1 +{ + int isa; + int reason; + int raise; + int name; + int callStackReturnAddresses; + int userInfo; + int reserved; +}; + +class Class1 +{ + int reason; + + int isa; + int autorelease; + int classForCoder; + int copy; + int dealloc; + int description; + int hash; + int init; + int isProxy; + int mutableCopy; + int release; + int retain; + int retainCount; + int self; + int superclass; + int zone; +}; + +interface Intf1 +{ + void isa(); + void reason(); + void autorelease(); + void classForCoder(); + void copy(); + void dealloc(); + void description(); + void hash(); + void init(); + void isProxy(); + void mutableCopy(); + void release(); + void retain(); + void retainCount(); + void self(); + void superclass(); + void zone(); +}; + +interface Intf2 +{ + void isa(int a); + void reason(int a); + void autorelease(int a); + void classForCoder(int a); + void copy(int a); + void dealloc(int a); + void description(int a); + void hash(int a); + void init(int a); + void isProxy(int a); + void mutableCopy(int a); + void release(int a); + void retain(int a); + void retainCount(int a); + void self(int a); + void superclass(int a); + void zone(int a); +}; + +}; diff --git a/objc/test/Slice/keyword/Key.ice b/objc/test/Slice/keyword/Key.ice new file mode 100644 index 00000000000..a45df9f0fa8 --- /dev/null +++ b/objc/test/Slice/keyword/Key.ice @@ -0,0 +1,86 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 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. +// +// ********************************************************************** + +module and +{ + +enum continue +{ + asm +}; + +struct auto +{ + int default; +}; + +["cpp:class"] struct delete +{ + string else; +}; + +interface break +{ + void case(int catch, out int try); +}; + +interface char +{ + void explicit(); +}; + +class switch +{ + int if; + void foo(char* export, out int volatile); +}; + +class do extends switch implements char, break +{ +}; + +sequence<auto> extern; + +dictionary<string,auto> for; + +exception return +{ + int signed; +}; + +exception sizeof extends return +{ + int static; + int switch; +}; + +local interface friend +{ + auto goto(continue if, auto d, delete inline, switch private, do mutable, break* namespace, + char* new, switch* not, do* operator, int or, int protected, int public, int register) + throws return, sizeof; + + void objc(int bycopy, int byref, int id, int IMP, int in, int inout, int nil, int NO, int oneway, + int SEL, int super, int YES); +}; + +const int template = 0; +const int this = 0; +const int throw = 0; +const int typedef = 0; +const int typeid = 0; +const int typename = 0; +const int union = 0; +const int unsigned = 0; +const int using = 0; +const int virtual = 0; +const int while = 0; +const int xor = 0; + +}; diff --git a/objc/test/Slice/keyword/Makefile b/objc/test/Slice/keyword/Makefile new file mode 100644 index 00000000000..78ee12943e1 --- /dev/null +++ b/objc/test/Slice/keyword/Makefile @@ -0,0 +1,29 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +# +# This copy of Ice Touch is licensed to you under the terms described in the +# ICE_TOUCH_LICENSE file included in this distribution. +# +# ********************************************************************** + +top_srcdir = ../../.. + +CLIENT = client + +TARGETS = $(CLIENT) + +SLICE_OBJS = Key.o Inherit.o + +OBJS = Key.o \ + Inherit.o \ + Client.o + +include $(top_srcdir)/config/Make.rules + +CPPFLAGS := -I. -I.. -I../../include $(CPPFLAGS) + +$(CLIENT): $(OBJS) + rm -f $@ + $(CC) $(LDFLAGS) $(LDEXEFLAGS) $(STATICLIBSTDFLAG) -o $@ $(OBJS) $(TEST_LIBS) + diff --git a/objc/test/Slice/keyword/run.py b/objc/test/Slice/keyword/run.py new file mode 100755 index 00000000000..eed9bface4f --- /dev/null +++ b/objc/test/Slice/keyword/run.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2014 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. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +client = os.path.join(os.getcwd(), "client") + +TestUtil.simpleTest(client) diff --git a/objc/test/include/TestCommon.h b/objc/test/include/TestCommon.h new file mode 100644 index 00000000000..eeced47cc3d --- /dev/null +++ b/objc/test/include/TestCommon.h @@ -0,0 +1,35 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved. +// +// This copy of Ice Touch is licensed to you under the terms described in the +// ICE_TOUCH_LICENSE file included in this distribution. +// +// ********************************************************************** + +#import <Foundation/NSObject.h> +#import <Foundation/NSException.h> + +@interface TestFailedException : NSException +@end + +#if TARGET_OS_IPHONE +void TestCommonInit(id, SEL); +void TestCommonTestInit(id, SEL, BOOL, BOOL, BOOL); +#endif + +@protocol ICECommunicator; +@protocol ICEProperties; + +id<ICEProperties> defaultServerProperties(); +id<ICEProperties> defaultClientProperties(); + +void serverReady(id<ICECommunicator>); + +void serverStop(); + +void tprintf(const char* fmt, ...); + +void testFailed(const char*, const char*, unsigned int); + +#define test(ex) ((ex) ? ((void)0) : testFailed(#ex, __FILE__, __LINE__)) diff --git a/py/config/Make.rules b/py/config/Make.rules index 5315160acf9..b142a7ddc48 100644 --- a/py/config/Make.rules +++ b/py/config/Make.rules @@ -11,7 +11,6 @@ # Select an installation base directory. The directory will be created # if it does not exist. # - prefix ?= /opt/Ice-$(VERSION) # diff --git a/scripts/TestUtil.py b/scripts/TestUtil.py index 677f3860ed0..39098029a9b 100755 --- a/scripts/TestUtil.py +++ b/scripts/TestUtil.py @@ -492,8 +492,8 @@ def run(tests, root = False): filters.append((testFilter, False)) elif o == "--cross": global cross - if a not in ["cpp", "cs", "java", "js", "py", "rb" ]: - print("cross must be one of cpp, cs, java, js, py or rb") + if a not in ["cpp", "cs", "java", "js", "py", "rb", "objc" ]: + print("cross must be one of cpp, cs, java, js, py, rb or objc") sys.exit(1) cross.append(a) elif o == "--all" : @@ -872,7 +872,7 @@ def getDefaultMapping(): here = os.getcwd().split(os.sep) here.reverse() for i in range(0, len(here)): - if here[i] in ["cpp", "cs", "java", "js", "php", "py", "rb", "cppe", "javae", "tmp"]: + if here[i] in ["cpp", "cs", "java", "js", "php", "py", "rb", "objc", "cppe", "javae", "tmp"]: return here[i] raise RuntimeError("cannot determine mapping") @@ -1137,7 +1137,7 @@ def directoryToPackage(): def getDefaultServerFile(): lang = getDefaultMapping() - if lang in ["js", "rb", "php", "cpp", "cs", "cppe"]: + if lang in ["js", "rb", "php", "cpp", "cs", "objc", "cppe"]: return "server" if lang == "py": return "Server.py" @@ -1155,7 +1155,7 @@ def getDefaultClientFile(lang = None): return "Client.rb" if lang == "php": return "Client.php" - if lang in ["cpp", "cs", "cppe"]: + if lang in ["cpp", "cs", "objc", "cppe"]: return "client" if lang == "py": return "Client.py" @@ -1807,7 +1807,7 @@ def getTestEnv(lang, testdir): # if isWin32(): addLdPath(getCppLibDir(lang), env) - elif lang in ["py", "rb", "php", "js"]: + elif lang in ["py", "rb", "php", "js", "objc"]: addLdPath(getCppLibDir(lang), env) if lang == "javae": @@ -1976,8 +1976,8 @@ def processCmdLine(): elif o == "--cross": global cross cross.append(a) - if not a in ["cpp", "cs", "java", "js", "py", "rb" ]: - print("cross must be one of cpp, cs, java, js, py or rb") + if not a in ["cpp", "cs", "java", "js", "py", "rb", "objc" ]: + print("cross must be one of cpp, cs, java, js, py, rb or objc") sys.exit(1) if getTestName() not in crossTests: print("*** This test does not support cross language testing") diff --git a/slice/Freeze/BackgroundSaveEvictor.ice b/slice/Freeze/BackgroundSaveEvictor.ice index 31789f613ce..350aeac636e 100644 --- a/slice/Freeze/BackgroundSaveEvictor.ice +++ b/slice/Freeze/BackgroundSaveEvictor.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Freeze/Evictor.ice> diff --git a/slice/Freeze/CatalogData.ice b/slice/Freeze/CatalogData.ice index cbc5eff6885..2495c22459f 100644 --- a/slice/Freeze/CatalogData.ice +++ b/slice/Freeze/CatalogData.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] module Freeze { diff --git a/slice/Freeze/Connection.ice b/slice/Freeze/Connection.ice index 33112b1e075..23522d67ced 100644 --- a/slice/Freeze/Connection.ice +++ b/slice/Freeze/Connection.ice @@ -13,7 +13,7 @@ #include <Ice/Version.ice> #include <Ice/CommunicatorF.ice> -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] module Freeze { diff --git a/slice/Freeze/ConnectionF.ice b/slice/Freeze/ConnectionF.ice index d45546e9467..fc4bf6d3fdb 100644 --- a/slice/Freeze/ConnectionF.ice +++ b/slice/Freeze/ConnectionF.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] module Freeze { diff --git a/slice/Freeze/DB.ice b/slice/Freeze/DB.ice index a3163713cee..383917beaba 100644 --- a/slice/Freeze/DB.ice +++ b/slice/Freeze/DB.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] /** * diff --git a/slice/Freeze/Evictor.ice b/slice/Freeze/Evictor.ice index 99ae80305c9..922ce686af3 100644 --- a/slice/Freeze/Evictor.ice +++ b/slice/Freeze/Evictor.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/ObjectAdapterF.ice> #include <Ice/ServantLocator.ice> diff --git a/slice/Freeze/EvictorF.ice b/slice/Freeze/EvictorF.ice index 8a6b3094e57..fc6b99d8bce 100644 --- a/slice/Freeze/EvictorF.ice +++ b/slice/Freeze/EvictorF.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] module Freeze { diff --git a/slice/Freeze/EvictorStorage.ice b/slice/Freeze/EvictorStorage.ice index eadaf120c4d..0458a56f0e7 100644 --- a/slice/Freeze/EvictorStorage.ice +++ b/slice/Freeze/EvictorStorage.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/Identity.ice> diff --git a/slice/Freeze/Exception.ice b/slice/Freeze/Exception.ice index 7fa56ebe9bd..09297cf70e4 100644 --- a/slice/Freeze/Exception.ice +++ b/slice/Freeze/Exception.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] module Freeze { diff --git a/slice/Freeze/Transaction.ice b/slice/Freeze/Transaction.ice index 58cf6a9170e..37f315068cb 100644 --- a/slice/Freeze/Transaction.ice +++ b/slice/Freeze/Transaction.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] module Freeze { diff --git a/slice/Freeze/TransactionalEvictor.ice b/slice/Freeze/TransactionalEvictor.ice index f71488660fb..3bd9b5b3933 100644 --- a/slice/Freeze/TransactionalEvictor.ice +++ b/slice/Freeze/TransactionalEvictor.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Freeze/Evictor.ice> diff --git a/slice/Glacier2/Metrics.ice b/slice/Glacier2/Metrics.ice index 9e1d7cefc3f..5554d660a8f 100644 --- a/slice/Glacier2/Metrics.ice +++ b/slice/Glacier2/Metrics.ice @@ -9,11 +9,12 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:Glacier2/Config.h"]] #include <Ice/Metrics.ice> +["objc:prefix:ICEMX"] module IceMX { diff --git a/slice/Glacier2/PermissionsVerifier.ice b/slice/Glacier2/PermissionsVerifier.ice index 85b2a7d47ee..6a1051989fa 100644 --- a/slice/Glacier2/PermissionsVerifier.ice +++ b/slice/Glacier2/PermissionsVerifier.ice @@ -9,11 +9,12 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:Glacier2/Config.h"]] #include <Glacier2/SSLInfo.ice> +["objc:prefix:GLACIER2"] module Glacier2 { diff --git a/slice/Glacier2/PermissionsVerifierF.ice b/slice/Glacier2/PermissionsVerifierF.ice index 45ad1590d0b..f1bb1d65279 100644 --- a/slice/Glacier2/PermissionsVerifierF.ice +++ b/slice/Glacier2/PermissionsVerifierF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:GLACIER2"] module Glacier2 { diff --git a/slice/Glacier2/Router.ice b/slice/Glacier2/Router.ice index 4f85e0fd1ff..d1f75b16639 100644 --- a/slice/Glacier2/Router.ice +++ b/slice/Glacier2/Router.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:Glacier2/Config.h"]] #include <Ice/Router.ice> @@ -24,6 +24,7 @@ * security solution that is both non-intrusive and easy to configure. * **/ +["objc:prefix:GLACIER2"] module Glacier2 { diff --git a/slice/Glacier2/RouterF.ice b/slice/Glacier2/RouterF.ice index bbaef076ea2..3117d525a1d 100644 --- a/slice/Glacier2/RouterF.ice +++ b/slice/Glacier2/RouterF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:GLACIER2"] module Glacier2 { diff --git a/slice/Glacier2/SSLInfo.ice b/slice/Glacier2/SSLInfo.ice index 106d76787f5..2c68700a057 100644 --- a/slice/Glacier2/SSLInfo.ice +++ b/slice/Glacier2/SSLInfo.ice @@ -9,11 +9,12 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:Glacier2/Config.h"]] #include <Ice/BuiltinSequences.ice> +["objc:prefix:GLACIER2"] module Glacier2 { diff --git a/slice/Glacier2/Session.ice b/slice/Glacier2/Session.ice index a18badf5e42..404bb5ed47a 100644 --- a/slice/Glacier2/Session.ice +++ b/slice/Glacier2/Session.ice @@ -9,13 +9,14 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:Glacier2/Config.h"]] #include <Ice/BuiltinSequences.ice> #include <Ice/Identity.ice> #include <Glacier2/SSLInfo.ice> +["objc:prefix:GLACIER2"] module Glacier2 { diff --git a/slice/Ice/BuiltinSequences.ice b/slice/Ice/BuiltinSequences.ice index da8a953933b..a2a08cea140 100644 --- a/slice/Ice/BuiltinSequences.ice +++ b/slice/Ice/BuiltinSequences.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Communicator.ice b/slice/Ice/Communicator.ice index 7065d5939cc..8038accab63 100644 --- a/slice/Ice/Communicator.ice +++ b/slice/Ice/Communicator.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/LoggerF.ice> #include <Ice/InstrumentationF.ice> @@ -32,6 +32,7 @@ * additional functionality that supports high scalability. * **/ +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/CommunicatorF.ice b/slice/Ice/CommunicatorF.ice index 158946e8272..f07c4ddd447 100644 --- a/slice/Ice/CommunicatorF.ice +++ b/slice/Ice/CommunicatorF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Connection.ice b/slice/Ice/Connection.ice index 0155b21ac50..87ba30de06b 100644 --- a/slice/Ice/Connection.ice +++ b/slice/Ice/Connection.ice @@ -10,12 +10,13 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/ObjectAdapterF.ice> #include <Ice/Identity.ice> #include <Ice/Endpoint.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/ConnectionF.ice b/slice/Ice/ConnectionF.ice index 1e09403be7b..9efb4ac85e1 100644 --- a/slice/Ice/ConnectionF.ice +++ b/slice/Ice/ConnectionF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Current.ice b/slice/Ice/Current.ice index 5aeec6baa25..b360fc10e7b 100644 --- a/slice/Ice/Current.ice +++ b/slice/Ice/Current.ice @@ -9,13 +9,14 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/ObjectAdapterF.ice> #include <Ice/ConnectionF.ice> #include <Ice/Identity.ice> #include <Ice/Version.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Endpoint.ice b/slice/Ice/Endpoint.ice index 35c06d7725b..1048e1c01ab 100644 --- a/slice/Ice/Endpoint.ice +++ b/slice/Ice/Endpoint.ice @@ -13,8 +13,9 @@ #include <Ice/BuiltinSequences.ice> #include <Ice/EndpointF.ice> -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/EndpointF.ice b/slice/Ice/EndpointF.ice index 5eb3c8102c0..e3d34d34429 100644 --- a/slice/Ice/EndpointF.ice +++ b/slice/Ice/EndpointF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/EndpointTypes.ice b/slice/Ice/EndpointTypes.ice index c12ee281ffa..c989a99fae9 100644 --- a/slice/Ice/EndpointTypes.ice +++ b/slice/Ice/EndpointTypes.ice @@ -10,8 +10,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/FacetMap.ice b/slice/Ice/FacetMap.ice index 0beb04457c8..04db5977215 100644 --- a/slice/Ice/FacetMap.ice +++ b/slice/Ice/FacetMap.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Identity.ice b/slice/Ice/Identity.ice index 5ce62a9c179..cf2f0b9b9bd 100644 --- a/slice/Ice/Identity.ice +++ b/slice/Ice/Identity.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/ImplicitContext.ice b/slice/Ice/ImplicitContext.ice index 83d1016119d..b40ee011237 100644 --- a/slice/Ice/ImplicitContext.ice +++ b/slice/Ice/ImplicitContext.ice @@ -9,11 +9,12 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/LocalException.ice> #include <Ice/Current.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/ImplicitContextF.ice b/slice/Ice/ImplicitContextF.ice index d9fa5e9475e..f18fa4c8c7b 100644 --- a/slice/Ice/ImplicitContextF.ice +++ b/slice/Ice/ImplicitContextF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Instrumentation.ice b/slice/Ice/Instrumentation.ice index 3e93a1a0c5f..353f1b4671b 100644 --- a/slice/Ice/Instrumentation.ice +++ b/slice/Ice/Instrumentation.ice @@ -9,12 +9,13 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/EndpointF.ice> #include <Ice/ConnectionF.ice> #include <Ice/Current.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/InstrumentationF.ice b/slice/Ice/InstrumentationF.ice index 3cbb0048a73..5fe3be61347 100644 --- a/slice/Ice/InstrumentationF.ice +++ b/slice/Ice/InstrumentationF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/LocalException.ice b/slice/Ice/LocalException.ice index 81246e29b6c..1c3c9654f5a 100644 --- a/slice/Ice/LocalException.ice +++ b/slice/Ice/LocalException.ice @@ -9,12 +9,13 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/Identity.ice> #include <Ice/Version.ice> #include <Ice/BuiltinSequences.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Locator.ice b/slice/Ice/Locator.ice index 15551c6a71a..169e9bb87e0 100644 --- a/slice/Ice/Locator.ice +++ b/slice/Ice/Locator.ice @@ -9,11 +9,13 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] + #include <Ice/Identity.ice> #include <Ice/ProcessF.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/LocatorF.ice b/slice/Ice/LocatorF.ice index 4a0a8656bed..91260f37e1d 100644 --- a/slice/Ice/LocatorF.ice +++ b/slice/Ice/LocatorF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Logger.ice b/slice/Ice/Logger.ice index 626c8825430..2f82c8f576b 100644 --- a/slice/Ice/Logger.ice +++ b/slice/Ice/Logger.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/LoggerF.ice b/slice/Ice/LoggerF.ice index 5a3666f721d..2ea22ab611e 100644 --- a/slice/Ice/LoggerF.ice +++ b/slice/Ice/LoggerF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Metrics.ice b/slice/Ice/Metrics.ice index 89c5bc5ebe1..d099b212e1b 100644 --- a/slice/Ice/Metrics.ice +++ b/slice/Ice/Metrics.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/BuiltinSequences.ice> @@ -20,6 +20,7 @@ * metrics from Ice applications. * **/ +["objc:prefix:ICEMX"] module IceMX { diff --git a/slice/Ice/ObjectAdapter.ice b/slice/Ice/ObjectAdapter.ice index 7b4d4f630ff..439976d85f2 100644 --- a/slice/Ice/ObjectAdapter.ice +++ b/slice/Ice/ObjectAdapter.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/CommunicatorF.ice> #include <Ice/ServantLocatorF.ice> @@ -18,6 +18,7 @@ #include <Ice/FacetMap.ice> #include <Ice/Endpoint.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/ObjectAdapterF.ice b/slice/Ice/ObjectAdapterF.ice index a322483dd28..aa5a6a1b354 100644 --- a/slice/Ice/ObjectAdapterF.ice +++ b/slice/Ice/ObjectAdapterF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/ObjectFactory.ice b/slice/Ice/ObjectFactory.ice index ff84d6440eb..0f1ee3a57d5 100644 --- a/slice/Ice/ObjectFactory.ice +++ b/slice/Ice/ObjectFactory.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/ObjectFactoryF.ice b/slice/Ice/ObjectFactoryF.ice index 284a8032b2e..710b1ee96c5 100644 --- a/slice/Ice/ObjectFactoryF.ice +++ b/slice/Ice/ObjectFactoryF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Plugin.ice b/slice/Ice/Plugin.ice index 8dddfc4b042..37d1167e046 100644 --- a/slice/Ice/Plugin.ice +++ b/slice/Ice/Plugin.ice @@ -10,11 +10,12 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/LoggerF.ice> #include <Ice/BuiltinSequences.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/PluginF.ice b/slice/Ice/PluginF.ice index 7320c96dcaf..ff570c1526a 100644 --- a/slice/Ice/PluginF.ice +++ b/slice/Ice/PluginF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Process.ice b/slice/Ice/Process.ice index 05af33b91b7..08073d39fc2 100644 --- a/slice/Ice/Process.ice +++ b/slice/Ice/Process.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/ProcessF.ice b/slice/Ice/ProcessF.ice index 2d36ac7a096..b824ab321ec 100644 --- a/slice/Ice/ProcessF.ice +++ b/slice/Ice/ProcessF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Properties.ice b/slice/Ice/Properties.ice index d59a6552892..deae17b3747 100644 --- a/slice/Ice/Properties.ice +++ b/slice/Ice/Properties.ice @@ -9,10 +9,11 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/PropertiesAdmin.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/PropertiesAdmin.ice b/slice/Ice/PropertiesAdmin.ice index e379fcc1553..6b8fe6932d9 100644 --- a/slice/Ice/PropertiesAdmin.ice +++ b/slice/Ice/PropertiesAdmin.ice @@ -9,10 +9,11 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/BuiltinSequences.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/PropertiesF.ice b/slice/Ice/PropertiesF.ice index ebf7abb423f..5cc3b3696de 100644 --- a/slice/Ice/PropertiesF.ice +++ b/slice/Ice/PropertiesF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/RemoteLogger.ice b/slice/Ice/RemoteLogger.ice index e15851427ac..bd45e81c5f6 100644 --- a/slice/Ice/RemoteLogger.ice +++ b/slice/Ice/RemoteLogger.ice @@ -11,9 +11,10 @@ #include <Ice/BuiltinSequences.ice> -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:list"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Router.ice b/slice/Ice/Router.ice index 796678e6f1c..44c7957402e 100644 --- a/slice/Ice/Router.ice +++ b/slice/Ice/Router.ice @@ -9,10 +9,11 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/BuiltinSequences.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/RouterF.ice b/slice/Ice/RouterF.ice index 4a0d1b3a6e0..3a74071003d 100644 --- a/slice/Ice/RouterF.ice +++ b/slice/Ice/RouterF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/ServantLocator.ice b/slice/Ice/ServantLocator.ice index 76c51c3b090..c4b24a9d591 100644 --- a/slice/Ice/ServantLocator.ice +++ b/slice/Ice/ServantLocator.ice @@ -9,11 +9,12 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/ObjectAdapterF.ice> #include <Ice/Current.ice> +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/ServantLocatorF.ice b/slice/Ice/ServantLocatorF.ice index f2ab8823195..74f74298b07 100644 --- a/slice/Ice/ServantLocatorF.ice +++ b/slice/Ice/ServantLocatorF.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/SliceChecksumDict.ice b/slice/Ice/SliceChecksumDict.ice index 98060d75043..bb4ee67c3e6 100644 --- a/slice/Ice/SliceChecksumDict.ice +++ b/slice/Ice/SliceChecksumDict.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/Ice/Version.ice b/slice/Ice/Version.ice index 5dc4c7d820b..7291cc43d78 100644 --- a/slice/Ice/Version.ice +++ b/slice/Ice/Version.ice @@ -9,8 +9,9 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] +["objc:prefix:ICE"] module Ice { diff --git a/slice/IceBox/IceBox.ice b/slice/IceBox/IceBox.ice index 8b01bc14c0a..69f6a816beb 100644 --- a/slice/IceBox/IceBox.ice +++ b/slice/IceBox/IceBox.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceBox/Config.h"]] #include <Ice/BuiltinSequences.ice> diff --git a/slice/IceDiscovery/IceDiscovery.ice b/slice/IceDiscovery/IceDiscovery.ice index 1d2519a37f9..decd6e95380 100644 --- a/slice/IceDiscovery/IceDiscovery.ice +++ b/slice/IceDiscovery/IceDiscovery.ice @@ -8,7 +8,7 @@ // ********************************************************************** #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/Identity.ice> diff --git a/slice/IceGrid/Admin.ice b/slice/IceGrid/Admin.ice index 77abfba3994..42c11385002 100644 --- a/slice/IceGrid/Admin.ice +++ b/slice/IceGrid/Admin.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] #include <Ice/Identity.ice> @@ -20,6 +20,7 @@ #include <IceGrid/Exception.ice> #include <IceGrid/Descriptor.ice> +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IceGrid/Descriptor.ice b/slice/IceGrid/Descriptor.ice index ee8501fc844..9c3f35b1825 100644 --- a/slice/IceGrid/Descriptor.ice +++ b/slice/IceGrid/Descriptor.ice @@ -9,12 +9,13 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] #include <Ice/Identity.ice> #include <Ice/BuiltinSequences.ice> +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IceGrid/Discovery.ice b/slice/IceGrid/Discovery.ice index 6c19c91c7bc..d6c36f0f0b6 100644 --- a/slice/IceGrid/Discovery.ice +++ b/slice/IceGrid/Discovery.ice @@ -9,11 +9,12 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] #include <IceGrid/Locator.ice> +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IceGrid/Exception.ice b/slice/IceGrid/Exception.ice index 760c3b72091..98413934a50 100644 --- a/slice/IceGrid/Exception.ice +++ b/slice/IceGrid/Exception.ice @@ -9,12 +9,13 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] #include <Ice/Identity.ice> #include <Ice/BuiltinSequences.ice> +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IceGrid/FileParser.ice b/slice/IceGrid/FileParser.ice index 846f8e21fc4..3572b0c1e94 100644 --- a/slice/IceGrid/FileParser.ice +++ b/slice/IceGrid/FileParser.ice @@ -9,11 +9,12 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] #include <IceGrid/Admin.ice> +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IceGrid/Locator.ice b/slice/IceGrid/Locator.ice index 75f97a9f047..03b3d2328c3 100644 --- a/slice/IceGrid/Locator.ice +++ b/slice/IceGrid/Locator.ice @@ -9,11 +9,12 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] #include <Ice/Locator.ice> +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IceGrid/Observer.ice b/slice/IceGrid/Observer.ice index 2ebcec6888a..ad96b7f6aae 100644 --- a/slice/IceGrid/Observer.ice +++ b/slice/IceGrid/Observer.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] #include <Glacier2/Session.ice> @@ -17,6 +17,7 @@ #include <IceGrid/Descriptor.ice> #include <IceGrid/Admin.ice> +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IceGrid/PluginFacade.ice b/slice/IceGrid/PluginFacade.ice index 60817b555e4..725bac61f10 100644 --- a/slice/IceGrid/PluginFacade.ice +++ b/slice/IceGrid/PluginFacade.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] #include <Ice/BuiltinSequences.ice> @@ -17,6 +17,7 @@ #include <IceGrid/Admin.ice> +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IceGrid/Query.ice b/slice/IceGrid/Query.ice index d055b0c9f75..97c293cd671 100644 --- a/slice/IceGrid/Query.ice +++ b/slice/IceGrid/Query.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] #include <Ice/Identity.ice> @@ -24,6 +24,7 @@ * heterogeneous computer network. * **/ +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IceGrid/Registry.ice b/slice/IceGrid/Registry.ice index 2113225193c..1ea91ea27ad 100644 --- a/slice/IceGrid/Registry.ice +++ b/slice/IceGrid/Registry.ice @@ -9,13 +9,14 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] #include <IceGrid/Exception.ice> #include <IceGrid/Session.ice> #include <IceGrid/Admin.ice> +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IceGrid/Session.ice b/slice/IceGrid/Session.ice index d9cf21e5eae..585f46f5165 100644 --- a/slice/IceGrid/Session.ice +++ b/slice/IceGrid/Session.ice @@ -9,12 +9,13 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] #include <Glacier2/Session.ice> #include <IceGrid/Exception.ice> +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IceGrid/UserAccountMapper.ice b/slice/IceGrid/UserAccountMapper.ice index 5c46d994cb0..a7923407b1a 100644 --- a/slice/IceGrid/UserAccountMapper.ice +++ b/slice/IceGrid/UserAccountMapper.ice @@ -9,9 +9,10 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceGrid/Config.h"]] +["objc:prefix:ICEGRID"] module IceGrid { diff --git a/slice/IcePatch2/FileInfo.ice b/slice/IcePatch2/FileInfo.ice index 99619181403..babae423d79 100644 --- a/slice/IcePatch2/FileInfo.ice +++ b/slice/IcePatch2/FileInfo.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IcePatch2/Config.h"]] #include <Ice/BuiltinSequences.ice> diff --git a/slice/IcePatch2/FileServer.ice b/slice/IcePatch2/FileServer.ice index 1cd957317a2..d95a0fa9d4b 100644 --- a/slice/IcePatch2/FileServer.ice +++ b/slice/IcePatch2/FileServer.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IcePatch2/Config.h"]] #include <IcePatch2/FileInfo.ice> diff --git a/slice/IceSSL/ConnectionInfo.ice b/slice/IceSSL/ConnectionInfo.ice index 2ce533ef73f..5a72675b668 100644 --- a/slice/IceSSL/ConnectionInfo.ice +++ b/slice/IceSSL/ConnectionInfo.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/Connection.ice> diff --git a/slice/IceSSL/EndpointInfo.ice b/slice/IceSSL/EndpointInfo.ice index 539b0226cc9..3e70d90d525 100644 --- a/slice/IceSSL/EndpointInfo.ice +++ b/slice/IceSSL/EndpointInfo.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/Endpoint.ice> diff --git a/slice/IceStorm/IceStorm.ice b/slice/IceStorm/IceStorm.ice index b68debe6a4a..271a20c75fe 100644 --- a/slice/IceStorm/IceStorm.ice +++ b/slice/IceStorm/IceStorm.ice @@ -9,7 +9,7 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceStorm/Config.h"]] #include <Ice/Identity.ice> @@ -25,6 +25,7 @@ * easy as invoking a method on an interface. * **/ +["objc:prefix:ICESTORM"] module IceStorm { diff --git a/slice/IceStorm/Metrics.ice b/slice/IceStorm/Metrics.ice index 208399cb594..0442274298a 100644 --- a/slice/IceStorm/Metrics.ice +++ b/slice/IceStorm/Metrics.ice @@ -9,11 +9,12 @@ #pragma once -[["cpp:header-ext:h"]] +[["cpp:header-ext:h", "objc:header-dir:objc"]] [["cpp:include:IceStorm/Config.h"]] #include <Ice/Metrics.ice> +["objc:prefix:ICEMX"] module IceMX { |