From 8bcee1e632bb3a3f2ce980f545492c2cf2793490 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Fri, 7 Feb 2020 11:52:20 +0300 Subject: [PATCH] Rework `@Throws` tests --- .../tests/framework/values/expectedLazy.h | 97 +++++++++++-- .../tests/framework/values/values.kt | 130 +++++++++++++++--- .../tests/framework/values/values.swift | 123 +++++++++++++---- 3 files changed, 294 insertions(+), 56 deletions(-) diff --git a/backend.native/tests/framework/values/expectedLazy.h b/backend.native/tests/framework/values/expectedLazy.h index fa66fdd4053..7b18c4bb369 100644 --- a/backend.native/tests/framework/values/expectedLazy.h +++ b/backend.native/tests/framework/values/expectedLazy.h @@ -265,25 +265,90 @@ __attribute__((swift_name("MyException"))) - (instancetype)initWithCause:(ValuesKotlinThrowable * _Nullable)cause __attribute__((swift_name("init(cause:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); @end; -__attribute__((swift_name("BridgeBase"))) -@interface ValuesBridgeBase : ValuesBase +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("MyError"))) +@interface ValuesMyError : ValuesKotlinError - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); -- (id _Nullable)foo1AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo1()"))); -- (int32_t)foo2AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo2()"))) __attribute__((swift_error(nonnull_error))); -- (BOOL)foo3AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo3()"))); -- (ValuesKotlinNothing * _Nullable)foo4AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo4()"))) __attribute__((swift_error(nonnull_error))); +- (instancetype)initWithMessage:(NSString * _Nullable)message __attribute__((swift_name("init(message:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithMessage:(NSString * _Nullable)message cause:(ValuesKotlinThrowable * _Nullable)cause __attribute__((swift_name("init(message:cause:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +- (instancetype)initWithCause:(ValuesKotlinThrowable * _Nullable)cause __attribute__((swift_name("init(cause:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); +@end; + +__attribute__((swift_name("SwiftOverridableMethodsWithThrows"))) +@protocol ValuesSwiftOverridableMethodsWithThrows +@required +- (BOOL)unitAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("unit()"))); +- (BOOL)nothingAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothing()"))); +- (id _Nullable)anyAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("any()"))); +- (ValuesInt *(^ _Nullable)(void))blockAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("block()"))); +@end; + +__attribute__((swift_name("MethodsWithThrows"))) +@protocol ValuesMethodsWithThrows +@required +- (ValuesKotlinNothing * _Nullable)nothingNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothingN()"))) __attribute__((swift_error(nonnull_error))); +- (id _Nullable)anyNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("anyN()"))) __attribute__((swift_error(nonnull_error))); +- (ValuesInt *(^ _Nullable)(void))blockNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("blockN()"))) __attribute__((swift_error(nonnull_error))); +- (void * _Nullable)pointerAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointer()"))); +- (void * _Nullable)pointerNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointerN()"))) __attribute__((swift_error(nonnull_error))); +- (int32_t)intAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("int()"))) __attribute__((swift_error(nonnull_error))); +- (ValuesLong * _Nullable)longNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("longN()"))) __attribute__((swift_error(nonnull_error))); +- (double)doubleAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("double()"))) __attribute__((swift_error(nonnull_error))); +@end; + +__attribute__((swift_name("MethodsWithThrowsUnitCaller"))) +@protocol ValuesMethodsWithThrowsUnitCaller +@required +- (BOOL)callMethods:(id)methods error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("call(methods:)"))); +@end; + +__attribute__((swift_name("Throwing"))) +@interface ValuesThrowing : ValuesBase +- (instancetype _Nullable)initWithDoThrow:(BOOL)doThrow error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("init(doThrow:)"))) __attribute__((objc_designated_initializer)); +- (BOOL)unitAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("unit()"))); +- (BOOL)nothingAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothing()"))); +- (ValuesKotlinNothing * _Nullable)nothingNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothingN()"))) __attribute__((swift_error(nonnull_error))); +- (id _Nullable)anyAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("any()"))); +- (id _Nullable)anyNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("anyN()"))) __attribute__((swift_error(nonnull_error))); +- (ValuesInt *(^ _Nullable)(void))blockAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("block()"))); +- (ValuesInt *(^ _Nullable)(void))blockNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("blockN()"))) __attribute__((swift_error(nonnull_error))); +- (void * _Nullable)pointerAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointer()"))); +- (void * _Nullable)pointerNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointerN()"))) __attribute__((swift_error(nonnull_error))); +- (int32_t)intAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("int()"))) __attribute__((swift_error(nonnull_error))); +- (ValuesLong * _Nullable)longNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("longN()"))) __attribute__((swift_error(nonnull_error))); +- (double)doubleAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("double()"))) __attribute__((swift_error(nonnull_error))); @end; __attribute__((objc_subclassing_restricted)) -__attribute__((swift_name("Bridge"))) -@interface ValuesBridge : ValuesBridgeBase +__attribute__((swift_name("NotThrowing"))) +@interface ValuesNotThrowing : ValuesBase +- (instancetype _Nullable)initAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); +- (BOOL)unitAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("unit()"))); +- (BOOL)nothingAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothing()"))); +- (ValuesKotlinNothing * _Nullable)nothingNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("nothingN()"))) __attribute__((swift_error(nonnull_error))); +- (id _Nullable)anyAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("any()"))); +- (id _Nullable)anyNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("anyN()"))) __attribute__((swift_error(nonnull_error))); +- (ValuesInt *(^ _Nullable)(void))blockAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("block()"))); +- (ValuesInt *(^ _Nullable)(void))blockNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("blockN()"))) __attribute__((swift_error(nonnull_error))); +- (void * _Nullable)pointerAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointer()"))); +- (void * _Nullable)pointerNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("pointerN()"))) __attribute__((swift_error(nonnull_error))); +- (int32_t)intAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("int()"))) __attribute__((swift_error(nonnull_error))); +- (ValuesLong * _Nullable)longNAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("longN()"))) __attribute__((swift_error(nonnull_error))); +- (double)doubleAndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("double()"))) __attribute__((swift_error(nonnull_error))); +@end; + +__attribute__((swift_name("ThrowsWithBridgeBase"))) +@protocol ValuesThrowsWithBridgeBase +@required +- (id _Nullable)plusOneX:(int32_t)x error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("plusOne(x:)"))); +@end; + +__attribute__((swift_name("ThrowsWithBridge"))) +@interface ValuesThrowsWithBridge : ValuesBase - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); -- (ValuesKotlinNothing * _Nullable)foo1AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo1()"))); -- (int32_t)foo2AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo2()"))) __attribute__((swift_error(nonnull_error))); -- (BOOL)foo3AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo3()"))); -- (ValuesKotlinNothing *)foo4AndReturnError:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("foo4()"))) __attribute__((swift_error(nonnull_error))); +- (ValuesInt * _Nullable)plusOneX:(int32_t)x error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("plusOne(x:)"))); @end; __attribute__((objc_subclassing_restricted)) @@ -1102,7 +1167,13 @@ __attribute__((swift_name("ValuesKt"))) + (BOOL)isFrozenObj:(id)obj __attribute__((swift_name("isFrozen(obj:)"))); + (id)kotlinLambdaBlock:(id (^)(id))block __attribute__((swift_name("kotlinLambda(block:)"))); + (int64_t)multiplyInt:(int32_t)int_ long:(int64_t)long_ __attribute__((swift_name("multiply(int:long:)"))); -+ (id _Nullable)callFoo1Bridge:(ValuesBridgeBase *)bridge error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("callFoo1(bridge:)"))); ++ (BOOL)throwExceptionError:(BOOL)error error:(NSError * _Nullable * _Nullable)error_ __attribute__((swift_name("throwException(error:)"))); ++ (ValuesKotlinObjCErrorException * _Nullable)testSwiftThrowingMethods:(id)methods error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("testSwiftThrowing(methods:)"))); ++ (BOOL)testSwiftNotThrowingMethods:(id)methods error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("testSwiftNotThrowing(methods:)"))); ++ (BOOL)callUnitMethods:(id)methods error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("callUnit(methods:)"))); ++ (BOOL)callUnitCallerCaller:(id)caller methods:(id)methods error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("callUnitCaller(caller:methods:)"))); ++ (BOOL)testSwiftThrowingTest:(id)test flag:(BOOL)flag error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("testSwiftThrowing(test:flag:)"))); ++ (BOOL)testSwiftNotThrowingTest:(id)test error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("testSwiftNotThrowing(test:)"))); + (id)same:(id)receiver __attribute__((swift_name("same(_:)"))); + (ValuesInt * _Nullable)callBase1:(id)base1 value:(ValuesInt * _Nullable)value __attribute__((swift_name("call(base1:value:)"))); + (ValuesInt * _Nullable)callExtendedBase1:(id)extendedBase1 value:(ValuesInt * _Nullable)value __attribute__((swift_name("call(extendedBase1:value:)"))); diff --git a/backend.native/tests/framework/values/values.kt b/backend.native/tests/framework/values/values.kt index 756237074d4..e17a08097c3 100644 --- a/backend.native/tests/framework/values/values.kt +++ b/backend.native/tests/framework/values/values.kt @@ -14,6 +14,7 @@ import kotlin.native.ref.WeakReference import kotlin.properties.ReadWriteProperty import kotlin.reflect.KClass import kotlin.reflect.KProperty +import kotlin.test.* import kotlinx.cinterop.* // Ensure loaded function IR classes aren't ordered by arity: @@ -253,27 +254,124 @@ fun kotlinLambda(block: (Any) -> Any): Any = block fun multiply(int: Int, long: Long) = int * long class MyException : Exception() +class MyError : Error() -open class BridgeBase { - @Throws(MyException::class) - open fun foo1(): Any = Any() - @Throws(MyException::class) - open fun foo2(): Int = 42 - @Throws(MyException::class) - open fun foo3(): Unit = Unit - @Throws(MyException::class) - open fun foo4(): Nothing? = throw IllegalStateException() +@Throws(MyException::class, MyError::class) +fun throwException(error: Boolean): Unit { + throw if (error) MyError() else MyException() } -class Bridge : BridgeBase() { - override fun foo1() = throw MyException() - override fun foo2() = throw MyException() - override fun foo3() = throw MyException() - override fun foo4() = throw MyException() +interface SwiftOverridableMethodsWithThrows { + @Throws(MyException::class) fun unit(): Unit + @Throws(MyException::class) fun nothing(): Nothing + @Throws(MyException::class) fun any(): Any + @Throws(MyException::class) fun block(): () -> Int } -@Throws(NullPointerException::class) -fun callFoo1(bridge: BridgeBase) = bridge.foo1() +interface MethodsWithThrows : SwiftOverridableMethodsWithThrows { + @Throws(MyException::class) fun nothingN(): Nothing? + @Throws(MyException::class) fun anyN(): Any? + @Throws(MyException::class) fun blockN(): (() -> Int)? + @Throws(MyException::class) fun pointer(): CPointer<*> + @Throws(MyException::class) fun pointerN(): CPointer<*>? + @Throws(MyException::class) fun int(): Int + @Throws(MyException::class) fun longN(): Long? + @Throws(MyException::class) fun double(): Double + + interface UnitCaller { + @Throws(MyException::class) fun call(methods: MethodsWithThrows): Unit + } +} + +open class Throwing : MethodsWithThrows { + @Throws(MyException::class) constructor(doThrow: Boolean) { + if (doThrow) throw MyException() + } + + override fun unit(): Unit = throw MyException() + override fun nothing(): Nothing = throw MyException() + override fun nothingN(): Nothing? = throw MyException() + override fun any(): Any = throw MyException() + override fun anyN(): Any? = throw MyException() + override fun block(): () -> Int = throw MyException() + override fun blockN(): (() -> Int)? = throw MyException() + override fun pointer(): CPointer<*> = throw MyException() + override fun pointerN(): CPointer<*>? = throw MyException() + override fun int(): Int = throw MyException() + override fun longN(): Long? = throw MyException() + override fun double(): Double = throw MyException() +} + +class NotThrowing : MethodsWithThrows { + @Throws(MyException::class) constructor() {} + + override fun unit(): Unit {} + override fun nothing(): Nothing = throw MyException() + override fun nothingN(): Nothing? = null + override fun any(): Any = Any() + override fun anyN(): Any? = Any() + override fun block(): () -> Int = { 42 } + override fun blockN(): (() -> Int)? = null + override fun pointer(): CPointer<*> = 1L.toCPointer()!! + override fun pointerN(): CPointer<*>? = null + override fun int(): Int = 42 + override fun longN(): Long? = null + override fun double(): Double = 3.14 +} + +@Throws(Throwable::class) +fun testSwiftThrowing(methods: SwiftOverridableMethodsWithThrows) = with(methods) { + assertSwiftThrowing { unit() } + assertSwiftThrowing { nothing() } + assertSwiftThrowing { any() } + assertSwiftThrowing { block() } +} + +private inline fun assertSwiftThrowing(block: () -> Unit) = + assertFailsWith(block = block) + +@Throws(Throwable::class) +fun testSwiftNotThrowing(methods: SwiftOverridableMethodsWithThrows) = with(methods) { + unit() + assertEquals(42, any()) + assertEquals(17, block()()) +} + +@Throws(MyError::class) +fun callUnit(methods: SwiftOverridableMethodsWithThrows) = methods.unit() + +@Throws(Throwable::class) +fun callUnitCaller(caller: MethodsWithThrows.UnitCaller, methods: MethodsWithThrows) { + assertFailsWith { caller.call(methods) } +} + +interface ThrowsWithBridgeBase { + @Throws(MyException::class) + fun plusOne(x: Int): Any +} + +abstract class ThrowsWithBridge : ThrowsWithBridgeBase { + abstract override fun plusOne(x: Int): Int +} + +@Throws(Throwable::class) +fun testSwiftThrowing(test: ThrowsWithBridgeBase, flag: Boolean) { + assertFailsWith { + if (flag) { + test.plusOne(0) + } else { + val test1 = test as ThrowsWithBridge + val ignore: Int = test1.plusOne(1) + } + } +} + +@Throws(Throwable::class) +fun testSwiftNotThrowing(test: ThrowsWithBridgeBase) { + assertEquals(3, test.plusOne(2)) + val test1 = test as ThrowsWithBridge + assertEquals(4, test1.plusOne(3)) +} fun Any.same() = this diff --git a/backend.native/tests/framework/values/values.swift b/backend.native/tests/framework/values/values.swift index 77f27754ebc..6ca77d914b0 100644 --- a/backend.native/tests/framework/values/values.swift +++ b/backend.native/tests/framework/values/values.swift @@ -275,43 +275,112 @@ func testFunctions() throws { try assertEquals(actual: ValuesKt.multiply(int: 3, long: 2), expected: 6) } -class BridgeSwift : BridgeBase { - class Err : Error {} +class SwiftThrowing : SwiftOverridableMethodsWithThrows { + class E : Error {} - override func foo1() throws -> Any { - throw Err() + 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) } } func testExceptions() throws { - let bridge = Bridge() + func testThrowing(_ block: () throws -> Void) throws { + do { + try block() + } catch let error as NSError { + try assertTrue(error.kotlinException is MyException) + } + } + + try testThrowing { try ValuesKt.throwException(error: false) } do { - try bridge.foo1() + try ValuesKt.throwException(error: true) } catch let error as NSError { - try assertTrue(error.kotlinException is MyException) + try assertTrue(error.kotlinException is MyError) } + + try assertFalse(TestThrowingConstructorRelease.deinitialized) + try testThrowing { try TestThrowingConstructorRelease(doThrow: true) } + ValuesKt.gc() + try assertTrue(TestThrowingConstructorRelease.deinitialized) + + 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 bridge.foo2() - } catch let error as NSError { - try assertTrue(error.kotlinException is MyException) - } - do { - try bridge.foo3() - } catch let error as NSError { - try assertTrue(error.kotlinException is MyException) - } - do { - try bridge.foo4() - } catch let error as NSError { - try assertTrue(error.kotlinException is MyException) - } - do { - try ValuesKt.callFoo1(bridge: BridgeSwift()) - } catch let error as BridgeSwift.Err { - // Ok - } catch { - try assertTrue(false) + 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 {