// // Copyright (c) ZeroC, Inc. All rights reserved. // import Dispatch import Foundation import Ice import PromiseKit import TestCommon private func breakCycles(_ value: Value) { if let d1 = value as? D1 { let tmp = d1.pd1 d1.pd1 = nil if tmp != nil, tmp! !== d1 { breakCycles(tmp!) } } if let d2 = value as? D2 { d2.pd2 = nil } if let d4 = value as? D4 { d4.p1 = nil d4.p2 = nil } if let b = value as? B { b.pb?.pb = nil b.pb = nil } if let p = value as? Preserved { p.ice_getSlicedData()?.clear() } if let p = value as? PDerived { p.pb = nil } if let p = value as? CompactPDerived { p.pb = nil } if let p = value as? PCDerived { let a = p.pbs p.pbs = [] for e in a { if let elt = e { breakCycles(elt) } } } if let p = value as? CompactPCDerived { let a = p.pbs p.pbs = [] for e in a { if let elt = e { breakCycles(elt) } } } if var curr = value as? PNode { while curr.next != nil, value !== curr.next { curr = curr.next! } curr.next = nil } if let p = value as? PSUnknown, p.graph != nil { breakCycles(p.graph!) } if let p = value as? PSUnknown2 { p.pb = nil } if let s = value as? SS1 { for b in s.s where b != nil { breakCycles(b!) } } if let s = value as? SS2 { for b in s.s where b != nil { breakCycles(b!) } } if let f = value as? Forward { f.h = nil } if let u = value as? SUnknown { u.cycle = nil } } public func allTests(_ helper: TestHelper) throws -> TestIntfPrx { func test(_ value: Bool, file: String = #file, line: Int = #line) throws { try helper.test(value, file: file, line: line) } let output = helper.getWriter() let communicator = helper.communicator() output.write("testing stringToProxy... ") let basePrx = try communicator.stringToProxy("Test:\(helper.getTestEndpoint(num: 0)) -t 2000")! output.writeLine("ok") output.write("testing checked cast... ") let testPrx = try checkedCast(prx: basePrx, type: TestIntfPrx.self)! try test(testPrx == basePrx) output.writeLine("ok") output.write("base as Object... ") do { let o = try testPrx.SBaseAsObject() let sb = o as! SBase try test(sb.ice_id() == "::Test::SBase") try test(sb.sb == "SBase.sb") breakCycles(sb) } output.writeLine("ok") output.write("base as Object (AMI)... ") try Promise { seal in firstly { testPrx.SBaseAsObjectAsync() }.map { o in let sb = o as! SBase try test(sb.ice_id() == "::Test::SBase") try test(sb.sb == "SBase.sb") breakCycles(sb) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("base as base... ") do { let sb = try testPrx.SBaseAsSBase()! try test(sb.sb == "SBase.sb") breakCycles(sb) } output.writeLine("ok") output.write("base as base (AMI)... ") try Promise { seal in firstly { testPrx.SBaseAsSBaseAsync() }.done { sb in try test(sb!.sb == "SBase.sb") seal.fulfill(()) breakCycles(sb!) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("base with known derived as base... ") do { let sb = try testPrx.SBSKnownDerivedAsSBase()! try test(sb.sb == "SBSKnownDerived.sb") let sbskd = sb as! SBSKnownDerived try test(sbskd.sbskd == "SBSKnownDerived.sbskd") breakCycles(sbskd) } output.writeLine("ok") output.write("base with known derived as base (AMI)... ") try Promise { seal in firstly { testPrx.SBSKnownDerivedAsSBaseAsync() }.done { sb in try test(sb!.sb == "SBSKnownDerived.sb") let sbskd = sb as! SBSKnownDerived try test(sbskd.sbskd == "SBSKnownDerived.sbskd") breakCycles(sbskd) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("base with known derived as known derived... ") do { let sbskd = try testPrx.SBSKnownDerivedAsSBSKnownDerived()! try test(sbskd.sbskd == "SBSKnownDerived.sbskd") breakCycles(sbskd) } output.writeLine("ok") output.write("base with known derived as known derived (AMI)... ") try Promise { seal in firstly { testPrx.SBSKnownDerivedAsSBSKnownDerivedAsync() }.done { sbskd in try test(sbskd!.sbskd == "SBSKnownDerived.sbskd") breakCycles(sbskd!) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("base with unknown derived as base... ") do { let sb = try testPrx.SBSUnknownDerivedAsSBase()! try test(sb.sb == "SBSUnknownDerived.sb") breakCycles(sb) } if testPrx.ice_getEncodingVersion() == Ice.Encoding_1_0 { do { let sb = try testPrx.SBSUnknownDerivedAsSBaseCompact()! try test(sb.sb == "SBSUnknownDerived.sb") breakCycles(sb) } } else { do { // // This test fails when using the compact format because the instance cannot // be sliced to a known type. // _ = try testPrx.SBSUnknownDerivedAsSBaseCompact() try test(false) } catch is Ice.NoValueFactoryException { // Expected. } } output.writeLine("ok") output.write("base with unknown derived as base (AMI)... ") try Promise { seal in firstly { testPrx.SBSUnknownDerivedAsSBaseAsync() }.done { sb in try test(sb!.sb == "SBSUnknownDerived.sb") breakCycles(sb!) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() if testPrx.ice_getEncodingVersion() == Ice.Encoding_1_0 { // // This test succeeds for the 1.0 encoding. // try Promise { seal in firstly { testPrx.SBSUnknownDerivedAsSBaseCompactAsync() }.done { sb in try test(sb!.sb == "SBSUnknownDerived.sb") breakCycles(sb!) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() } else { // // This test fails when using the compact format because the instance cannot // be sliced to a known type. // try Promise { seal in firstly { testPrx.SBSUnknownDerivedAsSBaseCompactAsync() }.done { _ in try test(false) }.catch { ex in do { try test(ex is Ice.NoValueFactoryException) seal.fulfill(()) } catch { seal.reject(error) } } }.wait() } output.writeLine("ok") output.write("unknown with Object as Object... ") do { let o = try testPrx.SUnknownAsObject()! try test(testPrx.ice_getEncodingVersion() != Ice.Encoding_1_0) try test(o is Ice.UnknownSlicedValue) try test((o as! Ice.UnknownSlicedValue).ice_id() == "::Test::SUnknown") try test((o as! Ice.UnknownSlicedValue).ice_getSlicedData() != nil) try testPrx.checkSUnknown(o) (o as! Ice.UnknownSlicedValue).ice_getSlicedData()!.clear() } catch is Ice.NoValueFactoryException { try test(testPrx.ice_getEncodingVersion() == Ice.Encoding_1_0) } output.writeLine("ok") output.write("unknown with Object as Object (AMI)... ") if testPrx.ice_getEncodingVersion() == Ice.Encoding_1_0 { try Promise { seal in firstly { testPrx.SUnknownAsObjectAsync() }.done { _ in try test(false) }.catch { ex in do { try test(ex is Ice.NoValueFactoryException) seal.fulfill(()) } catch { seal.reject(error) } } }.wait() } else { try Promise { seal in firstly { testPrx.SUnknownAsObjectAsync() }.done { o in if let unknown = o as? Ice.UnknownSlicedValue { try test(unknown.ice_id() == "::Test::SUnknown") unknown.ice_getSlicedData()!.clear() } else { try test(false) } seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() } output.writeLine("ok") output.write("one-element cycle... ") do { let b = try testPrx.oneElementCycle()! try test(b.ice_id() == "::Test::B") try test(b.sb == "B1.sb") try test(b.pb === b) breakCycles(b) } output.writeLine("ok") output.write("one-element cycle (AMI)... ") try Promise { seal in firstly { testPrx.oneElementCycleAsync() }.done { b in try test(b!.ice_id() == "::Test::B") try test(b!.sb == "B1.sb") try test(b!.pb === b) breakCycles(b!) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("two-element cycle... ") do { let b1 = try testPrx.twoElementCycle()! try test(b1.ice_id() == "::Test::B") try test(b1.sb == "B1.sb") let b2 = b1.pb! try test(b2.ice_id() == "::Test::B") try test(b2.sb == "B2.sb") try test(b2.pb === b1) breakCycles(b1) } output.writeLine("ok") output.write("two-element cycle (AMI)... ") try Promise { seal in firstly { testPrx.twoElementCycleAsync() }.done { o in let b1 = o! try test(b1.ice_id() == "::Test::B") try test(b1.sb == "B1.sb") let b2 = b1.pb! try test(b2.ice_id() == "::Test::B") try test(b2.sb == "B2.sb") try test(b2.pb === b1) breakCycles(b1) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("known derived pointer slicing as base... ") do { let b1 = try testPrx.D1AsB()! try test(b1.ice_id() == "::Test::D1") try test(b1.sb == "D1.sb") try test(b1.pb !== nil) try test(b1.pb !== b1) if let d1 = b1 as? D1 { try test(d1.sd1 == "D1.sd1") try test(d1.pd1 !== nil) try test(d1.pd1 !== b1) try test(b1.pb === d1.pd1) } else { try test(false) } let b2 = b1.pb! try test(b2.pb === b1) try test(b2.sb == "D2.sb") try test(b2.ice_id() == "::Test::B") breakCycles(b1) } output.writeLine("ok") output.write("known derived pointer slicing as base (AMI)... ") try Promise { seal in firstly { testPrx.D1AsBAsync() }.done { o in let b1 = o! try test(b1.ice_id() == "::Test::D1") try test(b1.sb == "D1.sb") try test(b1.pb !== nil) try test(b1.pb !== b1) if let d1 = b1 as? D1 { try test(d1.sd1 == "D1.sd1") try test(d1.pd1 !== nil) try test(d1.pd1 !== b1) try test(b1.pb === d1.pd1) } else { try test(false) } let b2 = b1.pb! try test(b2.pb === b1) try test(b2.sb == "D2.sb") try test(b2.ice_id() == "::Test::B") breakCycles(b1) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("known derived pointer slicing as derived... ") do { let d1 = try testPrx.D1AsD1()! try test(d1.ice_id() == "::Test::D1") try test(d1.sb == "D1.sb") try test(d1.pb !== nil) try test(d1.pb !== d1) let b2 = d1.pb! try test(b2.ice_id() == "::Test::B") try test(b2.sb == "D2.sb") try test(b2.pb === d1) breakCycles(d1) } output.writeLine("ok") output.write("known derived pointer slicing as derived (AMI)... ") try Promise { seal in firstly { testPrx.D1AsD1Async() }.done { o in let d1 = o! try test(d1.ice_id() == "::Test::D1") try test(d1.sb == "D1.sb") try test(d1.pb !== nil) try test(d1.pb !== d1) let b2 = d1.pb! try test(b2.ice_id() == "::Test::B") try test(b2.sb == "D2.sb") try test(b2.pb === d1) breakCycles(d1) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("unknown derived pointer slicing as base... ") do { let b2 = try testPrx.D2AsB()! try test(b2.ice_id() == "::Test::B") try test(b2.sb == "D2.sb") try test(b2.pb !== nil) try test(b2.pb !== b2) let b1 = b2.pb! try test(b1.ice_id() == "::Test::D1") try test(b1.sb == "D1.sb") try test(b1.pb === b2) if let d1 = b1 as? D1 { try test(d1.sd1 == "D1.sd1") try test(d1.pd1 === b2) breakCycles(b2) } else { try test(false) } } output.writeLine("ok") output.write("unknown derived pointer slicing as base (AMI)... ") try Promise { seal in firstly { testPrx.D2AsBAsync() }.done { o in let b2 = o! try test(b2.ice_id() == "::Test::B") try test(b2.sb == "D2.sb") try test(b2.pb !== nil) try test(b2.pb !== b2) let b1 = b2.pb! try test(b1.ice_id() == "::Test::D1") try test(b1.sb == "D1.sb") try test(b1.pb === b2) if let d1 = b1 as? D1 { try test(d1.sd1 == "D1.sd1") try test(d1.pd1 === b2) breakCycles(b2) } else { try test(false) } seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("param ptr slicing with known first... ") do { let (b1, b2) = try testPrx.paramTest1() try test(b1 !== nil) try test(b1!.ice_id() == "::Test::D1") try test(b1!.sb == "D1.sb") try test(b1!.pb === b2) let d1 = b1 as! D1 try test(d1.sd1 == "D1.sd1") try test(d1.pd1 === b2) try test(b2 !== nil) // No factory, must be sliced try test(b2!.ice_id() == "::Test::B") try test(b2!.sb == "D2.sb") try test(b2!.pb === b1) breakCycles(b1!) breakCycles(b2!) } output.writeLine("ok") output.write("param ptr slicing with known first (AMI)... ") try Promise { seal in firstly { testPrx.paramTest1Async() }.done { o1, o2 in try test(o1 != nil && o2 != nil) let b1 = o1! let b2 = o2! try test(b1.ice_id() == "::Test::D1") try test(b1.sb == "D1.sb") try test(b1.pb === b2) let d1 = b1 as! D1 try test(d1.sd1 == "D1.sd1") try test(d1.pd1 === b2) // No factory, must be sliced try test(b2.ice_id() == "::Test::B") try test(b2.sb == "D2.sb") try test(b2.pb === b1) breakCycles(b1) breakCycles(b2) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("param ptr slicing with unknown first... ") do { let (o2, o1) = try testPrx.paramTest2() try test(o1 != nil && o2 != nil) let b1 = o1! let b2 = o2! try test(b1.ice_id() == "::Test::D1") try test(b1.sb == "D1.sb") try test(b1.pb === b2) if let d1 = b1 as? D1 { try test(d1.sd1 == "D1.sd1") try test(d1.pd1 === b2) } else { try test(false) } // No factory, must be sliced try test(b2.ice_id() == "::Test::B") try test(b2.sb == "D2.sb") try test(b2.pb === b1) breakCycles(b1) breakCycles(b2) } output.writeLine("ok") output.write("param ptr slicing with unknown first (AMI)... ") try Promise { seal in firstly { testPrx.paramTest2Async() }.done { o2, o1 in try test(o2 != nil && o1 != nil) let b1 = o1! let b2 = o2! try test(b1.ice_id() == "::Test::D1") try test(b1.sb == "D1.sb") try test(b1.pb === b2) if let d1 = b1 as? D1 { try test(d1.sd1 == "D1.sd1") try test(d1.pd1 === b2) } else { try test(false) } // No factory, must be sliced try test(b2.ice_id() == "::Test::B") try test(b2.sb == "D2.sb") try test(b2.pb === b1) breakCycles(b1) breakCycles(b2) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("return value identity with known first... ") do { let (ret, p1, _) = try testPrx.returnTest1() try test(ret === p1) breakCycles(ret!) } output.writeLine("ok") output.write("return value identity with known first (AMI)... ") try Promise { seal in firstly { testPrx.returnTest1Async() }.done { r, p1, _ in try test(r === p1) breakCycles(r!) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("return value identity with unknown first... ") do { let (ret, p1, _) = try testPrx.returnTest2() try test(ret === p1) breakCycles(ret!) } output.writeLine("ok") output.write("return value identity with unknown first (AMI)... ") try Promise { seal in firstly { testPrx.returnTest2Async() }.done { r, p1, _ in try test(r === p1) breakCycles(r!) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("return value identity for input params known first... ") do { let d1 = D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" let d3 = D3() d3.pb = d1 d3.sb = "D3.sb" d3.sd3 = "D3.sd3" d3.pd3 = d1 d1.pb = d3 d1.pd1 = d3 let b1 = try testPrx.returnTest3(p1: d1, p2: d3)! try test(b1.sb == "D1.sb") try test(b1.ice_id() == "::Test::D1") if let p1 = b1 as? D1 { try test(p1.sd1 == "D1.sd1") try test(p1.pd1 === b1.pb) } else { try test(false) } let b2 = b1.pb! try test(b2.sb == "D3.sb") // Sliced by server try test(b2.ice_id() == "::Test::B") try test(b2.pb === b1) try test(!(b2 is D3)) try test(b1 !== d1) try test(b1 !== d3) try test(b2 !== d1) try test(b2 !== d3) breakCycles(b1) breakCycles(d1) breakCycles(d3) } output.writeLine("ok") output.write("return value identity for input params known first (AMI)... ") do { let d1 = D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" let d3 = D3() d3.pb = d1 d3.sb = "D3.sb" d3.sd3 = "D3.sd3" d3.pd3 = d1 d1.pb = d3 d1.pd1 = d3 try Promise { seal in firstly { testPrx.returnTest3Async(p1: d1, p2: d3) }.done { b in try test(b != nil) let b1 = b! try test(b1.sb == "D1.sb") try test(b1.ice_id() == "::Test::D1") if let p1 = b1 as? D1 { try test(p1.sd1 == "D1.sd1") try test(p1.pd1 === b1.pb) } else { try test(false) } let b2 = b1.pb! try test(b2.sb == "D3.sb") // Sliced by server try test(b2.ice_id() == "::Test::B") try test(b2.pb === b1) try test(!(b2 is D3)) try test(b1 !== d1) try test(b1 !== d3) try test(b2 !== d1) try test(b2 !== d3) breakCycles(b1) breakCycles(d1) breakCycles(d3) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") } output.write("return value identity for input params unknown first... ") do { let d1 = D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" let d3 = D3() d3.pb = d1 d3.sb = "D3.sb" d3.sd3 = "D3.sd3" d3.pd3 = d1 d1.pb = d3 d1.pd1 = d3 let b1 = try testPrx.returnTest3(p1: d3, p2: d1)! try test(b1.sb == "D3.sb") try test(b1.ice_id() == "::Test::B") // Sliced by server try test(!(b1 is D3)) let b2 = b1.pb! try test(b2.sb == "D1.sb") try test(b2.ice_id() == "::Test::D1") try test(b2.pb === b1) if let p3 = b2 as? D1 { try test(p3.sd1 == "D1.sd1") try test(p3.pd1 === b1) } else { try test(false) } try test(b1 !== d1) try test(b1 !== d3) try test(b2 !== d1) try test(b2 !== d3) breakCycles(b1) breakCycles(d1) breakCycles(d3) } output.writeLine("ok") output.write("return value identity for input params unknown first (AMI)... ") try Promise { seal in let d1 = D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" let d3 = D3() d3.pb = d1 d3.sb = "D3.sb" d3.sd3 = "D3.sd3" d3.pd3 = d1 d1.pb = d3 d1.pd1 = d3 firstly { testPrx.returnTest3Async(p1: d3, p2: d1) }.done { b in try test(b != nil) let b1 = b! try test(b1.sb == "D3.sb") try test(b1.ice_id() == "::Test::B") // Sliced by server try test(!(b1 is D3)) let b2 = b1.pb! try test(b2.sb == "D1.sb") try test(b2.ice_id() == "::Test::D1") try test(b2.pb === b1) if let p3 = b2 as? D1 { try test(p3.sd1 == "D1.sd1") try test(p3.pd1 === b1) } else { try test(false) } try test(b1 !== d1) try test(b1 !== d3) try test(b2 !== d1) try test(b2 !== d3) breakCycles(b1) breakCycles(d1) breakCycles(d3) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("remainder unmarshaling (3 instances)... ") do { let (ret1, o1, o2) = try testPrx.paramTest3() try test(o1 != nil) let p1 = o1! try test(p1.sb == "D2.sb (p1 1)") try test(p1.pb == nil) try test(p1.ice_id() == "::Test::B") try test(o2 != nil) let p2 = o2! try test(p2.sb == "D2.sb (p2 1)") try test(p2.pb == nil) try test(p2.ice_id() == "::Test::B") try test(ret1 != nil) let ret = ret1! try test(ret.sb == "D1.sb (p2 2)") try test(ret.pb == nil) try test(ret.ice_id() == "::Test::D1") breakCycles(ret) breakCycles(p1) breakCycles(p2) } output.writeLine("ok") output.write("remainder unmarshaling (3 instances) (AMI)... ") try Promise { seal in firstly { testPrx.paramTest3Async() }.done { ret1, o1, o2 in try test(o1 != nil) let p1 = o1! try test(p1.sb == "D2.sb (p1 1)") try test(p1.pb == nil) try test(p1.ice_id() == "::Test::B") try test(o2 != nil) let p2 = o2! try test(p2.sb == "D2.sb (p2 1)") try test(p2.pb == nil) try test(p2.ice_id() == "::Test::B") try test(ret1 != nil) let ret = ret1! try test(ret.sb == "D1.sb (p2 2)") try test(ret.pb == nil) try test(ret.ice_id() == "::Test::D1") breakCycles(ret) breakCycles(p1) breakCycles(p2) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("remainder unmarshaling (4 instances)... ") do { let (ret1, b1) = try testPrx.paramTest4() try test(b1 != nil) let b = b1! try test(b.sb == "D4.sb (1)") try test(b.pb == nil) try test(b.ice_id() == "::Test::B") try test(ret1 != nil) let ret = ret1! try test(ret.sb == "B.sb (2)") try test(ret.pb == nil) try test(ret.ice_id() == "::Test::B") breakCycles(ret) breakCycles(b) } output.writeLine("ok") output.write("remainder unmarshaling (4 instances) (AMI)... ") try Promise { seal in firstly { testPrx.paramTest4Async() }.done { ret1, b1 in try test(b1 != nil) let b = b1! try test(b.sb == "D4.sb (1)") try test(b.pb == nil) try test(b.ice_id() == "::Test::B") try test(ret1 != nil) let ret = ret1! try test(ret.sb == "B.sb (2)") try test(ret.pb == nil) try test(ret.ice_id() == "::Test::B") breakCycles(ret) breakCycles(b) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("param ptr slicing, instance marshaled in unknown derived as base... ") do { let b1 = B() b1.sb = "B.sb(1)" b1.pb = b1 let d3 = D3() d3.sb = "D3.sb" d3.pb = d3 d3.sd3 = "D3.sd3" d3.pd3 = b1 let b2 = B() b2.sb = "B.sb(2)" b2.pb = b1 let ret = try testPrx.returnTest3(p1: d3, p2: b2)! try test(ret.ice_id() == "::Test::B") try test(ret.sb == "D3.sb") try test(ret.pb === ret) breakCycles(ret) breakCycles(b1) breakCycles(d3) } output.writeLine("ok") output.write("param ptr slicing, instance marshaled in unknown derived as base (AMI)... ") try Promise { seal in let b1 = B() b1.sb = "B.sb(1)" b1.pb = b1 let d3 = D3() d3.sb = "D3.sb" d3.pb = d3 d3.sd3 = "D3.sd3" d3.pd3 = b1 let b2 = B() b2.sb = "B.sb(2)" b2.pb = b1 firstly { testPrx.returnTest3Async(p1: d3, p2: b2) }.done { r in try test(r != nil) let ret = r! try test(ret.ice_id() == "::Test::B") try test(ret.sb == "D3.sb") try test(ret.pb === ret) breakCycles(ret) breakCycles(b1) breakCycles(d3) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("param ptr slicing, instance marshaled in unknown derived as derived... ") do { let d11 = D1() d11.sb = "D1.sb(1)" d11.pb = d11 d11.sd1 = "D1.sd1(1)" let d3 = D3() d3.sb = "D3.sb" d3.pb = d3 d3.sd3 = "D3.sd3" d3.pd3 = d11 let d12 = D1() d12.sb = "D1.sb(2)" d12.pb = d12 d12.sd1 = "D1.sd1(2)" d12.pd1 = d11 let ret = try testPrx.returnTest3(p1: d3, p2: d12)! try test(ret.ice_id() == "::Test::B") try test(ret.sb == "D3.sb") try test(ret.pb === ret) breakCycles(d3) breakCycles(d11) breakCycles(d12) breakCycles(ret) } output.writeLine("ok") output.write("param ptr slicing, instance marshaled in unknown derived as derived (AMI)... ") try Promise { seal in let d11 = D1() d11.sb = "D1.sb(1)" d11.pb = d11 d11.sd1 = "D1.sd1(1)" let d3 = D3() d3.sb = "D3.sb" d3.pb = d3 d3.sd3 = "D3.sd3" d3.pd3 = d11 let d12 = D1() d12.sb = "D1.sb(2)" d12.pb = d12 d12.sd1 = "D1.sd1(2)" d12.pd1 = d11 firstly { testPrx.returnTest3Async(p1: d3, p2: d12) }.done { r in try test(r != nil) let ret = r! try test(ret.ice_id() == "::Test::B") try test(ret.sb == "D3.sb") try test(ret.pb === ret) breakCycles(d3) breakCycles(d11) breakCycles(d12) breakCycles(ret) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("sequence slicing... ") do { let ss1b = B() ss1b.sb = "B.sb" ss1b.pb = ss1b let ss1d1 = D1() ss1d1.sb = "D1.sb" ss1d1.sd1 = "D1.sd1" ss1d1.pb = ss1b let ss1d3 = D3() ss1d3.sb = "D3.sb" ss1d3.sd3 = "D3.sd3" ss1d3.pb = ss1b let ss2b = B() ss2b.sb = "B.sb" ss2b.pb = ss1b let ss2d1 = D1() ss2d1.sb = "D1.sb" ss2d1.sd1 = "D1.sd1" ss2d1.pb = ss2b let ss2d3 = D3() ss2d3.sb = "D3.sb" ss2d3.sd3 = "D3.sd3" ss2d3.pb = ss2b ss1d1.pd1 = ss2b ss1d3.pd3 = ss2d1 ss2d1.pd1 = ss1d3 ss2d3.pd3 = ss1d1 let ss1 = SS1() ss1.s = [ss1b, ss1d1, ss1d3] let ss2 = SS2() ss2.s = [ss2b, ss2d1, ss2d3] let ss = try testPrx.sequenceTest(p1: ss1, p2: ss2) breakCycles(ss1) breakCycles(ss2) try test(ss.c1 != nil) let ss1b2 = ss.c1!.s[0] let ss1d2 = ss.c1!.s[1] try test(ss.c2 != nil) let ss1d4 = ss.c1!.s[2] try test(ss.c2 != nil) let ss2b2 = ss.c2!.s[0] let ss2d2 = ss.c2!.s[1] let ss2d4 = ss.c2!.s[2] try test(ss1b2!.pb === ss1b2) try test(ss1d2!.pb === ss1b2) try test(ss1d4!.pb === ss1b2) try test(ss2b2!.pb === ss1b2) try test(ss2d2!.pb === ss2b2) try test(ss2d4!.pb === ss2b2) try test(ss1b2!.ice_id() == "::Test::B") try test(ss1d2!.ice_id() == "::Test::D1") try test(ss1d4!.ice_id() == "::Test::B") try test(ss2b2!.ice_id() == "::Test::B") try test(ss2d2!.ice_id() == "::Test::D1") try test(ss2d4!.ice_id() == "::Test::B") breakCycles(ss.c1!) breakCycles(ss.c2!) } output.writeLine("ok") output.write("sequence slicing (AMI)... ") try Promise { seal in let ss1b = B() ss1b.sb = "B.sb" ss1b.pb = ss1b let ss1d1 = D1() ss1d1.sb = "D1.sb" ss1d1.sd1 = "D1.sd1" ss1d1.pb = ss1b let ss1d3 = D3() ss1d3.sb = "D3.sb" ss1d3.sd3 = "D3.sd3" ss1d3.pb = ss1b let ss2b = B() ss2b.sb = "B.sb" ss2b.pb = ss1b let ss2d1 = D1() ss2d1.sb = "D1.sb" ss2d1.sd1 = "D1.sd1" ss2d1.pb = ss2b let ss2d3 = D3() ss2d3.sb = "D3.sb" ss2d3.sd3 = "D3.sd3" ss2d3.pb = ss2b ss1d1.pd1 = ss2b ss1d3.pd3 = ss2d1 ss2d1.pd1 = ss1d3 ss2d3.pd3 = ss1d1 let ss1 = SS1() ss1.s = [ss1b, ss1d1, ss1d3] let ss2 = SS2() ss2.s = [ss2b, ss2d1, ss2d3] firstly { testPrx.sequenceTestAsync(p1: ss1, p2: ss2) }.done { ss in breakCycles(ss1) breakCycles(ss2) try test(ss.c1 != nil) let ss1b2 = ss.c1!.s[0] let ss1d2 = ss.c1!.s[1] try test(ss.c2 != nil) let ss1d4 = ss.c1!.s[2] try test(ss.c2 != nil) let ss2b2 = ss.c2!.s[0] let ss2d2 = ss.c2!.s[1] let ss2d4 = ss.c2!.s[2] try test(ss1b2!.pb === ss1b2) try test(ss1d2!.pb === ss1b2) try test(ss1d4!.pb === ss1b2) try test(ss2b2!.pb === ss1b2) try test(ss2d2!.pb === ss2b2) try test(ss2d4!.pb === ss2b2) try test(ss1b2!.ice_id() == "::Test::B") try test(ss1d2!.ice_id() == "::Test::D1") try test(ss1d4!.ice_id() == "::Test::B") try test(ss2b2!.ice_id() == "::Test::B") try test(ss2d2!.ice_id() == "::Test::D1") try test(ss2d4!.ice_id() == "::Test::B") breakCycles(ss.c1!) breakCycles(ss.c2!) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("dictionary slicing... ") do { var bin = [Int32: B]() for i: Int32 in 0 ..< 10 { let s = "D1.\(i)" let d1 = D1() d1.sb = s d1.pb = d1 d1.sd1 = s bin[i] = d1 } let (ret, bout) = try testPrx.dictionaryTest(bin) try test(bout.count == 10) for i: Int32 in 0 ..< 10 { let b = bout[i * 10]!! let s = "D1.\(i)" try test(b.sb == s) try test(b.pb !== nil) try test(b.pb !== b) try test(b.pb!.sb == s) try test(b.pb!.pb === b.pb) } try test(ret.count == 10) for i: Int32 in 0 ..< 10 { let b = ret[i * 20]!! let s = "D1.\(i * 20)" try test(b.sb == s) if i == 0 { try test(b.pb == nil) } else { try test(b.pb === ret[(i - 1) * 20]!) } if let d1 = b as? D1 { try test(d1.sd1 == s) try test(d1.pd1 === d1) } else { try test(false) } } for i in bin { breakCycles(i.value) } for i in bout where i.value != nil { breakCycles(i.value!) } for i in ret where i.value != nil { breakCycles(i.value!) } } output.writeLine("ok") output.write("dictionary slicing (AMI)... ") try Promise { seal in var bin = [Int32: B]() for i: Int32 in 0 ..< 10 { let s = "D1.\(i)" let d1 = D1() d1.sb = s d1.pb = d1 d1.sd1 = s bin[i] = d1 } firstly { testPrx.dictionaryTestAsync(bin) }.done { ret, bout in try test(bout.count == 10) for i: Int32 in 0 ..< 10 { let b = bout[i * 10]!! let s = "D1.\(i)" try test(b.sb == s) try test(b.pb !== nil) try test(b.pb !== b) try test(b.pb!.sb == s) try test(b.pb!.pb === b.pb) } try test(ret.count == 10) for i: Int32 in 0 ..< 10 { let b = ret[i * 20]!! let s = "D1.\(i * 20)" try test(b.sb == s) if i == 0 { try test(b.pb == nil) } else { try test(b.pb === ret[(i - 1) * 20]!) } if let d1 = b as? D1 { try test(d1.sd1 == s) try test(d1.pd1 === d1) } else { try test(false) } } for i in bin { breakCycles(i.value) } for i in bout where i.value != nil { breakCycles(i.value!) } for i in ret where i.value != nil { breakCycles(i.value!) } seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("base exception thrown as base exception... ") do { try testPrx.throwBaseAsBase() try test(false) } catch let e as BaseException { try test(e.sbe == "sbe") try test(e.pb != nil) try test(e.pb!.sb == "sb") try test(e.pb!.pb === e.pb) breakCycles(e.pb!) } output.writeLine("ok") output.write("base exception thrown as base exception (AMI)... ") try Promise { seal in firstly { testPrx.throwBaseAsBaseAsync() }.done { try test(false) }.catch { ex in do { if let e = ex as? BaseException { try test(e.sbe == "sbe") try test(e.pb != nil) try test(e.pb!.sb == "sb") try test(e.pb!.pb === e.pb) breakCycles(e.pb!) } else { try test(false) } seal.fulfill(()) } catch { seal.reject(error) } } }.wait() output.writeLine("ok") output.write("derived exception thrown as base exception... ") do { try testPrx.throwDerivedAsBase() try test(false) } catch let e as DerivedException { try test(e.sbe == "sbe") try test(e.pb != nil) try test(e.pb!.sb == "sb1") try test(e.pb!.pb === e.pb) try test(e.sde == "sde1") try test(e.pd1 != nil) try test(e.pd1!.sb == "sb2") try test(e.pd1!.pb === e.pd1) try test(e.pd1!.sd1 == "sd2") try test(e.pd1!.pd1 === e.pd1) breakCycles(e.pb!) breakCycles(e.pd1!) } output.writeLine("ok") output.write("derived exception thrown as base exception (AMI)... ") try Promise { seal in firstly { testPrx.throwDerivedAsBaseAsync() }.done { try test(false) }.catch { ex in do { if let e = ex as? DerivedException { try test(e.sbe == "sbe") try test(e.pb != nil) try test(e.pb!.sb == "sb1") try test(e.pb!.pb === e.pb) try test(e.sde == "sde1") try test(e.pd1 != nil) try test(e.pd1!.sb == "sb2") try test(e.pd1!.pb === e.pd1) try test(e.pd1!.sd1 == "sd2") try test(e.pd1!.pd1 === e.pd1) breakCycles(e.pb!) breakCycles(e.pd1!) } else { try test(false) } seal.fulfill(()) } catch { seal.reject(error) } } }.wait() output.writeLine("ok") output.write("derived exception thrown as derived exception... ") do { try testPrx.throwDerivedAsDerived() try test(false) } catch let e as DerivedException { try test(e.sbe == "sbe") try test(e.pb != nil) try test(e.pb!.sb == "sb1") try test(e.pb!.pb === e.pb) try test(e.sde == "sde1") try test(e.pd1 != nil) try test(e.pd1!.sb == "sb2") try test(e.pd1!.pb === e.pd1) try test(e.pd1!.sd1 == "sd2") try test(e.pd1!.pd1 === e.pd1) breakCycles(e.pb!) breakCycles(e.pd1!) } output.writeLine("ok") output.write("derived exception thrown as derived exception (AMI)... ") try Promise { seal in firstly { testPrx.throwDerivedAsDerivedAsync() }.done { try test(false) }.catch { ex in do { if let e = ex as? DerivedException { try test(e.sbe == "sbe") try test(e.pb != nil) try test(e.pb!.sb == "sb1") try test(e.pb!.pb === e.pb) try test(e.sde == "sde1") try test(e.pd1 != nil) try test(e.pd1!.sb == "sb2") try test(e.pd1!.pb === e.pd1) try test(e.pd1!.sd1 == "sd2") try test(e.pd1!.pd1 === e.pd1) breakCycles(e.pb!) breakCycles(e.pd1!) } else { try test(false) } seal.fulfill(()) } catch { seal.reject(error) } } }.wait() output.writeLine("ok") output.write("unknown derived exception thrown as base exception... ") do { try testPrx.throwUnknownDerivedAsBase() try test(false) } catch let e as BaseException { try test(e.sbe == "sbe") try test(e.pb != nil) try test(e.pb!.sb == "sb d2") try test(e.pb!.pb === e.pb) breakCycles(e.pb!) } output.writeLine("ok") output.write("unknown derived exception thrown as base exception (AMI)... ") try Promise { seal in firstly { testPrx.throwUnknownDerivedAsBaseAsync() }.done { try test(false) }.catch { ex in do { if let e = ex as? BaseException { try test(e.sbe == "sbe") try test(e.pb != nil) try test(e.pb!.sb == "sb d2") try test(e.pb!.pb === e.pb) breakCycles(e.pb!) } else { try test(false) } seal.fulfill(()) } catch { seal.reject(error) } } }.wait() output.writeLine("ok") output.write("forward-declared class... ") do { let f = try testPrx.useForward() try test(f != nil) breakCycles(f!) } output.writeLine("ok") output.write("forward-declared class (AMI)... ") try Promise { seal in firstly { testPrx.useForwardAsync() }.done { f in try test(f != nil) breakCycles(f!) seal.fulfill(()) }.catch { e in seal.reject(e) } }.wait() output.writeLine("ok") output.write("preserved classes... ") // // Register a factory in order to substitute our own subclass of Preserved. This provides // an easy way to determine how many unmarshaled instances currently exist. // // We have to install this now (even though it's not necessary yet), because otherwise // the Ice run time will install its own internal factory for Preserved upon receiving the // first instance. // try communicator.getValueFactoryManager().add( factory: { id in Preserved.ice_staticId() == id ? PreservedI() : nil }, id: Preserved.ice_staticId() ) do { // // Server knows the most-derived class PDerived. // let pd = PDerived() pd.pi = 3 pd.ps = "preserved" pd.pb = pd let r = try testPrx.exchangePBase(pd) if let p2 = r as? PDerived { try test(p2.pi == 3) try test(p2.ps == "preserved") try test(p2.pb === p2) breakCycles(r!) breakCycles(pd) } else { try test(false) } } catch is Ice.OperationNotExistException {} do { // // Server only knows the base (non-preserved) type, so the object is sliced. // let pu = PCUnknown() pu.pi = 3 pu.pu = "preserved" let r = try testPrx.exchangePBase(pu)! try test(!(r is PCUnknown)) try test(r.pi == 3) breakCycles(r) } catch is Ice.OperationNotExistException {} do { // // 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. // let pcd = PCDerived() pcd.pi = 3 pcd.pbs = [pcd] let r = try testPrx.exchangePBase(pcd)! if testPrx.ice_getEncodingVersion() == Ice.Encoding_1_0 { try test(!(r is PCDerived)) try test(r.pi == 3) } else { if let p2 = r as? PCDerived { try test(p2.pi == 3) try test(p2.pbs[0] === p2) } else { try test(false) } } breakCycles(r) breakCycles(pcd) } catch is Ice.OperationNotExistException {} do { // // 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. // let pcd = CompactPCDerived() pcd.pi = 3 pcd.pbs = [pcd] let r = try testPrx.exchangePBase(pcd)! if testPrx.ice_getEncodingVersion() == Ice.Encoding_1_0 { try test(!(r is CompactPCDerived)) try test(r.pi == 3) } else { if let p2 = r as? CompactPCDerived { try test(p2.pi == 3) try test(p2.pbs[0] === p2) } else { try test(false) } } breakCycles(r) breakCycles(pcd) } catch is Ice.OperationNotExistException {} do { // // Send an object that will have multiple preserved slices in the server. // The object will be sliced to Preserved for the 1.0 encoding. // let pcd = PCDerived3() pcd.pi = 3 // // Sending more than 254 objects exercises the encoding for object ids. // pcd.pbs = [PBase]() for i: Int32 in 0 ..< 300 { let p2 = PCDerived2() p2.pi = i p2.pbs = [nil] // Nil reference. This slice should not have an indirection table. p2.pcd2 = i pcd.pbs.append(p2) } pcd.pcd2 = pcd.pi pcd.pcd3 = pcd.pbs[10] let r = try testPrx.exchangePBase(pcd)! if testPrx.ice_getEncodingVersion() == Ice.Encoding_1_0 { try test(!(r is PCDerived3)) try test(r is Preserved) try test(r.pi == 3) } else { if let p3 = r as? PCDerived3 { try test(p3.pi == 3) for i in 0 ..< 300 { if let p2 = p3.pbs[i] as? PCDerived2 { try test(p2.pi == i) try test(p2.pbs.count == 1) try test(p2.pbs[0] == nil) try test(p2.pcd2 == i) } else { try test(false) } } try test(p3.pcd2 == p3.pi) try test(p3.pcd3 === p3.pbs[10]) } else { try test(false) } } breakCycles(r) breakCycles(pcd) } catch is Ice.OperationNotExistException {} do { // // 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. // let p = try testPrx.PBSUnknownAsPreserved()! try testPrx.checkPBSUnknown(p) if testPrx.ice_getEncodingVersion() != Ice.Encoding_1_0 { let slicedData = p.ice_getSlicedData()! try test(slicedData.slices.count == 1) try testPrx.ice_encodingVersion(Ice.Encoding_1_0).checkPBSUnknown(p) } else { try test(p.ice_getSlicedData() == nil) } breakCycles(p) } catch is Ice.OperationNotExistException {} output.writeLine("ok") output.write("preserved classes (AMI)... ") // // Register a factory in order to substitute our own subclass of Preserved. This provides // an easy way to determine how many unmarshaled instances currently exist. // // We have to install this now (even though it's not necessary yet), because otherwise // the Ice run time will install its own internal factory for Preserved upon receiving the // first instance. try Promise { seal in // // Server knows the most-derived class PDerived. // let pd = PDerived() pd.pi = 3 pd.ps = "preserved" pd.pb = pd firstly { testPrx.exchangePBaseAsync(pd) }.done { r in if let p2 = r as? PDerived { try test(p2.pi == 3) try test(p2.ps == "preserved") try test(p2.pb === p2) } else { try test(false) } breakCycles(r!) breakCycles(pd) seal.fulfill(()) }.catch { e in if e is Ice.OperationNotExistException { seal.fulfill(()) } else { seal.reject(e) } } }.wait() try Promise { seal in // // Server only knows the base (non-preserved) type, so the object is sliced. // let pu = PCUnknown() pu.pi = 3 pu.pu = "preserved" firstly { testPrx.exchangePBaseAsync(pu) }.done { ret in let r = ret! try test(!(r is PCUnknown)) try test(r.pi == 3) breakCycles(r) seal.fulfill(()) }.catch { e in if e is Ice.OperationNotExistException { seal.fulfill(()) } else { seal.reject(e) } } }.wait() try Promise { seal in // // 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. // let pcd = PCDerived() pcd.pi = 3 pcd.pbs = [pcd] firstly { testPrx.exchangePBaseAsync(pcd) }.done { ret in let r = ret! if testPrx.ice_getEncodingVersion() == Ice.Encoding_1_0 { try test(!(r is PCDerived)) try test(r.pi == 3) } else { if let p2 = r as? PCDerived { try test(p2.pi == 3) try test(p2.pbs[0] === p2) } else { try test(false) } } breakCycles(r) breakCycles(pcd) seal.fulfill(()) }.catch { e in if e is Ice.OperationNotExistException { seal.fulfill(()) } else { seal.reject(e) } } }.wait() try Promise { seal in // // 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. // let pcd = CompactPCDerived() pcd.pi = 3 pcd.pbs = [pcd] firstly { testPrx.exchangePBaseAsync(pcd) }.done { ret in let r = ret! if testPrx.ice_getEncodingVersion() == Ice.Encoding_1_0 { try test(!(r is CompactPCDerived)) try test(r.pi == 3) } else { if let p2 = r as? CompactPCDerived { try test(p2.pi == 3) try test(p2.pbs[0] === p2) } else { try test(false) } } breakCycles(r) breakCycles(pcd) seal.fulfill(()) }.catch { e in if e is Ice.OperationNotExistException { seal.fulfill(()) } else { seal.reject(e) } } }.wait() try Promise { seal in // // Send an object that will have multiple preserved slices in the server. // The object will be sliced to Preserved for the 1.0 encoding. // let pcd = PCDerived3() pcd.pi = 3 // // Sending more than 254 objects exercises the encoding for object ids. // pcd.pbs = [PBase]() for i: Int32 in 0 ..< 300 { let p2 = PCDerived2() p2.pi = i p2.pbs = [nil] // Nil reference. This slice should not have an indirection table. p2.pcd2 = i pcd.pbs.append(p2) } pcd.pcd2 = pcd.pi pcd.pcd3 = pcd.pbs[10] firstly { testPrx.exchangePBaseAsync(pcd) }.done { ret in let r = ret! if testPrx.ice_getEncodingVersion() == Ice.Encoding_1_0 { try test(!(r is PCDerived3)) try test(r is Preserved) try test(r.pi == 3) } else { if let p3 = r as? PCDerived3 { try test(p3.pi == 3) for i in 0 ..< 300 { if let p2 = p3.pbs[i] as? PCDerived2 { try test(p2.pi == i) try test(p2.pbs.count == 1) try test(p2.pbs[0] == nil) try test(p2.pcd2 == i) } else { try test(false) } } try test(p3.pcd2 == p3.pi) try test(p3.pcd3 === p3.pbs[10]) } else { try test(false) } } breakCycles(r) breakCycles(pcd) seal.fulfill(()) }.catch { e in if e is Ice.OperationNotExistException { seal.fulfill(()) } else { seal.reject(e) } } }.wait() try Promise { seal in // // 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. // firstly { testPrx.PBSUnknownAsPreservedAsync() }.done { p1 in let p = p1! try testPrx.checkPBSUnknown(p) if testPrx.ice_getEncodingVersion() != Ice.Encoding_1_0 { let slicedData = p.ice_getSlicedData()! try test(slicedData.slices.count == 1) try test(slicedData.slices[0].typeId == "::Test::PSUnknown") try testPrx.ice_encodingVersion(Ice.Encoding_1_0).checkPBSUnknown(p) } else { try test(p.ice_getSlicedData() == nil) } breakCycles(p) seal.fulfill(()) }.catch { e in if e is Ice.OperationNotExistException { seal.fulfill(()) } else { seal.reject(e) } } }.wait() output.writeLine("ok") return testPrx }