[K/N][Tests] Migrate first Apple-specific test

^KT-61259
This commit is contained in:
Vladimir Sukharev
2024-01-16 23:54:43 +01:00
parent e91e5db0ce
commit 6e2df0e086
11 changed files with 100 additions and 57 deletions
+30
View File
@@ -0,0 +1,30 @@
/*
* 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.
*/
// TARGET_BACKEND: NATIVE
// DISABLE_NATIVE: isAppleTarget=false
// There is no GameController on watchOS.
// DISABLE_NATIVE: targetFamily=WATCHOS
// MODULE: cinterop
// FILE: kt59167.def
language=Objective-C
---
#import <GameController/GCDevice.h>
// We only need to touch the problematic header to trigger the problem,
// so actual code does not matter.
id<GCDevice> dummy() {
return nil;
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlin.test.*
import kt59167.*
fun box(): String {
assertNull(dummy())
return "OK"
}
@@ -1231,9 +1231,6 @@ if (PlatformInfo.isAppleTarget(project)) {
it.defFile 'interop/objc/objCAction/objclib.def'
it.headers "$projectDir/interop/objc/objCAction/objclib.h"
}
createInterop("kt59167") {
it.defFile 'interop/kt59167/kt59167.def'
}
createInterop("overridabilityCondition") {
it.defFile 'interop/objc/overridabilityCondition/lib.def'
it.headers "$projectDir/interop/objc/overridabilityCondition/lib.h"
@@ -1850,13 +1847,6 @@ if (PlatformInfo.isAppleTarget(project)) {
UtilsKt.dependsOnPlatformLibs(it)
}
interopTest("interop_kt59167") {
// There is no GameController on watchOS.
enabled = target.family != Family.WATCHOS
source = 'interop/kt59167/main.kt'
interop = 'kt59167'
}
interopTest("interop_objc_kt63423_dispose_on_main_stress") {
// Test depends on macOS-specific AppKit
enabled = (project.testTarget == 'macos_x64' || project.testTarget == 'macos_arm64' || project.testTarget == null)
@@ -1,9 +0,0 @@
language=Objective-C
---
#import <GameController/GCDevice.h>
// We only need to touch the problematic header to trigger the problem,
// so actual code does not matter.
id<GCDevice> dummy() {
return nil;
}
@@ -1,11 +0,0 @@
/*
* 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 kotlin.test.*
import kt59167.*
fun main() {
assertNull(dummy())
}
@@ -4856,6 +4856,12 @@ public class FirNativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTe
runTest("compiler/testData/codegen/box/cinterop/kt57640.kt");
}
@Test
@TestMetadata("kt59167.kt")
public void testKt59167() throws Exception {
runTest("compiler/testData/codegen/box/cinterop/kt59167.kt");
}
@Test
@TestMetadata("kt63048.kt")
public void testKt63048() throws Exception {
@@ -4966,6 +4966,12 @@ public class FirNativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenB
runTest("compiler/testData/codegen/box/cinterop/kt57640.kt");
}
@Test
@TestMetadata("kt59167.kt")
public void testKt59167() throws Exception {
runTest("compiler/testData/codegen/box/cinterop/kt59167.kt");
}
@Test
@TestMetadata("kt63048.kt")
public void testKt63048() throws Exception {
@@ -4746,6 +4746,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/cinterop/kt57640.kt");
}
@Test
@TestMetadata("kt59167.kt")
public void testKt59167() throws Exception {
runTest("compiler/testData/codegen/box/cinterop/kt59167.kt");
}
@Test
@TestMetadata("kt63048.kt")
public void testKt63048() throws Exception {
@@ -4857,6 +4857,12 @@ public class NativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenBoxT
runTest("compiler/testData/codegen/box/cinterop/kt57640.kt");
}
@Test
@TestMetadata("kt59167.kt")
public void testKt59167() throws Exception {
runTest("compiler/testData/codegen/box/cinterop/kt59167.kt");
}
@Test
@TestMetadata("kt63048.kt")
public void testKt63048() throws Exception {
@@ -29,7 +29,7 @@ internal sealed interface TestCompilationResult<A : TestCompilationArtifact> {
companion object {
fun <A : TestCompilationArtifact> TestCompilationResult<A>.assertSuccess(): Success<A> = when (this) {
is Success -> this
is UnexpectedFailure -> fail { describeFailure() }
is UnexpectedFailure -> throw CompilationToolException(describeFailure())
is CompilationToolFailure -> throw CompilationToolException(describeFailure())
is DependencyFailures -> fail { describeDependencyFailures() }
}
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.konan.test.blackbox.support.group
import org.jetbrains.kotlin.konan.test.blackbox.support.ClassLevelProperty
// Deprecated: Use test directives instead:
// `IGNORE_BACKEND: NATIVE`, `IGNORE_BACKEND_K1: NATIVE`, `IGNORE_BACKEND_K2: NATIVE` if test fails in any tets config
// `IGNORE_NATIVE`, `IGNORE_NATIVE_K1`, `IGNORE_NATIVE_K2` with a property matcher, for usual easy fails
// `DISABLE_NATIVE`, `DISABLE_NATIVE_K1`, `DISABLE_NATIVE_K2` in case compiler crashes within JVM
// `IGNORE_BACKEND: NATIVE`, `IGNORE_BACKEND_K1: NATIVE`, `IGNORE_BACKEND_K2: NATIVE` if test fails in any test config
// `IGNORE_NATIVE`, `IGNORE_NATIVE_K1`, `IGNORE_NATIVE_K2` with/without a property matcher, for usual easy fails (please provide issue link)
// `DISABLE_NATIVE`, `DISABLE_NATIVE_K1`, `DISABLE_NATIVE_K2` with/without a property matcher, in case compiler crashes within JVM, or compilation/execution would be a resource waste
@Target(AnnotationTarget.CLASS)
internal annotation class DisabledTests(
val sourceLocations: Array<String>
@@ -17,8 +17,8 @@ internal annotation class DisabledTests(
// @DisabledTestsIfProperty(...) is intended primarily to turn off tests in bulk to reduce pressure on CI infrastructure for certain targets
// To mark failed tests, please use the following test directives instead:
// `IGNORE_NATIVE`, `IGNORE_NATIVE_K1`, `IGNORE_NATIVE_K2` with a property matcher, for usual easy fails
// `DISABLE_NATIVE`, `DISABLE_NATIVE_K1`, `DISABLE_NATIVE_K2` for overcomplicated property combinations, or in case compiler crashes within JVM
// `IGNORE_NATIVE`, `IGNORE_NATIVE_K1`, `IGNORE_NATIVE_K2` with/without a property matcher, for usual easy fails (please provide issue link)
// `DISABLE_NATIVE`, `DISABLE_NATIVE_K1`, `DISABLE_NATIVE_K2` with/without a property matcher, in case compiler crashes within JVM, or compilation/execution would be a resource waste
@Target(AnnotationTarget.CLASS)
internal annotation class DisabledTestsIfProperty(
val sourceLocations: Array<String>,
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.konan.target.Family
import org.jetbrains.kotlin.konan.test.blackbox.support.*
import org.jetbrains.kotlin.konan.test.blackbox.support.TestCase.WithTestRunnerExtras
import org.jetbrains.kotlin.konan.test.blackbox.support.TestDirectives.ASSERTIONS_MODE
@@ -47,6 +48,7 @@ import org.jetbrains.kotlin.test.InTextDirectivesUtils.*
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.IGNORE_BACKEND
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.IGNORE_BACKEND_K1
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.IGNORE_BACKEND_K2
import org.jetbrains.kotlin.test.directives.model.StringDirective
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertTrue
import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -155,7 +157,7 @@ private class ExtTestDataFile(
val isRelevant: Boolean =
isCompatibleTarget(TargetBackend.NATIVE, testDataFile) // Checks TARGET_BACKEND/DONT_TARGET_EXACT_BACKEND directives.
&& !isDisabledNative(pipelineType, structure.directives)
&& !settings.isDisabledNative(structure.directives)
&& testDataFileSettings.languageSettings.none { it in INCOMPATIBLE_LANGUAGE_SETTINGS }
&& INCOMPATIBLE_DIRECTIVES.none { it in structure.directives }
&& structure.directives[API_VERSION_DIRECTIVE] !in INCOMPATIBLE_API_VERSIONS
@@ -893,14 +895,6 @@ private class ExtTestDataFileStructureFactory(parentDisposable: Disposable) : Te
}
}
internal fun isDisabledNative(pipelineType: PipelineType, directives: Directives): Boolean {
return when (pipelineType) {
PipelineType.K1 -> directives.contains(DISABLE_NATIVE.name) || directives.contains(DISABLE_NATIVE_K1.name)
PipelineType.K2 -> directives.contains(DISABLE_NATIVE.name) || directives.contains(DISABLE_NATIVE_K2.name)
PipelineType.DEFAULT -> directives.contains(DISABLE_NATIVE.name)
}
}
internal fun Settings.isIgnoredTarget(testDataFile: File): Boolean {
val disposable = Disposer.newDisposable("Disposable for ExtTestCaseGroupProvider.isIgnoredTarget")
try {
@@ -934,24 +928,27 @@ private fun Settings.isIgnoredWithIGNORE_BACKEND(directives: Directives): Boolea
return false
}
private val TARGET_FAMILY = "targetFamily"
private val IS_APPLE_TARGET = "isAppleTarget"
private val CACHE_MODE_NAMES = CacheMode.Alias.entries.map { it.name }
private val TEST_MODE_NAMES = TestMode.entries.map { it.name }
private val OPTIMIZATION_MODE_NAMES = OptimizationMode.entries.map { it.name }
private val GC_TYPE_NAMES = GCType.entries.map { it.name }
private val FAMILY_NAMES = Family.entries.map { it.name }
private val BOOLEAN_NAMES = listOf(true.toString(), false.toString())
private fun Settings.isIgnoredWithIGNORE_NATIVE(
directives: Directives,
): Boolean {
val directiveValues = buildList {
directives.listValues(IGNORE_NATIVE.name)?.let { addAll(it) }
when (get<PipelineType>()) {
PipelineType.K1 -> directives.listValues(IGNORE_NATIVE_K1.name)?.let { addAll(it) }
PipelineType.K2 -> directives.listValues(IGNORE_NATIVE_K2.name)?.let { addAll(it) }
else -> {}
}
}
// Boolean evaluation of expressions like `property1=value1 && property2=value2`
private fun Settings.isDisabledNative(directives: Directives) =
evaluate(getDirectiveValues(directives, DISABLE_NATIVE, DISABLE_NATIVE_K1, DISABLE_NATIVE_K2))
private fun Settings.isIgnoredWithIGNORE_NATIVE(directives: Directives) =
evaluate(getDirectiveValues(directives, IGNORE_NATIVE, IGNORE_NATIVE_K1, IGNORE_NATIVE_K2))
// Evaluation of conjunction of boolean expressions like `property1=value1 && property2=value2`.
// Any null element makes whole result as `true`.
private fun Settings.evaluate(directiveValues: List<String?>): Boolean {
directiveValues.forEach {
if (it == null)
return true // Directive without value is treated as unconditional
val split = it.split("&&")
val booleanList = split.map {
val matchResult = "(.+)=(.+)".toRegex().find(it.trim())
@@ -963,6 +960,8 @@ private fun Settings.isIgnoredWithIGNORE_NATIVE(
ClassLevelProperty.OPTIMIZATION_MODE.shortName -> get<OptimizationMode>().name to OPTIMIZATION_MODE_NAMES
ClassLevelProperty.TEST_TARGET.shortName -> get<KotlinNativeTargets>().testTarget.name to null
ClassLevelProperty.GC_TYPE.shortName -> get<GCType>().name to GC_TYPE_NAMES
TARGET_FAMILY -> get<KotlinNativeTargets>().testTarget.family.name to FAMILY_NAMES
IS_APPLE_TARGET -> get<KotlinNativeTargets>().testTarget.family.isAppleFamily.toString() to BOOLEAN_NAMES
else -> throw AssertionError("ClassLevelProperty name: $propName is not yet supported in IGNORE_NATIVE* test directives.")
}
val valueFromTestDirective = matchResult.groups[2]?.value!!
@@ -981,6 +980,26 @@ private fun Settings.isIgnoredWithIGNORE_NATIVE(
return false
}
// Returns list of relevant directive values.
// Null is added to result list in case the directive given without value.
private fun Settings.getDirectiveValues(
directives: Directives,
directiveAllPipelineTypes: StringDirective,
directiveK1: StringDirective,
directiveK2: StringDirective
): List<String?> = buildList {
fun extract(directives: Directives, directive: StringDirective) {
if (directives.contains(directive.name))
directives.listValues(directive.name)?.let { addAll(it) } ?: add(null)
}
extract(directives, directiveAllPipelineTypes)
when (get<PipelineType>()) {
PipelineType.K1 -> extract(directives, directiveK1)
PipelineType.K2 -> extract(directives, directiveK2)
else -> {}
}
}
private val KtFile.packageFqNameForKLib: FqName
get() = when (name.substringAfterLast(".")) {
"kt" -> packageFqName