// // Copyright (c) ZeroC, Inc. All rights reserved. // import Ice import PromiseKit import TestCommon class TestI: TestIntf { var _helper: TestHelper var _values = [Value]() init(_ helper: TestHelper) { _helper = helper } deinit { for value in _values { breakCycles(value) } } 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 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 } } func SBaseAsObject(current _: Current) throws -> Value? { return SBase(sb: "SBase.sb") } func SBaseAsSBase(current _: Current) throws -> SBase? { return SBase(sb: "SBase.sb") } func SBSKnownDerivedAsSBase(current _: Current) throws -> SBase? { return SBSKnownDerived(sb: "SBSKnownDerived.sb", sbskd: "SBSKnownDerived.sbskd") } func SBSKnownDerivedAsSBSKnownDerived(current _: Current) throws -> SBSKnownDerived? { return SBSKnownDerived(sb: "SBSKnownDerived.sb", sbskd: "SBSKnownDerived.sbskd") } func SBSUnknownDerivedAsSBase(current _: Current) throws -> SBase? { return SBSUnknownDerived(sb: "SBSUnknownDerived.sb", sbsud: "SBSUnknownDerived.sbsud") } func SBSUnknownDerivedAsSBaseCompact(current _: Current) throws -> SBase? { return SBSUnknownDerived(sb: "SBSUnknownDerived.sb", sbsud: "SBSUnknownDerived.sbsud") } func SUnknownAsObject(current _: Current) throws -> Value? { let su = SUnknown() su.su = "SUnknown.su" su.cycle = su _values.append(su) return su } func checkSUnknown(o: Value?, current: Current) throws { let su = o as? SUnknown if current.encoding == Ice.Encoding_1_0 { try _helper.test(su == nil) } else { try _helper.test(su!.su == "SUnknown.su") su!.cycle = nil } } func oneElementCycle(current _: Current) throws -> B? { let b = B() b.sb = "B1.sb" b.pb = b _values.append(b) return b } func twoElementCycle(current _: Current) throws -> B? { let b1 = B() b1.sb = "B1.sb" let b2 = B() b2.sb = "B2.sb" b2.pb = b1 b1.pb = b2 _values.append(b1) return b1 } func D1AsB(current _: Current) throws -> B? { let d1 = D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" let d2 = D2() d2.pb = d1 d2.sb = "D2.sb" d2.sd2 = "D2.sd2" d2.pd2 = d1 d1.pb = d2 d1.pd1 = d2 _values.append(d1) return d1 } func D1AsD1(current _: Current) throws -> D1? { let d1 = D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" let d2 = D2() d2.pb = d1 d2.sb = "D2.sb" d2.sd2 = "D2.sd2" d2.pd2 = d1 d1.pb = d2 d1.pd1 = d2 _values.append(d1) return d1 } func D2AsB(current _: Current) throws -> B? { let d2 = D2() d2.sb = "D2.sb" d2.sd2 = "D2.sd2" let d1 = D1() d1.pb = d2 d1.sb = "D1.sb" d1.sd1 = "D1.sd1" d1.pd1 = d2 d2.pb = d1 d2.pd2 = d1 _values.append(d1) return d2 } func paramTest1(current _: Current) throws -> (p1: B?, p2: B?) { let d1 = D1() d1.sb = "D1.sb" d1.sd1 = "D1.sd1" let d2 = D2() d2.pb = d1 d2.sb = "D2.sb" d2.sd2 = "D2.sd2" d2.pd2 = d1 d1.pb = d2 d1.pd1 = d2 _values.append(d1) return (d1, d2) } func paramTest2(current: Current) throws -> (p2: B?, p1: B?) { let ret = try paramTest1(current: current) return (ret.p2, ret.p1) } func paramTest3(current _: Current) throws -> (returnValue: B?, p1: B?, p2: B?) { let d2 = D2() d2.sb = "D2.sb (p1 1)" d2.pb = nil d2.sd2 = "D2.sd2 (p1 1)" let d1 = D1() d1.sb = "D1.sb (p1 2)" d1.pb = nil d1.sd1 = "D1.sd2 (p1 2)" d1.pd1 = nil d2.pd2 = d1 let d4 = D2() d4.sb = "D2.sb (p2 1)" d4.pb = nil d4.sd2 = "D2.sd2 (p2 1)" let d3 = D1() d3.sb = "D1.sb (p2 2)" d3.pb = nil d3.sd1 = "D1.sd2 (p2 2)" d3.pd1 = nil d4.pd2 = d3 _values.append(d1) _values.append(d2) _values.append(d3) _values.append(d4) return (d3, d2, d4) } func paramTest4(current _: Current) throws -> (returnValue: B?, p: B?) { let d4 = D4() d4.sb = "D4.sb (1)" d4.pb = nil d4.p1 = B() d4.p1!.sb = "B.sb (1)" d4.p2 = B() d4.p2!.sb = "B.sb (2)" _values.append(d4) return (d4.p2, d4) } func returnTest1(current: Current) throws -> (returnValue: B?, p1: B?, p2: B?) { let ret = try paramTest1(current: current) return (ret.p1, ret.p1, ret.p2) } func returnTest2(current: Current) throws -> (returnValue: B?, p2: B?, p1: B?) { let ret = try paramTest1(current: current) return (ret.p1, ret.p1, ret.p2) } func returnTest3(p1: B?, p2: B?, current _: Current) -> B? { _values.append(p1!) _values.append(p2!) return p1 } func sequenceTest(p1: SS1?, p2: SS2?, current _: Current) throws -> SS3 { let ss = SS3() ss.c1 = p1 ss.c2 = p2 _values.append(p1!) _values.append(p2!) return ss } func dictionaryTest(bin: BDict, current _: Current) throws -> (returnValue: BDict, bout: BDict) { var bout = [Int32: B?]() for i: Int32 in 0 ..< 10 { let b = bin[i]!! let d2 = D2() d2.sb = b.sb d2.pb = b.pb d2.sd2 = "D2" d2.pd2 = d2 _values.append(d2) bout[i * 10] = d2 } var r = [Int32: B]() for i: Int32 in 0 ..< 10 { let s = "D1.\(i * 20)" let d1 = D1() d1.sb = s d1.pb = i == 0 ? nil : r[(i - 1) * 20] d1.sd1 = s d1.pd1 = d1 _values.append(d1) r[i * 20] = d1 } return (r, bout) } func exchangePBase(pb: PBase?, current _: Current) throws -> PBase? { _values.append(pb!) return pb } func PBSUnknownAsPreserved(current: Current) throws -> Preserved? { let r = PSUnknown() r.pi = 5 r.ps = "preserved" r.psu = "unknown" r.graph = nil if current.encoding != Ice.Encoding_1_0 { // // 1.0 encoding doesn't support unmarshaling unknown classes even if referenced // from unread slice. // r.cl = MyClass(i: 15) } return r } func checkPBSUnknown(p: Preserved?, current: Current) throws { if current.encoding == Ice.Encoding_1_0 { try _helper.test(!(p is PSUnknown)) try _helper.test(p!.pi == 5) try _helper.test(p!.ps == "preserved") } else { let pu = p as! PSUnknown try _helper.test(pu.pi == 5) try _helper.test(pu.ps == "preserved") try _helper.test(pu.psu == "unknown") try _helper.test(pu.graph == nil) try _helper.test(pu.cl != nil && pu.cl!.i == 15) } } func PBSUnknownAsPreservedWithGraphAsync(current: Current) -> Promise { // This code requires a regular, non-colloc dispatch if let dq = try? current.adapter!.getDispatchQueue() { dispatchPrecondition(condition: .onQueue(dq)) } return Promise { seal in // .barrier to ensure we execute this code after Ice has called "done" on the promise // Otherwise the cycle breaking can occur before the result is marshaled by the // closure given to done. try current.adapter!.getDispatchQueue().async(flags: .barrier) { let r = PSUnknown() r.pi = 5 r.ps = "preserved" r.psu = "unknown" r.graph = PNode() r.graph!.next = PNode() r.graph!.next!.next = PNode() r.graph!.next!.next!.next = r.graph seal.fulfill(r) // Ice marshals r now r.graph!.next!.next!.next = nil // break the cycle } } } func checkPBSUnknownWithGraph(p: Preserved?, current: Current) throws { if current.encoding == Ice.Encoding_1_0 { try _helper.test(!(p is PSUnknown)) try _helper.test(p!.pi == 5) try _helper.test(p!.ps == "preserved") } else { let pu = p as! PSUnknown try _helper.test(pu.pi == 5) try _helper.test(pu.ps == "preserved") try _helper.test(pu.psu == "unknown") try _helper.test(pu.graph !== pu.graph!.next) try _helper.test(pu.graph!.next !== pu.graph!.next!.next) if pu.graph!.next!.next!.next == nil { print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") try _helper.test(false) } else { try _helper.test(pu.graph!.next!.next!.next === pu.graph) } pu.graph!.next!.next!.next = nil // break the cycle } } func PBSUnknown2AsPreservedWithGraphAsync(current: Current) -> Promise { return Promise { seal in try current.adapter!.getDispatchQueue().async(flags: .barrier) { let r = PSUnknown2() r.pi = 5 r.ps = "preserved" r.pb = r seal.fulfill(r) // Ice marshals r immediately r.pb = nil // break the cycle } } } func checkPBSUnknown2WithGraph(p: Preserved?, current: Current) throws { if current.encoding == Ice.Encoding_1_0 { try _helper.test(!(p is PSUnknown2)) try _helper.test(p!.pi == 5) try _helper.test(p!.ps == "preserved") } else { let pu = p as! PSUnknown2 try _helper.test(pu.pi == 5) try _helper.test(pu.ps == "preserved") try _helper.test(pu.pb === pu) pu.pb = nil // break the cycle } } func exchangePNode(pn: PNode?, current _: Current) throws -> PNode? { return pn } func throwBaseAsBase(current _: Current) throws { let be = BaseException() be.sbe = "sbe" be.pb = B() be.pb!.sb = "sb" be.pb!.pb = be.pb _values.append(be.pb!) throw be } func throwDerivedAsBase(current _: Current) throws { let de = DerivedException() de.sbe = "sbe" de.pb = B() de.pb!.sb = "sb1" de.pb!.pb = de.pb de.sde = "sde1" de.pd1 = D1() de.pd1!.sb = "sb2" de.pd1!.pb = de.pd1 de.pd1!.sd1 = "sd2" de.pd1!.pd1 = de.pd1 _values.append(de.pb!) _values.append(de.pd1!) throw de } func throwDerivedAsDerived(current _: Current) throws { let de = DerivedException() de.sbe = "sbe" de.pb = B() de.pb!.sb = "sb1" de.pb!.pb = de.pb de.sde = "sde1" de.pd1 = D1() de.pd1!.sb = "sb2" de.pd1!.pb = de.pd1 de.pd1!.sd1 = "sd2" de.pd1!.pd1 = de.pd1 _values.append(de.pb!) _values.append(de.pd1!) throw de } func throwUnknownDerivedAsBase(current _: Current) throws { let d2 = D2() d2.sb = "sb d2" d2.pb = d2 d2.sd2 = "sd2 d2" d2.pd2 = d2 _values.append(d2) let ude = UnknownDerivedException() ude.sbe = "sbe" ude.pb = d2 ude.sude = "sude" ude.pd2 = d2 throw ude } func throwPreservedExceptionAsync(current: Current) -> Promise { return Promise { seal in try current.adapter!.getDispatchQueue().async(flags: .barrier) { let ue = PSUnknownException() ue.p = PSUnknown2() ue.p!.pi = 5 ue.p!.ps = "preserved" ue.p!.pb = ue.p seal.reject(ue) // Ice marshals the error immediately ue.p!.pb = nil // break the cycle } } } func useForward(current _: Current) throws -> Forward? { let f = Forward() f.h = Hidden() f.h!.f = f _values.append(f) return f } func shutdown(current: Current) throws { current.adapter!.getCommunicator().shutdown() } }