From 0d8960088ea96484214e4ac6b84579ba42f1d8f8 Mon Sep 17 00:00:00 2001 From: Pavel Punegov Date: Tue, 7 Nov 2023 11:56:08 +0000 Subject: [PATCH] [K/N] XCTest launcher for CompilerOutput's TEST_BUNDLE This change adds a Native Obj-C launcher that implements XCTestCase and overrides defaultTestSuite property to provide XCTest with generated test suites and test cases. The defaultTestSuite method is essentially a starting point with runtime initialization. It requires a `Konan_create_testSuite()` method to be implemented in a Kotlin library that returns a list of XCTestCases. This launcher should be compiled as a TEST_BUNDLE to be used then with XCTest. This commit is a part of ^KT-58928 Co-authored-by: Alexander Shabalin Merge-request: KT-MR-12841 Merged-by: Pavel Punegov --- .../kotlin/backend/konan/CompilerOutput.kt | 5 +++- .../kotlin/backend/konan/KonanConfig.kt | 3 ++ kotlin-native/runtime/build.gradle.kts | 9 ++++++ kotlin-native/runtime/src/main/cpp/Runtime.h | 1 + .../src/xctest_launcher/cpp/TestLauncher.h | 20 +++++++++++++ .../src/xctest_launcher/cpp/TestLauncher.mm | 28 +++++++++++++++++++ 6 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 kotlin-native/runtime/src/xctest_launcher/cpp/TestLauncher.h create mode 100644 kotlin-native/runtime/src/xctest_launcher/cpp/TestLauncher.mm diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt index 30c0fa9469c..ffefcd296e8 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt @@ -93,11 +93,14 @@ private fun collectLlvmModules(generationState: NativeGenerationState, generated val additionalBitcodeFilesToLink = generationState.llvm.additionalProducedBitcodeFiles val exceptionsSupportNativeLibrary = listOf(config.exceptionsSupportNativeLibrary) .takeIf { config.produce == CompilerOutputKind.DYNAMIC_CACHE }.orEmpty() + val xcTestRunnerNativeLibrary = listOf(config.xcTestLauncherNativeLibrary) + .takeIf { config.produce == CompilerOutputKind.TEST_BUNDLE }.orEmpty() val additionalBitcodeFiles = nativeLibraries + generatedBitcodeFiles + additionalBitcodeFilesToLink + bitcodeLibraries + - exceptionsSupportNativeLibrary + exceptionsSupportNativeLibrary + + xcTestRunnerNativeLibrary val runtimeNativeLibraries = config.runtimeNativeLibraries diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index d614ad9edf1..f751c41b6f1 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -405,6 +405,9 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration internal val objCNativeLibrary: String = File(distribution.defaultNatives(target)).child("objc.bc").absolutePath + internal val xcTestLauncherNativeLibrary: String = + File(distribution.defaultNatives(target)).child("xctest_launcher.bc").absolutePath + internal val exceptionsSupportNativeLibrary: String = File(distribution.defaultNatives(target)).child("exceptionsSupport.bc").absolutePath diff --git a/kotlin-native/runtime/build.gradle.kts b/kotlin-native/runtime/build.gradle.kts index 31e98a1a6f5..778efa482d1 100644 --- a/kotlin-native/runtime/build.gradle.kts +++ b/kotlin-native/runtime/build.gradle.kts @@ -360,6 +360,15 @@ bitcode { } } + module("xctest_launcher") { + headersDirs.from(files("src/main/cpp")) + + sourceSets { + main {} + } + onlyIf { target.family.isAppleFamily } + } + testsGroup("custom_alloc_runtime_tests") { testedModules.addAll("custom_alloc") testSupportModules.addAll("main", "mm", "common_alloc", "common_gc", "common_gcScheduler", "manual_gcScheduler", "concurrent_ms_gc_custom", "objc") diff --git a/kotlin-native/runtime/src/main/cpp/Runtime.h b/kotlin-native/runtime/src/main/cpp/Runtime.h index b7b073fc55b..4cb16be7cba 100644 --- a/kotlin-native/runtime/src/main/cpp/Runtime.h +++ b/kotlin-native/runtime/src/main/cpp/Runtime.h @@ -7,6 +7,7 @@ #define RUNTIME_RUNTIME_H #include "Porting.h" +#include "Memory.h" #ifdef __cplusplus extern "C" { diff --git a/kotlin-native/runtime/src/xctest_launcher/cpp/TestLauncher.h b/kotlin-native/runtime/src/xctest_launcher/cpp/TestLauncher.h new file mode 100644 index 00000000000..282a5665187 --- /dev/null +++ b/kotlin-native/runtime/src/xctest_launcher/cpp/TestLauncher.h @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +/** + * These are stub declarations from XCTest.framework needed for the launcher compilation. + * It makes possible to compile it without dependency on the framework, while the + * final build of the bundle should be done with a real XCTest.framework library. + */ + +@interface XCTestCase +@end + +@interface XCTestSuite +@end + +@interface XCTestCase (XCTestSuiteExtensions) +@property (class, readonly) XCTestSuite *defaultTestSuite; +@end \ No newline at end of file diff --git a/kotlin-native/runtime/src/xctest_launcher/cpp/TestLauncher.mm b/kotlin-native/runtime/src/xctest_launcher/cpp/TestLauncher.mm new file mode 100644 index 00000000000..c1c50cfa15c --- /dev/null +++ b/kotlin-native/runtime/src/xctest_launcher/cpp/TestLauncher.mm @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +#import "Memory.h" +#import "ObjCExport.h" +#import "TestLauncher.h" + +extern "C" OBJ_GETTER0(Konan_create_testSuite); + +@interface XCTestLauncher : XCTestCase +@end + +@implementation XCTestLauncher +/** + * Test suites factory. + * + * This is a starting point for XCTest to get test suites with test cases. + * K/N dynamically adds test suites for Kotlin tests. + * See `setupXCTestSuite` Kotlin method. + */ ++ (id)defaultTestSuite { + kotlin::CalledFromNativeGuard guard; + ObjHolder holder; + return Kotlin_ObjCExport_refToObjC(Konan_create_testSuite(holder.slot())); +} +@end