From 8b4540f7e43737922b81ae30ffa93dda0493eae1 Mon Sep 17 00:00:00 2001 From: Pavel Kunyavskiy Date: Tue, 30 Nov 2021 15:48:25 +0300 Subject: [PATCH] [K/N] Add test for suspend function inheritance in ObjCExport ^KT-49395 --- .../tests/objcexport/coroutines.kt | 16 +++++++ .../tests/objcexport/coroutines.swift | 44 +++++++++++++++++++ .../tests/objcexport/expectedLazy.h | 30 +++++++++++++ .../expectedLazyLegacySuspendUnit.h | 30 +++++++++++++ .../tests/objcexport/expectedLazyNoGenerics.h | 30 +++++++++++++ 5 files changed, 150 insertions(+) diff --git a/kotlin-native/backend.native/tests/objcexport/coroutines.kt b/kotlin-native/backend.native/tests/objcexport/coroutines.kt index f247b5a8e92..6c5cc00c7c7 100644 --- a/kotlin-native/backend.native/tests/objcexport/coroutines.kt +++ b/kotlin-native/backend.native/tests/objcexport/coroutines.kt @@ -11,6 +11,7 @@ import kotlin.coroutines.intrinsics.* import kotlin.native.concurrent.isFrozen import kotlin.native.internal.ObjCErrorException import kotlin.test.* +import kotlin.reflect.* class CoroutineException : Throwable() @@ -185,14 +186,29 @@ class ThrowCancellationExceptionImpl : ThrowCancellationException() { } } +class suspendFunctionChild0: suspend () -> String { + override suspend fun invoke(): String = "child 0" +} + +class suspendFunctionChild1: suspend (String) -> String { + override suspend fun invoke(s: String): String = "$s 1" +} + fun getSuspendLambda0(): suspend () -> String = { "lambda 0" } private suspend fun suspendCallableReference0Target(): String = "callable reference 0" fun getSuspendCallableReference0(): suspend () -> String = ::suspendCallableReference0Target +fun getSuspendChild0() = suspendFunctionChild0() + fun getSuspendLambda1(): suspend (String) -> String = { "$it 1" } private suspend fun suspendCallableReference1Target(str: String): String = "$str 1" fun getSuspendCallableReference1(): suspend (String) -> String = ::suspendCallableReference1Target +fun getSuspendChild1() = suspendFunctionChild1() + suspend fun invoke1(block: suspend (Any?) -> Any?, argument: Any?): Any? = block(argument) + +fun getKSuspendCallableReference0(): KSuspendFunction0 = ::suspendCallableReference0Target +fun getKSuspendCallableReference1(): KSuspendFunction1 = ::suspendCallableReference1Target diff --git a/kotlin-native/backend.native/tests/objcexport/coroutines.swift b/kotlin-native/backend.native/tests/objcexport/coroutines.swift index 111352f72f4..5342ec4af86 100644 --- a/kotlin-native/backend.native/tests/objcexport/coroutines.swift +++ b/kotlin-native/backend.native/tests/objcexport/coroutines.swift @@ -441,8 +441,51 @@ private func testSuspendFunctionType1(f: KotlinSuspendFunction1) throws { private func testSuspendFunctionType() throws { try testSuspendFunctionType0(f: CoroutinesKt.getSuspendLambda0(), expectedResult: "lambda 0") try testSuspendFunctionType0(f: CoroutinesKt.getSuspendCallableReference0(), expectedResult: "callable reference 0") + try testSuspendFunctionType0(f: CoroutinesKt.getSuspendChild0(), expectedResult: "child 0") try testSuspendFunctionType1(f: CoroutinesKt.getSuspendLambda1()) try testSuspendFunctionType1(f: CoroutinesKt.getSuspendCallableReference1()) + try testSuspendFunctionType1(f: CoroutinesKt.getSuspendChild1()) +} + +private func testKSuspendFunctionType0(f: KotlinKSuspendFunction0, expectedResult: String) throws { + try assertTrue((f as AnyObject) is KotlinKSuspendFunction0) + + var result: String? = nil + var error: Error? = nil + var completionCalled = 0 + + f.invoke { _result, _error in + completionCalled += 1 + result = _result as? String + error = _error + } + + try assertEquals(actual: completionCalled, expected: 1) + try assertEquals(actual: result, expected: expectedResult) + try assertNil(error) +} + +private func testKSuspendFunctionType1(f: KotlinKSuspendFunction1) throws { + try assertTrue((f as AnyObject) is KotlinKSuspendFunction1) + + var result: String? = nil + var error: Error? = nil + var completionCalled = 0 + + f.invoke(p1: "suspend function type") { _result, _error in + completionCalled += 1 + result = _result as? String + error = _error + } + + try assertEquals(actual: completionCalled, expected: 1) + try assertEquals(actual: result, expected: "suspend function type 1") + try assertNil(error) +} + +private func testKSuspendFunctionType() throws { + try testKSuspendFunctionType0(f: CoroutinesKt.getKSuspendCallableReference0(), expectedResult: "callable reference 0") + try testKSuspendFunctionType1(f: CoroutinesKt.getKSuspendCallableReference1()) } private func testSuspendFunctionSwiftImpl() throws { @@ -480,6 +523,7 @@ class CoroutinesTests : SimpleTestProvider { test("TestImplicitThrows1", testImplicitThrows1) test("TestImplicitThrows2", testImplicitThrows2) test("TestSuspendFunctionType", testSuspendFunctionType) + test("TestKSuspendFunctionType", testSuspendFunctionType) test("TestSuspendFunctionSwiftImpl", testSuspendFunctionSwiftImpl) } } \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h index 07ac948fbca..692afa4a7f8 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazy.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazy.h @@ -279,6 +279,32 @@ __attribute__((swift_name("ThrowCancellationExceptionImpl"))) - (void)throwCancellationExceptionWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)"))); @end; +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("suspendFunctionChild0"))) +@interface KtsuspendFunctionChild0 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)invokeWithCompletionHandler:(void (^)(NSString * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("invoke(completionHandler:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("suspendFunctionChild1"))) +@interface KtsuspendFunctionChild1 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)invokeP1:(NSString *)s completionHandler:(void (^)(NSString * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("invoke(p1:completionHandler:)"))); +@end; + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("CoroutinesKt"))) @interface KtCoroutinesKt : KtBase @@ -338,14 +364,18 @@ __attribute__((swift_name("CoroutinesKt"))) + (void)throwCancellationExceptionWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)"))); + (id)getSuspendLambda0 __attribute__((swift_name("getSuspendLambda0()"))); + (id)getSuspendCallableReference0 __attribute__((swift_name("getSuspendCallableReference0()"))); ++ (KtsuspendFunctionChild0 *)getSuspendChild0 __attribute__((swift_name("getSuspendChild0()"))); + (id)getSuspendLambda1 __attribute__((swift_name("getSuspendLambda1()"))); + (id)getSuspendCallableReference1 __attribute__((swift_name("getSuspendCallableReference1()"))); ++ (KtsuspendFunctionChild1 *)getSuspendChild1 __attribute__((swift_name("getSuspendChild1()"))); /** @note This method converts instances of CancellationException to errors. Other uncaught Kotlin exceptions are fatal. */ + (void)invoke1Block:(id)block argument:(id _Nullable)argument completionHandler:(void (^)(id _Nullable_result, NSError * _Nullable))completionHandler __attribute__((swift_name("invoke1(block:argument:completionHandler:)"))); ++ (id)getKSuspendCallableReference0 __attribute__((swift_name("getKSuspendCallableReference0()"))); ++ (id)getKSuspendCallableReference1 __attribute__((swift_name("getKSuspendCallableReference1()"))); @end; __attribute__((swift_name("DeallocRetainBase"))) diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h index 55f1cd0050f..f180b6934b0 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyLegacySuspendUnit.h @@ -279,6 +279,32 @@ __attribute__((swift_name("ThrowCancellationExceptionImpl"))) - (void)throwCancellationExceptionWithCompletionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)"))); @end; +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("suspendFunctionChild0"))) +@interface KtsuspendFunctionChild0 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)invokeWithCompletionHandler:(void (^)(NSString * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("invoke(completionHandler:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("suspendFunctionChild1"))) +@interface KtsuspendFunctionChild1 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)invokeP1:(NSString *)s completionHandler:(void (^)(NSString * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("invoke(p1:completionHandler:)"))); +@end; + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("CoroutinesKt"))) @interface KtCoroutinesKt : KtBase @@ -338,14 +364,18 @@ __attribute__((swift_name("CoroutinesKt"))) + (void)throwCancellationExceptionWithCompletionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)"))); + (id)getSuspendLambda0 __attribute__((swift_name("getSuspendLambda0()"))); + (id)getSuspendCallableReference0 __attribute__((swift_name("getSuspendCallableReference0()"))); ++ (KtsuspendFunctionChild0 *)getSuspendChild0 __attribute__((swift_name("getSuspendChild0()"))); + (id)getSuspendLambda1 __attribute__((swift_name("getSuspendLambda1()"))); + (id)getSuspendCallableReference1 __attribute__((swift_name("getSuspendCallableReference1()"))); ++ (KtsuspendFunctionChild1 *)getSuspendChild1 __attribute__((swift_name("getSuspendChild1()"))); /** @note This method converts instances of CancellationException to errors. Other uncaught Kotlin exceptions are fatal. */ + (void)invoke1Block:(id)block argument:(id _Nullable)argument completionHandler:(void (^)(id _Nullable_result, NSError * _Nullable))completionHandler __attribute__((swift_name("invoke1(block:argument:completionHandler:)"))); ++ (id)getKSuspendCallableReference0 __attribute__((swift_name("getKSuspendCallableReference0()"))); ++ (id)getKSuspendCallableReference1 __attribute__((swift_name("getKSuspendCallableReference1()"))); @end; __attribute__((swift_name("DeallocRetainBase"))) diff --git a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h index cffdf842ac8..b550a276e67 100644 --- a/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h +++ b/kotlin-native/backend.native/tests/objcexport/expectedLazyNoGenerics.h @@ -279,6 +279,32 @@ __attribute__((swift_name("ThrowCancellationExceptionImpl"))) - (void)throwCancellationExceptionWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)"))); @end; +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("suspendFunctionChild0"))) +@interface KtsuspendFunctionChild0 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)invokeWithCompletionHandler:(void (^)(NSString * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("invoke(completionHandler:)"))); +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("suspendFunctionChild1"))) +@interface KtsuspendFunctionChild1 : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); + +/** + @note This method converts instances of CancellationException to errors. + Other uncaught Kotlin exceptions are fatal. +*/ +- (void)invokeP1:(NSString *)s completionHandler:(void (^)(NSString * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("invoke(p1:completionHandler:)"))); +@end; + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("CoroutinesKt"))) @interface KtCoroutinesKt : KtBase @@ -338,14 +364,18 @@ __attribute__((swift_name("CoroutinesKt"))) + (void)throwCancellationExceptionWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)"))); + (id)getSuspendLambda0 __attribute__((swift_name("getSuspendLambda0()"))); + (id)getSuspendCallableReference0 __attribute__((swift_name("getSuspendCallableReference0()"))); ++ (KtsuspendFunctionChild0 *)getSuspendChild0 __attribute__((swift_name("getSuspendChild0()"))); + (id)getSuspendLambda1 __attribute__((swift_name("getSuspendLambda1()"))); + (id)getSuspendCallableReference1 __attribute__((swift_name("getSuspendCallableReference1()"))); ++ (KtsuspendFunctionChild1 *)getSuspendChild1 __attribute__((swift_name("getSuspendChild1()"))); /** @note This method converts instances of CancellationException to errors. Other uncaught Kotlin exceptions are fatal. */ + (void)invoke1Block:(id)block argument:(id _Nullable)argument completionHandler:(void (^)(id _Nullable_result, NSError * _Nullable))completionHandler __attribute__((swift_name("invoke1(block:argument:completionHandler:)"))); ++ (id)getKSuspendCallableReference0 __attribute__((swift_name("getKSuspendCallableReference0()"))); ++ (id)getKSuspendCallableReference1 __attribute__((swift_name("getKSuspendCallableReference1()"))); @end; __attribute__((swift_name("DeallocRetainBase")))