| /* |
| * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license |
| * that can be found in the LICENSE file. |
| */ |
| |
| import Foundation |
| import Kt |
| |
| // -------- Tests -------- |
| |
| func testVals() throws { |
| print("Values from Swift") |
| let dbl = ValuesKt.dbl |
| let flt = ValuesKt.flt |
| let int = ValuesKt.integer |
| let long = ValuesKt.longInt |
| |
| print(dbl) |
| print(flt) |
| print(int) |
| print(long) |
| |
| try assertEquals(actual: dbl, expected: 3.14 as Double, "Double value isn't equal.") |
| try assertEquals(actual: flt, expected: 2.73 as Float, "Float value isn't equal.") |
| try assertEquals(actual: int, expected: 42) |
| try assertEquals(actual: long, expected: 1984) |
| } |
| |
| func testVars() throws { |
| print("Variables from Swift") |
| var intVar = ValuesKt.intVar |
| var strVar = ValuesKt.str |
| var strAsId = ValuesKt.strAsAny |
| |
| print(intVar) |
| print(strVar) |
| print(strAsId) |
| |
| try assertEquals(actual: intVar, expected: 451) |
| try assertEquals(actual: strVar, expected: "Kotlin String") |
| try assertEquals(actual: strAsId as! String, expected: "Kotlin String as Any") |
| |
| strAsId = "Swift str" |
| ValuesKt.strAsAny = strAsId |
| print(ValuesKt.strAsAny) |
| try assertEquals(actual: ValuesKt.strAsAny as! String, expected: strAsId as! String) |
| |
| // property with custom getter/setter backed by the Kotlin's var |
| var intProp : Int32 { |
| get { |
| return ValuesKt.intVar * 2 |
| } |
| set(value) { |
| ValuesKt.intVar = 123 + value |
| } |
| } |
| intProp += 10 |
| print(intProp) |
| print(ValuesKt.intVar) |
| try assertEquals(actual: ValuesKt.intVar * 2, expected: intProp, "Property backed by var") |
| } |
| |
| func testDoubles() throws { |
| print("Doubles in Swift") |
| let minDouble = ValuesKt.minDoubleVal as! Double |
| let maxDouble = ValuesKt.maxDoubleVal as! NSNumber |
| |
| print(minDouble) |
| print(maxDouble) |
| print(ValuesKt.nanDoubleVal) |
| print(ValuesKt.nanFloatVal) |
| print(ValuesKt.infDoubleVal) |
| print(ValuesKt.infFloatVal) |
| |
| try assertEquals(actual: minDouble, expected: Double.leastNonzeroMagnitude, "Min double") |
| try assertEquals(actual: maxDouble, expected: Double.greatestFiniteMagnitude as NSNumber, "Max double") |
| try assertTrue(ValuesKt.nanDoubleVal.isNaN, "NaN double") |
| try assertTrue(ValuesKt.nanFloatVal.isNaN, "NaN float") |
| try assertEquals(actual: ValuesKt.infDoubleVal, expected: Double.infinity, "Inf double") |
| try assertEquals(actual: ValuesKt.infFloatVal, expected: -Float.infinity, "-Inf float") |
| } |
| |
| func testNumbers() throws { |
| try assertEquals(actual: KotlinBoolean(value: true).boolValue, expected: true) |
| try assertEquals(actual: KotlinBoolean(value: false).intValue, expected: 0) |
| try assertEquals(actual: KotlinBoolean(value: true), expected: true) |
| try assertFalse(KotlinBoolean(value: false) as! Bool) |
| |
| try assertEquals(actual: KotlinByte(value: -1).int8Value, expected: -1) |
| try assertEquals(actual: KotlinByte(value: -1).int32Value, expected: -1) |
| try assertEquals(actual: KotlinByte(value: -1).doubleValue, expected: -1.0) |
| try assertEquals(actual: KotlinByte(value: -1), expected: NSNumber(value: Int64(-1))) |
| try assertFalse(KotlinByte(value: -1) == NSNumber(value: -1.5)) |
| try assertEquals(actual: KotlinByte(value: -1), expected: -1) |
| try assertTrue(KotlinByte(value: -1) == -1) |
| try assertFalse(KotlinByte(value: -1) == 1) |
| try assertEquals(actual: KotlinByte(value: -1) as! Int32, expected: -1) |
| |
| try assertEquals(actual: KotlinShort(value: 111).int16Value, expected: 111) |
| try assertEquals(actual: KotlinShort(value: -15) as! Int16, expected: -15) |
| try assertEquals(actual: KotlinShort(value: 47), expected: 47) |
| |
| try assertEquals(actual: KotlinInt(value: 99).int32Value, expected: 99) |
| try assertEquals(actual: KotlinInt(value: -1) as! Int32, expected: -1) |
| try assertEquals(actual: KotlinInt(value: 72), expected: 72) |
| |
| try assertEquals(actual: KotlinLong(value: 65).int64Value, expected: 65) |
| try assertEquals(actual: KotlinLong(value: 10000000000) as! Int64, expected: 10000000000) |
| try assertEquals(actual: KotlinLong(value: 8), expected: 8) |
| |
| try assertEquals(actual: KotlinUByte(value: 17).uint8Value, expected: 17) |
| try assertEquals(actual: KotlinUByte(value: 42) as! UInt8, expected: 42) |
| try assertEquals(actual: 88, expected: KotlinUByte(value: 88)) |
| |
| try assertEquals(actual: KotlinUShort(value: 40000).uint16Value, expected: 40000) |
| try assertEquals(actual: KotlinUShort(value: 1) as! UInt16, expected: UInt16(1)) |
| try assertEquals(actual: KotlinUShort(value: 65000), expected: 65000) |
| |
| try assertEquals(actual: KotlinUInt(value: 3).uint32Value, expected: 3) |
| try assertEquals(actual: KotlinUInt(value: UInt32.max) as! UInt32, expected: UInt32.max) |
| try assertEquals(actual: KotlinUInt(value: 2), expected: 2) |
| |
| try assertEquals(actual: KotlinULong(value: 55).uint64Value, expected: 55) |
| try assertEquals(actual: KotlinULong(value: 0) as! UInt64, expected: 0) |
| try assertEquals(actual: KotlinULong(value: 7), expected: 7) |
| |
| try assertEquals(actual: KotlinFloat(value: 1.0).floatValue, expected: 1.0) |
| try assertEquals(actual: KotlinFloat(value: 22.0) as! Float, expected: 22) |
| try assertEquals(actual: KotlinFloat(value: 41.0), expected: 41) |
| try assertEquals(actual: KotlinFloat(value: -5.5), expected: -5.5) |
| |
| try assertEquals(actual: KotlinDouble(value: 0.5).doubleValue, expected: 0.5) |
| try assertEquals(actual: KotlinDouble(value: 45.0) as! Double, expected: 45) |
| try assertEquals(actual: KotlinDouble(value: 89.0), expected: 89) |
| try assertEquals(actual: KotlinDouble(value: -3.7), expected: -3.7) |
| |
| ValuesKt.ensureEqualBooleans(actual: KotlinBoolean(value: true), expected: true) |
| ValuesKt.ensureEqualBooleans(actual: false, expected: false) |
| |
| ValuesKt.ensureEqualBytes(actual: KotlinByte(value: 42), expected: 42) |
| ValuesKt.ensureEqualBytes(actual: -11, expected: -11) |
| |
| ValuesKt.ensureEqualShorts(actual: KotlinShort(value: 256), expected: 256) |
| ValuesKt.ensureEqualShorts(actual: -1, expected: -1) |
| |
| ValuesKt.ensureEqualInts(actual: KotlinInt(value: 100000), expected: 100000) |
| ValuesKt.ensureEqualInts(actual: -7, expected: -7) |
| |
| ValuesKt.ensureEqualLongs(actual: KotlinLong(value: Int64.max), expected: Int64.max) |
| ValuesKt.ensureEqualLongs(actual: 17, expected: 17) |
| |
| ValuesKt.ensureEqualUBytes(actual: KotlinUByte(value: 6), expected: 6) |
| ValuesKt.ensureEqualUBytes(actual: 255, expected: 255) |
| |
| ValuesKt.ensureEqualUShorts(actual: KotlinUShort(value: 300), expected: 300) |
| ValuesKt.ensureEqualUShorts(actual: 65535, expected: UInt16.max) |
| |
| ValuesKt.ensureEqualUInts(actual: KotlinUInt(value: 70000), expected: 70000) |
| ValuesKt.ensureEqualUInts(actual: 48, expected: 48) |
| |
| ValuesKt.ensureEqualULongs(actual: KotlinULong(value: UInt64.max), expected: UInt64.max) |
| ValuesKt.ensureEqualULongs(actual: 39, expected: 39) |
| |
| ValuesKt.ensureEqualFloats(actual: KotlinFloat(value: 36.6), expected: 36.6) |
| ValuesKt.ensureEqualFloats(actual: 49.5, expected: 49.5) |
| ValuesKt.ensureEqualFloats(actual: 18, expected: 18.0) |
| |
| ValuesKt.ensureEqualDoubles(actual: KotlinDouble(value: 12.34), expected: 12.34) |
| ValuesKt.ensureEqualDoubles(actual: 56.78, expected: 56.78) |
| ValuesKt.ensureEqualDoubles(actual: 3, expected: 3) |
| |
| func checkBox<T: Equatable, B : NSObject>(_ value: T, _ boxFunction: (T) -> B?) throws { |
| let box = boxFunction(value)! |
| try assertEquals(actual: box as! T, expected: value) |
| print(type(of: box)) |
| print(B.self) |
| try assertTrue(box.isKind(of: B.self)) |
| } |
| |
| try checkBox(true, ValuesKt.box) |
| try checkBox(Int8(-1), ValuesKt.box) |
| try checkBox(Int16(-2), ValuesKt.box) |
| try checkBox(Int32(-3), ValuesKt.box) |
| try checkBox(Int64(-4), ValuesKt.box) |
| try checkBox(UInt8(5), ValuesKt.box) |
| try checkBox(UInt16(6), ValuesKt.box) |
| try checkBox(UInt32(7), ValuesKt.box) |
| try checkBox(UInt64(8), ValuesKt.box) |
| try checkBox(Float(8.7), ValuesKt.box) |
| try checkBox(Double(9.4), ValuesKt.box) |
| } |
| |
| func testLists() throws { |
| let numbersList = ValuesKt.numbersList |
| let gold = [1, 2, 13] |
| for i in 0..<gold.count { |
| try assertEquals(actual: gold[i], expected: Int(numbersList[i] as! NSNumber), "Numbers list") |
| } |
| |
| let anyList = ValuesKt.anyList |
| for i in anyList { |
| print(i) |
| } |
| // try assertEquals(actual: gold, expected: anyList, "Numbers list") |
| } |
| |
| func testLazyVal() throws { |
| let lazyVal = ValuesKt.lazyVal |
| print(lazyVal) |
| try assertEquals(actual: lazyVal, expected: "Lazily initialized string", "lazy value") |
| } |
| |
| let goldenArray = ["Delegated", "global", "array", "property"] |
| |
| func testDelegatedProp() throws { |
| let delegatedGlobalArray = ValuesKt.delegatedGlobalArray |
| guard Int(delegatedGlobalArray.size) == goldenArray.count else { |
| throw TestError.assertFailed("Size differs") |
| } |
| for i in 0..<delegatedGlobalArray.size { |
| print(delegatedGlobalArray.get(index: i)!) |
| } |
| } |
| |
| func testGetterDelegate() throws { |
| let delegatedList = ValuesKt.delegatedList |
| guard delegatedList.count == goldenArray.count else { |
| throw TestError.assertFailed("Size differs") |
| } |
| for val in delegatedList { |
| print(val) |
| } |
| } |
| |
| func testNulls() throws { |
| let nilVal : Any? = ValuesKt.nullVal |
| try assertTrue(nilVal == nil, "Null value") |
| |
| ValuesKt.nullVar = nil |
| var nilVar : Any? = ValuesKt.nullVar |
| try assertTrue(nilVar == nil, "Null variable") |
| } |
| |
| func testAnyVar() throws { |
| let anyVar : Any = ValuesKt.anyValue |
| print(anyVar) |
| if let str = anyVar as? String { |
| print(str) |
| try assertEquals(actual: str, expected: "Str") |
| } else { |
| throw TestError.assertFailed("Incorrect type passed from Any") |
| } |
| } |
| |
| func testFunctions() throws { |
| let _: Any? = ValuesKt.emptyFun() |
| |
| let str = ValuesKt.strFun() |
| try assertEquals(actual: str, expected: "fooStr") |
| |
| try assertEquals(actual: ValuesKt.argsFun(i: 10, l: 20, d: 3.5, s: "res") as! String, |
| expected: "res10203.5") |
| |
| try assertEquals(actual: ValuesKt.multiply(int: 3, long: 2), expected: 6) |
| } |
| |
| class SwiftThrowing : SwiftOverridableMethodsWithThrows { |
| class E : Error {} |
| |
| func unit() throws -> Void { throw E() } |
| func nothing() throws -> Void { throw E() } |
| func any() throws -> Any { throw E() } |
| func block() throws -> () -> KotlinInt { throw E() } |
| } |
| |
| class TestThrowingConstructorRelease : Throwing { |
| static var deinitialized = false |
| deinit { |
| TestThrowingConstructorRelease.deinitialized = true |
| } |
| } |
| |
| class SwiftNotThrowing : SwiftOverridableMethodsWithThrows { |
| func unit() throws -> Void { } |
| func nothing() throws -> Void { throw SwiftThrowing.E() } |
| func any() throws -> Any { return 42 as Int32 } |
| func block() throws -> () -> KotlinInt { return { 17 } } |
| } |
| |
| class SwiftUnitCaller : MethodsWithThrowsUnitCaller { |
| func call(methods: MethodsWithThrows) throws -> Void { |
| try methods.unit() |
| } |
| } |
| |
| class SwiftThrowingWithBridge : ThrowsWithBridge { |
| override func plusOne(x: Int32) throws -> KotlinInt { |
| throw SwiftThrowing.E() |
| } |
| } |
| |
| class SwiftNotThrowingWithBridge : ThrowsWithBridge { |
| override func plusOne(x: Int32) throws -> KotlinInt { |
| return KotlinInt(value: x + 1) |
| } |
| } |
| |
| private func testThrowing(file: String = #file, line: Int = #line, _ block: () throws -> Void) throws { |
| try assertFailsWithKotlin(MyException.self, file: file, line: line, block: block) |
| } |
| |
| func testExceptions() throws { |
| try testThrowing { try ValuesKt.throwException(error: false) } |
| do { |
| try ValuesKt.throwException(error: true) |
| } catch let error as NSError { |
| try assertTrue(error.kotlinException is MyError) |
| } |
| |
| #if !NOOP_GC |
| try assertFalse(TestThrowingConstructorRelease.deinitialized) |
| try testThrowing { try TestThrowingConstructorRelease(doThrow: true) } |
| ValuesKt.gc() |
| try assertTrue(TestThrowingConstructorRelease.deinitialized) |
| #endif |
| |
| try testThrowing { try Throwing(doThrow: true) } |
| |
| let throwing = try Throwing(doThrow: false) |
| try testThrowing { try throwing.unit() } |
| try testThrowing { try throwing.nothing() } |
| try testThrowing { try throwing.nothingN() } |
| try testThrowing { try throwing.any() } |
| try testThrowing { try throwing.anyN() } |
| try testThrowing { try throwing.block()() } |
| try testThrowing { try throwing.blockN() } |
| try testThrowing { try throwing.pointer() } |
| try testThrowing { try throwing.pointerN() } |
| try testThrowing { try throwing.int() } |
| try testThrowing { try throwing.longN() } |
| try testThrowing { try throwing.double() } |
| |
| let notThrowing = try NotThrowing() |
| |
| try notThrowing.unit() |
| try assertEquals(actual: notThrowing.nothingN(), expected: nil) |
| try assertTrue(notThrowing.any() is KotlinBase) |
| try assertTrue(notThrowing.anyN() is KotlinBase) |
| try assertEquals(actual: notThrowing.block()(), expected: 42) |
| try assertTrue(notThrowing.blockN() == nil) |
| try assertEquals(actual: Int(bitPattern: notThrowing.pointer()), expected: 1) |
| try assertEquals(actual: notThrowing.pointerN(), expected: nil) |
| try assertEquals(actual: notThrowing.int(), expected: 42) |
| try assertEquals(actual: notThrowing.longN(), expected: nil) |
| try assertEquals(actual: notThrowing.double(), expected: 3.14) |
| |
| try ValuesKt.testSwiftThrowing(methods: SwiftThrowing()) |
| try ValuesKt.testSwiftNotThrowing(methods: SwiftNotThrowing()) |
| |
| do { |
| try ValuesKt.callUnit(methods: SwiftThrowing()) |
| } catch let e as SwiftThrowing.E { |
| // Ok. |
| } |
| |
| try ValuesKt.callUnitCaller(caller: SwiftUnitCaller(), methods: throwing) |
| |
| try ValuesKt.testSwiftThrowing(test: SwiftThrowingWithBridge(), flag: false) |
| try ValuesKt.testSwiftThrowing(test: SwiftThrowingWithBridge(), flag: true) |
| try ValuesKt.testSwiftNotThrowing(test: SwiftNotThrowingWithBridge()) |
| } |
| |
| func testFuncType() throws { |
| let s = "str" |
| let fFunc: () -> String = { return s } |
| try assertEquals(actual: ValuesKt.funArgument(foo: fFunc), expected: s, "Using function type arguments failed") |
| } |
| |
| func testGenericsFoo() throws { |
| let fun = { (i: Int) -> String in return "S \(i)" } |
| // wrap lambda to workaround issue with type conversion inability: |
| // (Int) -> String can't be cast to (Any?) -> Any? |
| let wrapper = { (t: Any?) -> Any? in return fun(t as! Int) } |
| let res = ValuesKt.genericFoo(t: 42, foo: wrapper) |
| try assertEquals(actual: res as! String, expected: "S 42") |
| } |
| |
| func testVararg() throws { |
| #if NO_GENERICS |
| let ktArray = KotlinArray(size: 3, init: { (_) -> NSNumber in return 42 }) |
| #else |
| let ktArray = KotlinArray<AnyObject>(size: 3, init: { (_) -> NSNumber in return 42 }) |
| #endif |
| let arr: [Int] = ValuesKt.varargToList(args: ktArray) as! [Int] |
| try assertEquals(actual: arr, expected: [42, 42, 42]) |
| } |
| |
| func testStrExtFun() throws { |
| try assertEquals(actual: ValuesKt.subExt("String", i: 2), expected: "r") |
| try assertEquals(actual: ValuesKt.subExt("A", i: 2), expected: "nothing") |
| } |
| |
| func testAnyToString() throws { |
| try assertEquals(actual: ValuesKt.toString(nil), expected: "null") |
| try assertEquals(actual: ValuesKt.toString(42), expected: "42") |
| } |
| |
| func testAnyPrint() throws { |
| print("BEGIN") |
| ValuesKt.print(nil) |
| ValuesKt.print("Print") |
| ValuesKt.print(123456789) |
| ValuesKt.print(3.14) |
| ValuesKt.print([3, 2, 1]) |
| print("END") |
| } |
| |
| func testCharExtensions() throws { |
| try assertTrue(ValuesKt.isA(ValuesKt.boxChar(65))) |
| try assertFalse(ValuesKt.isA(ValuesKt.boxChar(66))) |
| } |
| |
| func testLambda() throws { |
| try assertEquals(actual: ValuesKt.sumLambda(3, 4), expected: 7) |
| |
| var blockRuns = 0 |
| |
| try assertTrue(ValuesKt.runUnitBlock { blockRuns += 1 }) |
| try assertEquals(actual: blockRuns, expected: 1) |
| |
| let unitBlock: () -> Void = ValuesKt.asUnitBlock { |
| blockRuns += 1 |
| return 42 |
| } |
| try assertTrue(unitBlock() == Void()) |
| try assertEquals(actual: blockRuns, expected: 2) |
| |
| let nothingBlock: () -> Void = { blockRuns += 1 } |
| ValuesKt.runNothingBlock(block: nothingBlock) |
| try assertEquals(actual: blockRuns, expected: 3) |
| |
| try assertTrue(ValuesKt.getNullBlock() == nil) |
| try assertTrue(ValuesKt.isBlockNull(block: nil)) |
| |
| // Test dynamic conversion: |
| let intBlocks = IntBlocksImpl() |
| try assertEquals(actual: intBlocks.getPlusOneBlock()(1), expected: 2) |
| try assertEquals(actual: intBlocks.callBlock(argument: 2) { KotlinInt(value: $0.int32Value + 2) }, expected: 4) |
| |
| // Test round trip with dynamic conversion: |
| let coercedUnitBlock: () -> KotlinUnit = UnitBlockCoercionImpl().coerce { blockRuns += 1 } |
| try assertTrue(coercedUnitBlock() === KotlinUnit()) |
| try assertEquals(actual: blockRuns, expected: 4) |
| |
| let uncoercedUnitBlock: () -> Void = UnitBlockCoercionImpl().uncoerce { |
| blockRuns += 1 |
| return KotlinUnit() |
| } |
| try assertTrue(uncoercedUnitBlock() == Void()) |
| try assertEquals(actual: blockRuns, expected: 5) |
| |
| let blockMustBeFunction0: @convention(block) () -> AnyObject? = { return nil } |
| try assertTrue(ValuesKt.isFunction(obj: blockMustBeFunction0)) |
| try assertTrue(ValuesKt.isFunction0(obj: blockMustBeFunction0)) |
| try assertFalse(ValuesKt.isFunction(obj: NSObject())) |
| try assertFalse(ValuesKt.isFunction0(obj: NSObject())) |
| |
| // Test no function class for dynamic conversion: |
| let blockAsMissingFunction: @convention(block) (AnyObject?, AnyObject?, AnyObject?, AnyObject?, AnyObject?) -> AnyObject? |
| = { return $0 ?? $1 ?? $2 ?? $3 ?? $4 } |
| |
| try assertTrue(ValuesKt.isFunction(obj: blockAsMissingFunction)) |
| try assertFalse(ValuesKt.isFunction0(obj: blockAsMissingFunction)) |
| } |
| |
| // -------- Tests for classes and interfaces ------- |
| class ValIEmptyExt : I { |
| func iFun() -> String { |
| return "ValIEmptyExt::iFun" |
| } |
| } |
| |
| class ValIExt : I { |
| func iFun() -> String { |
| return "ValIExt::iFun" |
| } |
| } |
| |
| func testInterfaceExtension() throws { |
| try assertEquals(actual: ValIEmptyExt().iFun(), expected: "ValIEmptyExt::iFun") |
| try assertEquals(actual: ValIExt().iFun(), expected: "ValIExt::iFun") |
| } |
| |
| func testClassInstances() throws { |
| try assertEquals(actual: OpenClassI().iFun(), expected: "OpenClassI::iFun") |
| try assertEquals(actual: DefaultInterfaceExt().iFun(), expected: "I::iFun") |
| try assertEquals(actual: FinalClassExtOpen().iFun(), expected: "FinalClassExtOpen::iFun") |
| try assertEquals(actual: MultiExtClass().iFun(), expected: "PI::iFun") |
| try assertEquals(actual: MultiExtClass().piFun() as! Int, expected: 42) |
| try assertEquals(actual: ConstrClass(i: 1, s: "str", a: "Any").iFun(), expected: "OpenClassI::iFun") |
| try assertEquals(actual: ExtConstrClass(i: 123).iFun(), expected: "ExtConstrClass::iFun::123-String-AnyS") |
| } |
| |
| func testEnum() throws { |
| try assertEquals(actual: ValuesKt.passEnum(), expected: Enumeration.answer) |
| try assertEquals(actual: ValuesKt.passEnum().enumValue, expected: 42) |
| try assertEquals(actual: ValuesKt.passEnum().name, expected: "ANSWER") |
| ValuesKt.receiveEnum(e: 1) |
| } |
| |
| func testDataClass() throws { |
| let f = "1" |
| let s = "2" |
| let t = "3" |
| |
| #if NO_GENERICS |
| let tripleVal = TripleVals(first: f as NSString, second: s as NSString, third: t as NSString) |
| #else |
| let tripleVal = TripleVals<NSString>(first: f as NSString, second: s as NSString, third: t as NSString) |
| #endif |
| try assertEquals(actual: tripleVal.first as! String, expected: f, "Data class' value") |
| print(tripleVal) |
| try assertEquals(actual: String(describing: tripleVal), expected: "TripleVals(first=\(f), second=\(s), third=\(t))") |
| |
| #if NO_GENERICS |
| let tripleVar = TripleVars(first: f as NSString, second: s as NSString, third: t as NSString) |
| #else |
| let tripleVar = TripleVars<NSString>(first: f as NSString, second: s as NSString, third: t as NSString) |
| #endif |
| try assertEquals(actual: tripleVar.first as! String, expected: f, "Data class' value") |
| print(tripleVar) |
| try assertEquals(actual: String(describing: tripleVar), expected: "[\(f), \(s), \(t)]") |
| |
| tripleVar.first = t as NSString |
| tripleVar.second = f as NSString |
| tripleVar.third = s as NSString |
| try assertEquals(actual: String(describing: tripleVar), expected: "[\(t), \(f), \(s)]") |
| } |
| |
| func testCompanionObj() throws { |
| try assertEquals(actual: WithCompanionAndObject.Companion().str, expected: "String") |
| try assertEquals(actual: ValuesKt.getCompanionObject().str, expected: "String") |
| |
| let namedFromCompanion = ValuesKt.getCompanionObject().named |
| let named = ValuesKt.getNamedObject() |
| try assertTrue(named === namedFromCompanion, "Should be the same Named object") |
| |
| try assertEquals(actual: ValuesKt.getNamedObjectInterface().iFun(), expected: named.iFun(), "Named object's method") |
| } |
| |
| func testInlineClasses() throws { |
| let ic1: Int32 = 42 |
| let ic1N = ValuesKt.box(ic1: 17) |
| let ic2 = "foo" |
| let ic2N = "bar" |
| #if NO_GENERICS |
| let ic3 = TripleVals(first: 1, second: 2, third: 3) |
| #else |
| let ic3 = TripleVals<NSNumber>(first: 1, second: 2, third: 3) |
| #endif |
| let ic3N = ValuesKt.box(ic3: nil) |
| |
| try assertEquals( |
| actual: ValuesKt.concatenateInlineClassValues(ic1: ic1, ic1N: ic1N, ic2: ic2, ic2N: ic2N, ic3: ic3, ic3N: ic3N), |
| expected: "42 17 foo bar TripleVals(first=1, second=2, third=3) null" |
| ) |
| |
| try assertEquals( |
| actual: ValuesKt.concatenateInlineClassValues(ic1: ic1, ic1N: nil, ic2: ic2, ic2N: nil, ic3: nil, ic3N: nil), |
| expected: "42 null foo null null null" |
| ) |
| |
| try assertEquals(actual: ValuesKt.getValue1(ic1), expected: 42) |
| try assertEquals(actual: ValuesKt.getValueOrNull1(ic1N) as! Int, expected: 17) |
| |
| try assertEquals(actual: ValuesKt.getValue2(ic2), expected: "foo") |
| try assertEquals(actual: ValuesKt.getValueOrNull2(ic2N), expected: "bar") |
| |
| try assertEquals(actual: ValuesKt.getValue3(ic3), expected: ic3) |
| try assertEquals(actual: ValuesKt.getValueOrNull3(ic3N), expected: nil) |
| } |
| |
| class TestSharedIImpl : NSObject, I { |
| func iFun() -> String { |
| return "TestSharedIImpl::iFun" |
| } |
| } |
| |
| func testShared() throws { |
| if !ValuesKt.isFreezingEnabled() { |
| return; |
| } |
| func assertFrozen(_ obj: AnyObject) throws { |
| try assertTrue(ValuesKt.isFrozen(obj: obj), "isFrozen(\(obj))") |
| } |
| |
| func assertNotFrozen(_ obj: AnyObject) throws { |
| try assertFalse(ValuesKt.isFrozen(obj: obj), "isFrozen(\(obj))") |
| } |
| |
| try assertFrozen(NSObject()) |
| try assertFrozen(TestSharedIImpl()) |
| try assertFrozen(ValuesKt.kotlinLambda(block: { return $0 }) as AnyObject) |
| try assertNotFrozen(FinalClassExtOpen()) |
| } |
| |
| class PureSwiftClass { |
| } |
| |
| struct PureSwiftStruct { |
| var x: Int |
| } |
| class PureSwiftKotlinInterfaceImpl : I { |
| func iFun() -> String { |
| return "pure" |
| } |
| } |
| |
| func testPureSwiftClasses() throws { |
| let pureSwiftClass = PureSwiftClass() |
| try assertTrue(ValuesKt.same(pureSwiftClass) as? AnyObject === pureSwiftClass) |
| |
| try assertEquals(actual: 123, expected: (ValuesKt.same(PureSwiftStruct(x: 123)) as? PureSwiftStruct)?.x) |
| try assertEquals(actual: "pure", expected: ValuesKt.iFunExt(PureSwiftKotlinInterfaceImpl())) |
| } |
| |
| func testNames() throws { |
| try assertEquals(actual: ValuesKt.PROPERTY_NAME_MUST_NOT_BE_ALTERED_BY_SWIFT, expected: 111) |
| try assertEquals(actual: Deeply.NestedType().thirtyTwo, expected: 32) |
| #if NO_GENERICS |
| try assertEquals(actual: WithGenericDeeply.NestedType().thirtyThree, expected: 33) |
| #else |
| try assertEquals(actual: WithGenericDeeplyNestedType<AnyObject>().thirtyThree, expected: 33) |
| #endif |
| try assertEquals(actual: CKeywords(float: 1.0, enum : 42, goto: true).goto_, expected: true) |
| try assertEquals(actual: TypeOuter.Type_().thirtyFour, expected: 34) |
| try assertTrue(String(describing: DeeplyNestedIType.self).hasSuffix("DeeplyNestedIType")) |
| } |
| |
| class Base123 : Base23, ExtendedBase1 { |
| override func same(value: KotlinInt?) -> KotlinInt { |
| return value! |
| } |
| } |
| |
| func testSwiftOverride() throws { |
| let impl = Base123() |
| try assertEquals(actual: ValuesKt.call(base1: impl, value: 1), expected: 1) |
| try assertEquals(actual: ValuesKt.call(extendedBase1: impl, value: 2), expected: 2) |
| try assertEquals(actual: ValuesKt.call(base2: impl, value: 3), expected: 3) |
| try assertEquals(actual: ValuesKt.call(base3: impl, value: 4), expected: 4) |
| try assertEquals(actual: ValuesKt.call(base23: impl, value: 5), expected: 5) |
| } |
| |
| class TransformIntToLongCallingSuper : TransformIntToLong { |
| override func map(value: KotlinInt) -> KotlinLong { |
| return super.map(value: value) |
| } |
| } |
| |
| func testKotlinOverride() throws { |
| #if NO_GENERICS |
| try assertEquals(actual: TransformInheritingDefault().map(value: 1) as! Int32, expected: 1) |
| #else |
| try assertEquals(actual: TransformInheritingDefault<NSNumber>().map(value: 1) as! Int32, expected: 1) |
| #endif |
| try assertEquals(actual: TransformIntToDecimalString().map(value: 2), expected: "2") |
| try assertEquals(actual: TransformIntToDecimalString().map(intValue: 3), expected: "3") |
| try assertEquals(actual: ValuesKt.createTransformDecimalStringToInt().map(value: "4") as! Int32, expected: 4) |
| try assertEquals(actual: TransformIntToLongCallingSuper().map(value: 5), expected: 5) |
| } |
| |
| // See https://github.com/JetBrains/kotlin-native/issues/2945 |
| func testGH2945() throws { |
| let gh2945 = GH2945(errno: 1) |
| try assertEquals(actual: 1, expected: gh2945.errno) |
| gh2945.errno = 2 |
| try assertEquals(actual: 2, expected: gh2945.errno) |
| |
| try assertEquals(actual: 7, expected: gh2945.testErrnoInSelector(p: 3, errno: 4)) |
| } |
| |
| // See https://github.com/JetBrains/kotlin-native/issues/2830 |
| func testGH2830() throws { |
| try assertTrue(GH2830().getI() is GH2830I) |
| } |
| |
| // See https://github.com/JetBrains/kotlin-native/issues/2959 |
| func testGH2959() throws { |
| try assertEquals(actual: GH2959().getI(id: 2959)[0].id, expected: 2959) |
| } |
| |
| func testKClass() throws { |
| let test = TestKClass() |
| |
| let testKClass = test.getKotlinClass(clazz: TestKClass.self)! |
| try assertTrue(test.isTestKClass(kClass: testKClass)) |
| try assertFalse(test.isI(kClass: testKClass)) |
| try assertEquals(actual: testKClass.simpleName, expected: "TestKClass") |
| |
| let iKClass = test.getKotlinClass(protocol: TestKClassI.self)! |
| try assertFalse(test.isTestKClass(kClass: iKClass)) |
| try assertTrue(test.isI(kClass: iKClass)) |
| try assertEquals(actual: iKClass.simpleName, expected: "I") |
| |
| try assertTrue(test.getKotlinClass(clazz: NSObject.self) == nil) |
| try assertTrue(test.getKotlinClass(clazz: PureSwiftClass.self) == nil) |
| try assertTrue(test.getKotlinClass(clazz: PureSwiftKotlinInterfaceImpl.self) == nil) |
| try assertTrue(test.getKotlinClass(clazz: Base123.self) == nil) |
| |
| try assertTrue(test.getKotlinClass(protocol: NSObjectProtocol.self) == nil) |
| } |
| |
| open class TestSR10177WorkaroundBase<T> {} |
| class TestSR10177WorkaroundDerived : TestSR10177WorkaroundBase<TestSR10177Workaround> {} |
| |
| // See https://bugs.swift.org/browse/SR-10177 and https://bugs.swift.org/browse/SR-10217 |
| func testSR10177Workaround() throws { |
| let test = TestSR10177WorkaroundDerived() |
| try assertTrue(String(describing: test).contains("TestSR10177WorkaroundDerived")) |
| } |
| |
| func testClashes() throws { |
| let test = TestClashesImpl() |
| let test1: TestClashes1 = test |
| let test2: TestClashes2 = test |
| |
| try assertEquals(actual: 1, expected: test1.clashingProperty) |
| |
| #if !DISABLE_MEMBER_NAME_MANGLING && !DISABLE_INTERFACE_METHOD_NAME_MANGLING |
| try assertEquals(actual: 1, expected: test2.clashingProperty_ as! Int32) |
| try assertEquals(actual: 2, expected: test2.clashingProperty__ as! Int32) |
| #endif |
| } |
| |
| func testInvalidIdentifiers() throws { |
| let test = TestInvalidIdentifiers() |
| |
| try assertEquals(actual: 42, expected: test.aSdSd(S1: 13, _2: 14, _3: 15)) |
| |
| try assertEquals(actual: TestInvalidIdentifiers.E._4s.value, expected: 4) |
| try assertEquals(actual: TestInvalidIdentifiers.E._5s.value, expected: 5) |
| try assertEquals(actual: TestInvalidIdentifiers.E.__.value, expected: 6) |
| try assertEquals(actual: TestInvalidIdentifiers.E.___.value, expected: 7) |
| |
| try assertEquals(actual: TestInvalidIdentifiers.CompanionS()._42, expected: 42) |
| |
| #if !DISABLE_MEMBER_NAME_MANGLING |
| try assertEquals(actual: Set([test.__, test.___]), expected: Set(["_".utf16.first, "_".utf16.first])) |
| #endif |
| } |
| |
| class ImplementingHiddenSubclass : TestDeprecation.ImplementingHidden { |
| override func effectivelyHidden() -> Int32 { |
| return -2 |
| } |
| } |
| |
| func testDeprecation() throws { |
| let test = TestDeprecation() |
| try assertEquals(actual: test.openNormal(), expected: 1) |
| |
| let testHiddenOverride: TestDeprecation = TestDeprecation.HiddenOverride() |
| try assertEquals(actual: testHiddenOverride.openNormal(), expected: 2) |
| |
| let testErrorOverride: TestDeprecation = TestDeprecation.ErrorOverride() |
| try assertEquals(actual: testErrorOverride.openNormal(), expected: 3) |
| |
| let testWarningOverride: TestDeprecation = TestDeprecation.WarningOverride() |
| try assertEquals(actual: testWarningOverride.openNormal(), expected: 4) |
| |
| try assertEquals(actual: test.callEffectivelyHidden(obj: ImplementingHiddenSubclass()), expected: -2) |
| } |
| |
| func setAssociatedObject(object: AnyObject, value: AnyObject) { |
| objc_setAssociatedObject( |
| object, |
| UnsafeRawPointer(bitPattern: 1)!, |
| value, |
| objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN |
| ) |
| } |
| |
| func testWeakRefs() throws { |
| #if !NOOP_GC |
| try testWeakRefs0(frozen: false) |
| try testWeakRefs0(frozen: true) |
| #endif |
| } |
| |
| func testWeakRefs0(frozen: Bool) throws { |
| func getObj(test: TestWeakRefs) -> AnyObject { |
| return autoreleasepool { test.getObj() as AnyObject } |
| } |
| |
| func test1() throws { |
| var test = TestWeakRefs(frozen: frozen) |
| |
| var obj: AnyObject? = getObj(test: test) |
| weak var ref = getObj(test: test) |
| |
| ValuesKt.gc() |
| try assertTrue(ref === getObj(test: test)) // There are both Kotlin and Swift references to the object. |
| |
| obj = nil |
| ValuesKt.gc() |
| try assertTrue(ref === getObj(test: test)) // There are only Kotlin references to the object. |
| |
| test.clearObj() |
| ValuesKt.gc() |
| try assertTrue(ref === nil) |
| } |
| |
| func test2() throws { |
| var test = TestWeakRefs(frozen: frozen) |
| |
| var obj: AnyObject? = getObj(test: test) |
| weak var ref = getObj(test: test) |
| |
| ValuesKt.gc() |
| try assertTrue(ref === obj!) // There are both Kotlin and Swift references to the object. |
| |
| test.clearObj() |
| ValuesKt.gc() |
| try assertTrue(ref === obj!) // There are only Swift references to the object. |
| |
| obj = nil |
| ValuesKt.gc() |
| try assertTrue(ref === nil) |
| } |
| |
| func test3() throws { |
| class Holder { |
| static weak var ref: AnyObject? = nil |
| static var deinitialized = false |
| |
| deinit { |
| // Access weak ref to Kotlin object during its counterpart dealloc: |
| try! assertTrue(Holder.ref === nil) |
| Holder.deinitialized = true |
| } |
| } |
| |
| Holder.deinitialized = false |
| Holder.ref = nil |
| |
| var test = TestWeakRefs(frozen: frozen) |
| |
| Holder.ref = getObj(test: test) |
| |
| // Prepare Holder() to get deinitialized along with getObj(test: test): |
| setAssociatedObject( |
| object: getObj(test: test), |
| value: Holder() |
| ) |
| |
| try assertFalse(Holder.ref === nil) |
| try assertFalse(Holder.deinitialized) |
| |
| test.clearObj() |
| ValuesKt.gc() |
| |
| try assertTrue(Holder.ref === nil) |
| try assertTrue(Holder.deinitialized) |
| } |
| |
| func test4() throws { |
| class Holder { |
| static weak var ref1: AnyObject? = nil |
| static weak var ref2: AnyObject? = nil |
| static var deinitialized: Int = 0 |
| |
| deinit { |
| // Access weak ref to Kotlin object during its counterpart dealloc: |
| try! assertTrue(Holder.ref1 === nil) |
| try! assertTrue(Holder.ref2 === nil) |
| Holder.deinitialized += 1 |
| } |
| } |
| |
| Holder.deinitialized = 0 |
| Holder.ref1 = nil |
| Holder.ref2 = nil |
| |
| var test = TestWeakRefs(frozen: frozen) |
| |
| autoreleasepool { |
| let cycle = test.createCycle() |
| |
| let obj1 = cycle[0] as AnyObject |
| let obj2 = cycle[1] as AnyObject |
| |
| // Prepare Holders to get deinitialized along with obj1 and obj2: |
| setAssociatedObject(object: obj1, value: Holder()) |
| setAssociatedObject(object: obj2, value: Holder()) |
| |
| Holder.ref1 = obj1 |
| Holder.ref2 = obj2 |
| } |
| |
| ValuesKt.gc() |
| |
| try assertTrue(Holder.ref1 === nil) |
| try assertTrue(Holder.ref2 === nil) |
| try assertEquals(actual: Holder.deinitialized, expected: 2) |
| } |
| |
| try test1() |
| try test2() |
| try test3() |
| try test4() |
| } |
| |
| var falseFlag = false |
| |
| class TestSharedRefs { |
| private func testLambdaSimple() throws { |
| func getClosure() -> (() -> Void) { |
| let lambda = autoreleasepool { |
| SharedRefs().createLambda() |
| } |
| return { if falseFlag { lambda() } } |
| } |
| |
| DispatchQueue.global().async(execute: getClosure()) |
| } |
| |
| private static func launchInNewThread(initializeKotlinRuntime: Bool, block: @escaping () -> Void) -> pthread_t { |
| class Closure { |
| static var currentBlock: (() -> Void)? = nil |
| static var initializeKotlinRuntime: Bool = false |
| } |
| |
| Closure.currentBlock = block |
| Closure.initializeKotlinRuntime = initializeKotlinRuntime |
| |
| var thread: pthread_t? = nil |
| let createCode = pthread_create(&thread, nil, { _ in |
| if Closure.initializeKotlinRuntime { |
| let ignore = SharedRefs() // Ensures that Kotlin runtime gets initialized. |
| } |
| |
| // Take the block from Closure to avoid races when block() execution triggers |
| // calling launchInNewThread on another thread (e.g. on the finalizer thread). |
| let block = Closure.currentBlock! |
| Closure.currentBlock = nil |
| |
| block() |
| |
| return nil |
| }, nil) |
| try! assertEquals(actual: createCode, expected: 0) |
| return thread! |
| } |
| |
| private static func joinThread(thread: pthread_t) { |
| let joinCode = pthread_join(thread, nil) |
| try! assertEquals(actual: joinCode, expected: 0) |
| } |
| |
| private static func runInNewThread(initializeKotlinRuntime: Bool, block: @escaping () -> Void) { |
| let thread = launchInNewThread(initializeKotlinRuntime: initializeKotlinRuntime, block: block) |
| joinThread(thread: thread) |
| } |
| |
| private func runInNewThread(initializeKotlinRuntime: Bool, block: @escaping () -> Void) { |
| return TestSharedRefs.runInNewThread(initializeKotlinRuntime: initializeKotlinRuntime, block: block) |
| } |
| |
| private func testObjectPartialRelease() { |
| let object = autoreleasepool { SharedRefs().createRegularObject() } |
| var objectVar: AnyObject? = object |
| |
| runInNewThread(initializeKotlinRuntime: true) { |
| objectVar = nil |
| } |
| } |
| |
| private func testRunRefCount<T>( |
| run: (@escaping () -> Void) -> Void, |
| createObject: @escaping (SharedRefs) -> T |
| ) throws { |
| let refs = SharedRefs() |
| |
| var objectVar1: T? = autoreleasepool { createObject(refs) } |
| var objectVar2: T? = nil |
| |
| try assertTrue(refs.hasAliveObjects()) |
| |
| run { |
| objectVar2 = objectVar1! |
| objectVar1 = nil |
| } |
| |
| try assertTrue(refs.hasAliveObjects()) |
| |
| run { |
| objectVar2 = nil |
| } |
| |
| try assertFalse(refs.hasAliveObjects()) |
| } |
| |
| private func testBackgroundRefCount<T>(createObject: @escaping (SharedRefs) -> T) throws { |
| try testRunRefCount( |
| run: { runInNewThread(initializeKotlinRuntime: false, block: $0) }, |
| createObject: createObject |
| ) |
| |
| try testRunRefCount( |
| run: { runInNewThread(initializeKotlinRuntime: true, block: $0) }, |
| createObject: createObject |
| ) |
| } |
| |
| private func testReferenceOutlivesThread(releaseWithKotlinRuntime: Bool) throws { |
| var objectVar: AnyObject? = nil |
| weak var objectWeakVar: AnyObject? = nil |
| var collection: AnyObject? = nil |
| |
| runInNewThread(initializeKotlinRuntime: false) { |
| autoreleasepool { |
| let refs = SharedRefs() |
| collection = refs.createCollection() |
| |
| let object = refs.createRegularObject() |
| objectVar = object |
| objectWeakVar = object |
| |
| try! assertTrue(objectWeakVar === object) |
| } |
| } |
| |
| runInNewThread(initializeKotlinRuntime: releaseWithKotlinRuntime) { |
| objectVar = nil |
| collection = nil |
| ValuesKt.gc() |
| try! assertTrue(objectWeakVar === nil) |
| } |
| |
| } |
| |
| private func testMoreWorkBeforeThreadExit() throws { |
| class Deinit { |
| static var object1: AnyObject? = nil |
| static var object2: AnyObject? = nil |
| static weak var weakVar2: AnyObject? = nil |
| |
| deinit { |
| TestSharedRefs.runInNewThread(initializeKotlinRuntime: false) { |
| Deinit.object2 = nil |
| } |
| } |
| } |
| |
| runInNewThread(initializeKotlinRuntime: false) { |
| autoreleasepool { |
| let object1 = SharedRefs.MutableData() |
| Deinit.object1 = object1 |
| setAssociatedObject(object: object1, value: Deinit()) |
| |
| let object2 = SharedRefs.MutableData() |
| Deinit.object2 = object2 |
| Deinit.weakVar2 = object2 |
| } |
| |
| TestSharedRefs.runInNewThread(initializeKotlinRuntime: false) { |
| Deinit.object1 = nil |
| } |
| } |
| |
| // This will free `object1` and release+dealloc its associated `Deinit` which nils `Deinit.object2` |
| ValuesKt.gc() |
| // This will free `object2`. |
| ValuesKt.gc() |
| |
| try assertTrue(Deinit.weakVar2 === nil) |
| } |
| |
| func testRememberNewObject(createObject: @escaping (SharedRefs) -> AnyObject) throws { |
| |
| class TestImpl : TestRememberNewObject { |
| let cleanupFinishedSemaphore = DispatchSemaphore(value: 0) |
| let threadWaitingForCleanupSemaphore = DispatchSemaphore(value: 0) |
| |
| var obj: AnyObject? = nil |
| |
| func getObject() -> Any { |
| return obj! |
| } |
| |
| func waitForCleanup() { |
| threadWaitingForCleanupSemaphore.signal() |
| cleanupFinishedSemaphore.wait() |
| } |
| } |
| |
| let test = TestImpl() |
| |
| let refs = SharedRefs() |
| try assertFalse(refs.hasAliveObjects()) |
| |
| autoreleasepool { |
| test.obj = createObject(refs) |
| } |
| |
| try assertTrue(refs.hasAliveObjects()) |
| |
| let thread = TestSharedRefs.launchInNewThread(initializeKotlinRuntime: false) { |
| ValuesKt.testRememberNewObject(test: test) |
| } |
| |
| test.threadWaitingForCleanupSemaphore.wait() |
| test.obj = nil |
| ValuesKt.gc() |
| |
| try assertTrue(refs.hasAliveObjects()) |
| |
| test.cleanupFinishedSemaphore.signal() |
| |
| TestSharedRefs.joinThread(thread: thread) |
| try assertFalse(refs.hasAliveObjects()) |
| } |
| |
| // Based on https://youtrack.jetbrains.com/issue/KT-49497. |
| |
| func testKT49497() throws { |
| var model: KT49497Model? = nil |
| |
| for i in 1...10 { |
| model = KT49497Model() // Frozen and has a reference to itself, so becomes aggregating frozen container. |
| ValuesKt.gc() // Just in case, to ensure there are no other references except `model`. |
| |
| runInNewThread(initializeKotlinRuntime: false) { |
| // Thread has no runtime initialized, so this should enqueue release ref to the original thread: |
| model = nil |
| } |
| |
| ValuesKt.gc() // Process the enqueued release ref. |
| } |
| } |
| |
| func test() throws { |
| try testLambdaSimple() |
| try testObjectPartialRelease() |
| |
| #if !NOOP_GC |
| try testBackgroundRefCount(createObject: { $0.createLambda() }) |
| try testBackgroundRefCount(createObject: { $0.createRegularObject() }) |
| try testBackgroundRefCount(createObject: { $0.createCollection() }) |
| |
| try testBackgroundRefCount(createObject: { $0.createFrozenLambda() }) |
| try testBackgroundRefCount(createObject: { $0.createFrozenRegularObject() }) |
| try testBackgroundRefCount(createObject: { $0.createFrozenCollection() }) |
| |
| try testReferenceOutlivesThread(releaseWithKotlinRuntime: false) |
| try testReferenceOutlivesThread(releaseWithKotlinRuntime: true) |
| try testMoreWorkBeforeThreadExit() |
| |
| try testRememberNewObject(createObject: { $0.createFrozenRegularObject() }) |
| try testRememberNewObject(createObject: { $0.createFrozenCollection() }) |
| #endif |
| |
| try testKT49497() |
| |
| usleep(300 * 1000) |
| } |
| } |
| |
| // See https://github.com/JetBrains/kotlin-native/issues/2931 |
| func testGH2931() throws { |
| for i in 0..<50000 { |
| let holder = GH2931.Holder() |
| let queue = DispatchQueue.global(qos: .background) |
| let group = DispatchGroup() |
| |
| for j in 0..<2 { |
| group.enter() |
| queue.async { |
| autoreleasepool { |
| holder.data |
| } |
| group.leave() |
| } |
| } |
| |
| group.wait() |
| } |
| } |
| |
| class ClassForTypeCheckInheritor : ClassForTypeCheck { } |
| |
| func testClassTypeCheck() throws { |
| try assertTrue(ValuesKt.testClassTypeCheck(x: ClassForTypeCheckInheritor())) |
| } |
| |
| class ClassForInterfaceTypeCheckInheritor1 : InterfaceForTypeCheck { } |
| class ClassForInterfaceTypeCheckInheritor2 : Base23, InterfaceForTypeCheck { } |
| class ClassForInterfaceTypeCheckInheritor3 : Base23, ExtendedBase1, InterfaceForTypeCheck { } |
| class ClassForInterfaceTypeCheck_Fail : Base23 { } |
| |
| func testInterfaceTypeCheck() throws { |
| try assertTrue(ValuesKt.testInterfaceTypeCheck(x: ClassForInterfaceTypeCheckInheritor1())) |
| try assertTrue(ValuesKt.testInterfaceTypeCheck(x: ClassForInterfaceTypeCheckInheritor2())) |
| try assertTrue(ValuesKt.testInterfaceTypeCheck(x: ClassForInterfaceTypeCheckInheritor3())) |
| try assertFalse(ValuesKt.testInterfaceTypeCheck(x: ClassForInterfaceTypeCheck_Fail())) |
| } |
| |
| class AbstractInterface : AbstractInterfaceBase { |
| override func bar() -> Int32 { |
| return 42 |
| } |
| } |
| |
| // See https://github.com/JetBrains/kotlin-native/issues/3503 |
| func testGH3503_1() throws { |
| try assertEquals(actual: ValuesKt.testAbstractInterfaceCall(x: AbstractInterface()), expected: 42) |
| } |
| |
| class AbstractInterface2 : AbstractInterfaceBase2 { |
| |
| } |
| |
| func testGH3503_2() throws { |
| try assertEquals(actual: ValuesKt.testAbstractInterfaceCall2(x: AbstractInterface2()), expected: 42) |
| } |
| |
| class AbstractInterface3 : AbstractInterfaceBase3 { |
| override func foo() -> Int32 { |
| return 42 |
| } |
| } |
| |
| func testGH3503_3() throws { |
| try assertEquals(actual: ValuesKt.testAbstractInterfaceCall(x: AbstractInterface3()), expected: 42) |
| } |
| |
| func testGH3525() throws { |
| try assertEquals(actual: ValuesKt.gh3525BaseInitCount, expected: 0) |
| try assertEquals(actual: ValuesKt.gh3525InitCount, expected: 0) |
| |
| let gh3525_1 = GH3525() |
| try assertTrue(gh3525_1 is GH3525) |
| |
| try assertEquals(actual: ValuesKt.gh3525BaseInitCount, expected: 1) |
| try assertEquals(actual: ValuesKt.gh3525InitCount, expected: 1) |
| |
| let gh3525_2 = GH3525() |
| try assertTrue(gh3525_2 is GH3525) |
| |
| try assertEquals(actual: ValuesKt.gh3525BaseInitCount, expected: 1) |
| try assertEquals(actual: ValuesKt.gh3525InitCount, expected: 1) |
| |
| try assertTrue(gh3525_1 === gh3525_2) |
| } |
| |
| func testStringConversion() throws { |
| func test1() throws { |
| let test = TestStringConversion() |
| |
| let buffer = NSMutableString() |
| buffer.append("a") |
| test.str = buffer |
| buffer.append("b") |
| |
| try assertEquals(actual: buffer, expected: "ab") |
| // Ensure test.str isn't affected by buffer mutation: |
| try assertEquals(actual: test.str as! NSString, expected: "a") |
| } |
| |
| func ensureNoCopy(nsStr: NSString) throws { |
| let test = TestStringConversion() |
| |
| test.str = nsStr |
| let nsStr2 = test.str as! NSString |
| |
| // Ensure no additional NSString created on both conversions: |
| try assertTrue(nsStr === nsStr2) |
| } |
| |
| func test2() throws { |
| var str = "a" |
| str += NSObject().description |
| try ensureNoCopy(nsStr: str as NSString) |
| |
| try ensureNoCopy(nsStr: NSString("abc")) |
| |
| try ensureNoCopy(nsStr: NSString(format: "%d%d%d", 3, 2, 1)) |
| } |
| |
| try test1() |
| try test2() |
| } |
| |
| class GH3825SwiftImpl : GH3825 { |
| class E : Error {} |
| |
| func call0(callback: () -> KotlinBoolean) throws { |
| if callback().boolValue { throw E() } |
| } |
| |
| func call1(doThrow: Bool, callback: () -> Void) throws { |
| if doThrow { throw E() } |
| callback() |
| } |
| |
| func call2(callback: () -> Void, doThrow: Bool) throws { |
| if doThrow { throw E() } |
| callback() |
| } |
| } |
| |
| func testGH3825() throws { |
| try ValuesKt.testGH3825(gh3825: GH3825SwiftImpl()) |
| |
| let test = GH3825KotlinImpl() |
| var count = 0 |
| |
| try testThrowing { try test.call0 { true } } |
| try test.call0 { |
| count += 1 |
| return false |
| } |
| try assertEquals(actual: count, expected: 1) |
| |
| try testThrowing { try test.call1(doThrow: true) { count += 1 } } |
| try test.call1(doThrow: false) { count += 1 } |
| try assertEquals(actual: count, expected: 2) |
| |
| try testThrowing { try test.call2(callback: { count += 1 }, doThrow: true)} |
| try test.call2(callback: { count += 1 }, doThrow: false) |
| try assertEquals(actual: count, expected: 3) |
| } |
| |
| |
| func testMapsExport() throws { |
| // Original reproducer failed in different way for MutableMap (iOS 11) and Map (MacOS 10.14, iOS 13) |
| |
| try assertEquals(actual: ValuesKt.mapBoolean2String()[true], expected: "true") |
| try assertEquals(actual: ValuesKt.mapByte2Short()[-1], expected: 2) |
| try assertEquals(actual: ValuesKt.mapShort2Byte()[-2], expected: 1) |
| try assertEquals(actual: ValuesKt.mapInt2Long()[-4], expected: 8) |
| try assertEquals(actual: ValuesKt.mapLong2Long()[-8], expected: 8) |
| try assertEquals(actual: ValuesKt.mapUByte2Boolean()[128], expected: true) |
| try assertEquals(actual: ValuesKt.mapUShort2Byte()[0x8000], expected: 1) |
| try assertEquals(actual: ValuesKt.mapUInt2Long()[0x7FFFFFFF], expected: 7) |
| // the following samples require explicit cast to KotlinUInt or KotlinULong |
| try assertEquals(actual: ValuesKt.mapUInt2Long()[KotlinUInt(-0x8000_0000)], expected: 8) |
| _ = ValuesKt.mapULong2Long() as! [KotlinULong: KotlinLong] // test cast |
| var u64: UInt64 = 0x8000_0000_0000_0000 |
| try assertEquals(actual: ValuesKt.mapULong2Long()[KotlinULong(value: u64)], expected: 8) |
| |
| _ = ValuesKt.mapFloat2Float() as! [KotlinFloat: KotlinFloat] // test cast |
| try assertEquals(actual: ValuesKt.mapFloat2Float()[3.14], expected: 100.0) |
| try assertEquals(actual: ValuesKt.mapDouble2String()[2.718281828459045], expected: "2.718281828459045") |
| |
| // test also explicit cast to [:] of primitiva types, e.g. [Int: Int] |
| try assertEquals(actual: (ValuesKt.mutBoolean2String() as! [Bool: String])[true], expected: "true") |
| try assertEquals(actual: (ValuesKt.mutByte2Short() as! [Int8: Int16])[-1], expected: 2) |
| try assertEquals(actual: (ValuesKt.mutShort2Byte() as! [Int16: Int8])[-2], expected: 1) |
| try assertEquals(actual: (ValuesKt.mutInt2Long() as! [Int: Int64])[-4], expected: 8) |
| try assertEquals(actual: (ValuesKt.mutLong2Long() as! [Int64: Int64])[-8], expected: 8) |
| |
| try assertEquals(actual: (ValuesKt.mutUByte2Boolean() as! [UInt8: Bool])[128], expected: true) |
| try assertEquals(actual: (ValuesKt.mutUShort2Byte() as! [UInt16: Int8])[0x8000], expected: 1) |
| // the following samples require explicit cast to KotlinUInt or KotlinULong |
| try assertEquals(actual: (ValuesKt.mutUInt2Long() as! [UInt: Int64])[UInt(0x8000_0000)], expected: 8) |
| |
| try assertEquals(actual: (ValuesKt.mutULong2Long() as! [UInt64: Int64])[u64], expected: 8) |
| |
| try assertEquals(actual: (ValuesKt.mutFloat2Float() as! [Float: Float])[3.14], expected: 100.0) |
| try assertEquals(actual: (ValuesKt.mutDouble2String() as! [Double: String])[2.718281828459045], expected: "2.718281828459045") |
| } |
| |
| class Baz_FakeOverrideInInterface : Bar_FakeOverrideInInterface { |
| func foo(t: Any?) {} |
| } |
| |
| func testFakeOverrideInInterface() throws { |
| ValuesKt.callFoo_FakeOverrideInInterface(obj: Baz_FakeOverrideInInterface()) |
| } |
| |
| // -------- Execution of the test -------- |
| |
| class ValuesTests : SimpleTestProvider { |
| override init() { |
| super.init() |
| |
| test("TestValues", testVals) |
| test("TestVars", testVars) |
| test("TestDoubles", testDoubles) |
| test("TestNumbers", testNumbers) |
| test("TestLists", testLists) |
| test("TestLazyValues", testLazyVal) |
| test("TestDelegatedProperties", testDelegatedProp) |
| test("TestGetterDelegate", testGetterDelegate) |
| test("TestNulls", testNulls) |
| test("TestAnyVar", testAnyVar) |
| test("TestFunctions", testFunctions) |
| test("TestExceptions", testExceptions) |
| test("TestFuncType", testFuncType) |
| test("TestGenericsFoo", testGenericsFoo) |
| test("TestVararg", testVararg) |
| test("TestStringExtension", testStrExtFun) |
| test("TestAnyToString", testAnyToString) |
| test("TestAnyPrint", testAnyPrint) |
| test("TestCharExtensions", testCharExtensions) |
| test("TestLambda", testLambda) |
| test("TestInterfaceExtension", testInterfaceExtension) |
| test("TestClassInstances", testClassInstances) |
| test("TestEnum", testEnum) |
| test("TestDataClass", testDataClass) |
| test("TestCompanionObj", testCompanionObj) |
| test("TestInlineClasses", testInlineClasses) |
| test("TestShared", testShared) |
| test("TestPureSwiftClasses", testPureSwiftClasses) |
| test("TestNames", testNames) |
| test("TestSwiftOverride", testSwiftOverride) |
| test("TestKotlinOverride", testKotlinOverride) |
| test("TestGH2945", testGH2945) |
| test("TestGH2830", testGH2830) |
| test("TestGH2959", testGH2959) |
| test("TestKClass", testKClass) |
| test("TestSR10177Workaround", testSR10177Workaround) |
| test("TestClashes", testClashes) |
| test("TestInvalidIdentifiers", testInvalidIdentifiers) |
| test("TestDeprecation", testDeprecation) |
| test("TestWeakRefs", testWeakRefs) |
| test("TestSharedRefs", TestSharedRefs().test) |
| test("TestClassTypeCheck", testClassTypeCheck) |
| test("TestInterfaceTypeCheck", testInterfaceTypeCheck) |
| test("TestGH3503_1", testGH3503_1) |
| test("TestGH3503_2", testGH3503_2) |
| test("TestGH3503_3", testGH3503_3) |
| test("TestGH3525", testGH3525) |
| test("TestStringConversion", testStringConversion) |
| test("TestGH3825", testGH3825) |
| test("TestMapsExport", testMapsExport) |
| test("TestFakeOverrideInInterface", testFakeOverrideInInterface) |
| |
| // Stress test, must remain the last one: |
| test("TestGH2931", testGH2931) |
| } |
| } |