diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index b4eb5d83dfc..7e83e5f78c8 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -177,15 +177,9 @@ tasks.named("clean", Delete.class) { tasks.named("run") { dependsOn(tasks.withType(KonanTest).matching { it.enabled }) - // Add framework tests - dependsOn(tasks.withType(FrameworkTest).matching { it.enabled }) dependsOn(tasks.withType(FileCheckTest).matching { it.enabled }) - dependsOn(tasks.withType(KonanTest).matching { it.enabled }) - // Add framework tests - dependsOn(tasks.withType(FrameworkTest).matching { it.enabled }) // Add regular gradle test tasks dependsOn(tasks.withType(Test).matching { it.enabled }) - dependsOn(tasks.withType(FileCheckTest).matching { it.enabled }) dependsOn(":kotlin-native:Interop:Indexer:check") dependsOn(":kotlin-native:Interop:StubGenerator:check") dependsOn(":native:kotlin-native-utils:check") @@ -1836,42 +1830,6 @@ standaloneTest("split_compilation_pipeline") { useGoldenData = true } -Task frameworkTest(String name, Closure configurator) { - return KotlinNativeTestKt.createTest(project, name, FrameworkTest) { task -> - configurator.delegate = task - UtilsKt.dependsOnDist(task) - configurator() - if (task.enabled) { - konanArtifacts { - task.frameworks.forEach { fr -> - framework(fr.name, targets: [target.name]) { - fr.sources.forEach { src -> - srcFiles src - } - baseDir "$testOutputFramework/${task.name}" - - fr.libraries.forEach { library -> - dependsOn konanArtifacts[library].getByTarget(target.name) - libraries { - klibFile konanArtifacts[library].getArtifactByTarget(target.name) - } - linkerOpts "-L${project.layout.buildDirectory.get().asFile}" - UtilsKt.dependsOnKonanBuildingTask(task, library, target) - } - - if (fr.isStatic) extraOpts "-Xstatic-framework" - extraOpts fr.opts - extraOpts project.globalTestArgs - - artifactName fr.artifact - } - UtilsKt.dependsOnDist(project.tasks.findByName("compileKonan${fr.name.capitalize()}${UtilsKt.getTestTargetSuffix(project)}")) - } - } - } - } -} - tasks.register("override_konan_properties0", KonanDriverTest) { disabled = isAggressiveGC // No need to test with different GC schedulers def overrides = PlatformInfo.isWindows() diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/FrameworkTest.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/FrameworkTest.kt deleted file mode 100644 index 6eb7cef2785..00000000000 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/FrameworkTest.kt +++ /dev/null @@ -1,204 +0,0 @@ -package org.jetbrains.kotlin - -import groovy.lang.Closure -import org.gradle.api.Action -import org.gradle.api.DefaultTask -import org.gradle.api.Task -import org.gradle.api.file.FileTree -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.TaskAction -import org.gradle.language.base.plugins.LifecycleBasePlugin - -import org.jetbrains.kotlin.konan.target.* -import java.io.File -import java.io.FileWriter -import java.io.Serializable -import java.nio.file.Path -import java.nio.file.Paths - -/** - * Test task for -produce framework testing. Requires a framework to be built by the Konan plugin - * with konanArtifacts { framework(frameworkName, targets: [ testTarget] ) } and a dependency set - * according to a pattern "compileKonan${frameworkName}". - * - * @property swiftSources Swift-language test sources that use a given framework - * @property frameworks names of frameworks - */ -open class FrameworkTest : DefaultTask(), KonanTestExecutable { - @Input - lateinit var swiftSources: List - - @Input - var swiftExtraOpts: List = emptyList() - - @Input - lateinit var frameworks: MutableList - - @Input - var codesign: Boolean = true - - @Input - val testOutput: String = project.testOutputFramework - - @Input @Optional - var expectedExitStatus: Int? = null - - /** - * Framework description. - * - * @param name is the framework name, - * @param sources framework sources, - * @param isStatic determines that framework is static - * @param artifact the name of the resulting artifact, - * @param library list of library dependency names, - * @param opts additional options for the compiler. - */ - class Framework( - val name: String, - var sources: List = emptyList(), - var isStatic: Boolean = false, - var artifact: String = name, - var libraries: List = emptyList(), - var opts: List = emptyList() - ) : Serializable // Required for Gradle when using Framework as task input. - - /** - * Used for the framework configuration in the task's closure. - */ - fun framework(name: String, closure: Closure): Framework { - val f = Framework(name).apply { - closure.delegate = this - closure.resolveStrategy = Closure.DELEGATE_FIRST - closure.call() - // map to file paths - sources = sources.toFiles(Language.Kotlin).map { it.path } - } - if (!::frameworks.isInitialized) { - frameworks = mutableListOf(f) - } else { - frameworks.add(f) - } - return f - } - - enum class Language(val extension: String) { - Kotlin(".kt"), ObjC(".m"), Swift(".swift") - } - - fun Language.filesFrom(dir: String): FileTree = project.fileTree(dir) { - // include only files with the language extension - include("*${this@filesFrom.extension}") - } - - fun List.toFiles(language: Language): List = - this.map { language.filesFrom(it) } - .flatMap { it.files } - - @get:Internal - override val executable: String - get() = Paths.get(testOutput, name, "swiftTestExecutable").toString() - - @Internal - override var doBeforeRun: Action? = null - - @Internal - override var doBeforeBuild: Action? = null - - @get:Internal - override val buildTasks: List - get() = frameworks.map { project.tasks.getByName("compileKonan${it.name}") } - - @Suppress("UnstableApiUsage") - override fun configure(config: Closure<*>): Task { - super.configure(config) - // set crossdist build dependency if custom konan.home wasn't set - this.dependsOnDist() - - // Set Gradle properties for the better navigation - group = LifecycleBasePlugin.VERIFICATION_GROUP - description = "Kotlin/Native test infrastructure task" - - check(::frameworks.isInitialized) { "Frameworks should be set" } - return this - } - - private fun buildTestExecutable() { - val frameworkParentDirPath = "$testOutput/$name/${project.testTarget.name}" - frameworks.forEach { framework -> - val frameworkArtifact = framework.artifact - val frameworkPath = "$frameworkParentDirPath/$frameworkArtifact.framework" - if (codesign) codesign(project, frameworkPath) - } - - // create a test provider and get main entry point - val provider = Paths.get(testOutput, name, "provider.swift") - FileWriter(provider.toFile()).use { writer -> - val providers = swiftSources.toFiles(Language.Swift) - .map { file -> - file.name.toString().removeSuffix(".swift").replaceFirstChar { it.uppercase() } - } - .map { "${it}Tests" } - - writer.write(""" - |// THIS IS AUTOGENERATED FILE - |// This method is invoked by the main routine to get a list of tests - |func registerProviders() { - | ${providers.joinToString("\n ") { "$it()" }} - |} - """.trimMargin()) - } - val testHome = project.file("framework").toPath() - val swiftMain = Paths.get(testHome.toString(), "main.swift").toString() - - // Compile swift sources - val sources = swiftSources.toFiles(Language.Swift) - .map { it.path } + listOf(provider.toString(), swiftMain) - val options = listOf( - "-g", - "-Xlinker", "-rpath", "-Xlinker", "@executable_path/Frameworks", - "-Xlinker", "-rpath", "-Xlinker", frameworkParentDirPath, - "-F", frameworkParentDirPath, - "-Xcc", "-Werror" // To fail compilation on warnings in framework header. - ) - // As of Xcode 13.1 swift passes wrong libclang_rt to simulator targets (similar to KT-47333). - // To workaround this problem, we explicitly provide the correct one. - val simulatorHack = if (project.testTargetConfigurables.targetTriple.isSimulator) { - project.platformManager.platform(project.testTarget).linker.provideCompilerRtLibrary("")?.let { - listOf("-Xlinker", it) - } ?: emptyList() - } else { - emptyList() - } - compileSwift(project, project.testTarget, sources, options + simulatorHack + swiftExtraOpts, Paths.get(executable)) - } - - @TaskAction - fun run() { - // Build test executable as a first action of the task before executing the test - buildTestExecutable() - doBeforeRun?.execute(this) - val testExecutable = Paths.get(executable) - val (stdOut, stdErr, exitCode) = runProcess( - executor = { - project.executor.execute { - it.execute(this) - workingDir = Paths.get(testOutput).toFile() - } - }, - executable = testExecutable.toString()) - - val testExecName = testExecutable.fileName - println(""" - |$testExecName - |stdout: $stdOut - |stderr: $stdErr - """.trimMargin()) - val timeoutMessage = if (exitCode == -1) { - "WARNING: probably a timeout\n" - } else "" - val expectedExitCode = expectedExitStatus?.takeUnless { project.compileOnlyTests } ?: 0 - check(exitCode == expectedExitCode) { "${timeoutMessage}Execution of $testExecName failed with exit code: $exitCode (expected exit code: $expectedExitCode)" } - } -} diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/compilation/CompilationToolCall.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/compilation/CompilationToolCall.kt index fe22626d65d..eb4db05e08a 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/compilation/CompilationToolCall.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/compilation/CompilationToolCall.kt @@ -189,6 +189,8 @@ internal fun invokeSwiftC( File(configs.absoluteTargetToolchain).resolveSibling("ExtraFrameworks").absolutePath } } catch (rpe: RunProcessException) { + if (rpe.exitCode == null) + throw rpe // Treat compiler timeouts as fatal errors return CompilationToolCallResult( exitCode = ExitCode.COMPILATION_ERROR, toolOutput = "ARGS: $args\nSTDOUT: ${rpe.stdout}\nSTDERR: ${rpe.stderr}", @@ -207,11 +209,7 @@ internal fun invokeSwiftC( internal fun codesign(path: String) { val executableAbsolutePath = "/usr/bin/codesign" val args = arrayOf("--verbose", "-s", "-", path) - try { - runProcess(executableAbsolutePath, *args) { - timeout = Duration.parse("30s") - } - } catch (rpe: RunProcessException) { - throw AssertionError("`$executableAbsolutePath ${args.joinToString(" ")}` failed with exitCode=${rpe.exitCode}: ${rpe.message}") + runProcess(executableAbsolutePath, *args) { + timeout = Duration.parse("30s") } }