diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleAndroidTest.java b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleAndroidTest.java index 8766a7f0ea8..a24f86e6929 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleAndroidTest.java +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleAndroidTest.java @@ -18,7 +18,6 @@ import java.lang.annotation.Target; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @GradleTestVersions -@OsCondition @AndroidTestVersions @ParameterizedTest(name = "AGP {1} with {0}: {displayName}") @ArgumentsSource(GradleAndAgpArgumentsProvider.class) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleTest.java b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleTest.java index f44dd266c59..9cf42674f87 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleTest.java +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleTest.java @@ -17,7 +17,6 @@ import java.lang.annotation.Target; // Workaround for https://youtrack.jetbrains.com/issue/IDEA-265284 @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) -@OsCondition @GradleTestVersions @ParameterizedTest(name = "{0}: {displayName}") @ArgumentsSource(GradleArgumentsProvider.class) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleWithJdkTest.java b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleWithJdkTest.java index f50a60c70f6..b0ea2e877d9 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleWithJdkTest.java +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/java/org/jetbrains/kotlin/gradle/testbase/GradleWithJdkTest.java @@ -18,7 +18,6 @@ import java.lang.annotation.Target; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @GradleTestVersions -@OsCondition @JdkVersions @ParameterizedTest(name = "{1} with {0}: {displayName}") @ArgumentsSource(GradleAndJdkArgumentsProvider.class) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt index 6c16a4d2857..68831472742 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.gradle import org.gradle.api.JavaVersion import org.gradle.api.logging.LogLevel -import org.gradle.api.logging.configuration.WarningMode import org.gradle.testkit.runner.BuildResult import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.tasks.USING_JVM_INCREMENTAL_COMPILATION_MESSAGE @@ -28,7 +27,6 @@ import org.jetbrains.kotlin.gradle.util.checkedReplace import org.jetbrains.kotlin.gradle.util.testResolveAllConfigurations import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.OS import java.nio.file.Files import java.util.zip.ZipFile @@ -1030,7 +1028,7 @@ open class Kapt3IT : Kapt3BaseIT() { @DisplayName("KT-52392: Setup with different windows disks does not fail configuration") @GradleTest - @EnabledOnOs(OS.WINDOWS) + @OsCondition(supportedOn = [OS.WINDOWS], enabledOnCI = [OS.WINDOWS]) fun testDifferentDisksSetupDoesNotFailConfiguration(gradleVersion: GradleVersion) { project("simple".withPrefix, gradleVersion) { fun findAnotherRoot() = ('A'..'Z').first { !projectPath.root.startsWith(it.toString()) } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/AppleSiliconIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/AppleSiliconIT.kt index 74f19de9a91..790ff0ec967 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/AppleSiliconIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/AppleSiliconIT.kt @@ -10,11 +10,10 @@ import org.jetbrains.kotlin.gradle.testbase.* import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.OS import kotlin.test.fail -@EnabledOnOs(OS.MAC, disabledReason = "Test requires MacOS host") +@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC]) @DisplayName("Tests for Apple Silicon builds") @NativeGradlePluginTests class AppleSiliconIT : KGPBaseTest() { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeLibraryDslIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeLibraryDslIT.kt index 81a38fb9d0f..5bc463dba2d 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeLibraryDslIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeLibraryDslIT.kt @@ -9,7 +9,6 @@ import org.gradle.api.logging.LogLevel import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.testbase.* import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.OS import kotlin.io.path.appendText @@ -98,7 +97,7 @@ class NativeLibraryDslIT : KGPBaseTest() { } } - @EnabledOnOs(OS.MAC) + @OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC]) @DisplayName("Links release XCFramework from two gradle modules") @GradleTest fun shouldLinkXCFrameworkFromTwoModules(gradleVersion: GradleVersion) { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeLibraryDslWithCocoapodsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeLibraryDslWithCocoapodsIT.kt index 1d8d3d6adae..96ceca38567 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeLibraryDslWithCocoapodsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeLibraryDslWithCocoapodsIT.kt @@ -8,11 +8,10 @@ package org.jetbrains.kotlin.gradle.native import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.testbase.* import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.OS import kotlin.io.path.appendText -@EnabledOnOs(OS.MAC) +@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC]) @DisplayName("Tests for K/N with cocoapods") @NativeGradlePluginTests class NativeLibraryDslWithCocoapodsIT : KGPBaseTest() { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeXcodeSimulatorTestsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeXcodeSimulatorTestsIT.kt index 5f128190425..75edc672aa2 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeXcodeSimulatorTestsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeXcodeSimulatorTestsIT.kt @@ -12,14 +12,13 @@ import org.jetbrains.kotlin.gradle.utils.Xcode import org.jetbrains.kotlin.konan.target.KonanTarget import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.OS import java.io.File import kotlin.test.assertEquals @DisplayName("tests for the K/N XCode simulator test infrastructure") @NativeGradlePluginTests -@EnabledOnOs(OS.MAC) +@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC]) class NativeXcodeSimulatorTestsIT : KGPBaseTest() { private val defaultIosSimulator by lazy { val xcode = Xcode ?: error("XCode is expected to be defined") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/XCFrameworkIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/XCFrameworkIT.kt index 9493bc415a9..db1765b90b0 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/XCFrameworkIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/XCFrameworkIT.kt @@ -10,10 +10,9 @@ import org.jetbrains.kotlin.gradle.testbase.* import org.jetbrains.kotlin.gradle.util.replaceFirst import org.jetbrains.kotlin.gradle.util.replaceText import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.OS -@EnabledOnOs(OS.MAC) +@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC]) @DisplayName("Tests for K/N with apple XCFramework") @NativeGradlePluginTests class XCFrameworkIT : KGPBaseTest() { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/KGPBaseTest.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/KGPBaseTest.kt index bea668f710d..0cfb2c8e68b 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/KGPBaseTest.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/KGPBaseTest.kt @@ -28,6 +28,7 @@ import java.nio.file.Path @TestInstance(TestInstance.Lifecycle.PER_CLASS) @WithMuteInDatabase @TestDataPath("\$CONTENT_ROOT/resources/testProject") +@OsCondition abstract class KGPBaseTest { open val defaultBuildOptions = BuildOptions() diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/argumentProviders.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/argumentProviders.kt index 644147d1f64..deac4e4e5d6 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/argumentProviders.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/argumentProviders.kt @@ -23,6 +23,35 @@ annotation class GradleTestVersions( val additionalVersions: Array = [] ) +inline fun findAnnotation(context: ExtensionContext): T { + var nextSuperclass: Class<*>? = context.testClass.get().superclass + val superClassSequence = if (nextSuperclass != null) { + generateSequence { + val currentSuperclass = nextSuperclass + nextSuperclass = nextSuperclass?.superclass + currentSuperclass + } + } else { + emptySequence() + } + + return sequenceOf( + context.testMethod.orElse(null), + context.testClass.orElse(null) + ) + .filterNotNull() + .plus(superClassSequence) + .mapNotNull { declaration -> + declaration.annotations.firstOrNull { it is T } + } + .firstOrNull() as T? + ?: context.testMethod.get().annotations + .mapNotNull { annotation -> + annotation.annotationClass.annotations.firstOrNull { it is T } + } + .first() as T +} + open class GradleArgumentsProvider : ArgumentsProvider { override fun provideArguments( context: ExtensionContext @@ -48,34 +77,6 @@ open class GradleArgumentsProvider : ArgumentsProvider { .map { Arguments.of(it) } .asStream() } - - inline fun findAnnotation(context: ExtensionContext): T { - var nextSuperclass: Class<*>? = context.testClass.get().superclass - val superClassSequence = if (nextSuperclass != null) { - generateSequence { - val currentSuperclass = nextSuperclass - nextSuperclass = nextSuperclass?.superclass - currentSuperclass - } - } else { - emptySequence() - } - - return sequenceOf( - context.testMethod.get(), - context.testClass.get() - ) - .plus(superClassSequence) - .mapNotNull { declaration -> - declaration.annotations.firstOrNull { it is T } - } - .firstOrNull() as T? - ?: context.testMethod.get().annotations - .mapNotNull { annotation -> - annotation.annotationClass.annotations.firstOrNull { it is T } - } - .first() as T - } } @Target(AnnotationTarget.FUNCTION, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/osConditions.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/osConditions.kt index d168b811b2b..e0ea9803f4e 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/osConditions.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/osConditions.kt @@ -10,37 +10,67 @@ import org.junit.jupiter.api.extension.ConditionEvaluationResult import org.junit.jupiter.api.extension.ExecutionCondition import org.junit.jupiter.api.extension.ExtendWith import org.junit.jupiter.api.extension.ExtensionContext -import org.junit.platform.commons.util.AnnotationUtils +import org.junit.platform.commons.logging.LoggerFactory +import java.lang.reflect.AnnotatedElement +import java.util.* +/** + * An annotation that enables tests to be executed on a specific operating system within a specific environment. + * + * @param supportedOn Declares all the systems, on which this test can be executed in general, no matter on which environment. + * @param enabledOnCI Declares only platforms on which this test should be run in the TeamCity builds + * (that helps us not to overload such platforms like Mac OS). + * + * ## Warning + * If this annotation is directly present, indirectly present, or meta-present multiple times on a given + * element, only the first restrictions of each declaration level will be applied, + * but all the restrictions from different levels will be applied. + * For example, if you have this annotation on both the class level and method level, + * the method level annotation can only narrow the scope of the class level annotation. + * + * Exception: When used in a superclass declaration, + * this declaration does not compete with other declaration levels. + * It works only if it is the only declaration present for the superclass. + */ @Target(AnnotationTarget.FUNCTION, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS) @Retention(AnnotationRetention.RUNTIME) @ExtendWith(ExecutionOnOsCondition::class) annotation class OsCondition( val supportedOn: Array = [OS.LINUX, OS.MAC, OS.WINDOWS], - val enabledOnCI: Array = [OS.LINUX, OS.WINDOWS] + val enabledOnCI: Array = [OS.LINUX, OS.WINDOWS], ) internal class ExecutionOnOsCondition : ExecutionCondition { + + private val logger = LoggerFactory.getLogger(ExecutionOnOsCondition::class.java) + private val isUnderTeamcity = System.getenv("TEAMCITY_VERSION") != null - private val disabledByDefault = ConditionEvaluationResult.disabled("@OsCondition is not present") private val enabledOnCurrentOs = "Enabled on operating system: " + System.getProperty("os.name") private val notSupportedOnCurrentOs = "Test is not supported on operating system: " + System.getProperty("os.name") private val disabledForCI = "Disabled for operating system: " + System.getProperty("os.name") + " on CI" override fun evaluateExecutionCondition(context: ExtensionContext): ConditionEvaluationResult { - val annotation = AnnotationUtils.findAnnotation(context.element, OsCondition::class.java) - if (annotation.isPresent) { - val supportedOn = annotation.get().supportedOn - val enabledOnCI = annotation.get().enabledOnCI + val annotation = findAnnotation(context) - return if (!supportedOn.any { it.isCurrentOs }) - ConditionEvaluationResult.disabled(notSupportedOnCurrentOs) - else if (isUnderTeamcity && !enabledOnCI.any { it.isCurrentOs }) - ConditionEvaluationResult.disabled(disabledForCI) - else ConditionEvaluationResult.enabled(enabledOnCurrentOs) + val supportedOn = annotation.supportedOn + val enabledOnCI = annotation.enabledOnCI + + return if (supportedOn.none { it.isCurrentOs }) { + logger.info { createDisabledMessage(context.element.get(), "local", supportedOn) } + ConditionEvaluationResult.disabled(notSupportedOnCurrentOs) + } else if (isUnderTeamcity && enabledOnCI.none { it.isCurrentOs }) { + logger.info { createDisabledMessage(context.element.get(), "TeamCity", enabledOnCI) } + ConditionEvaluationResult.disabled(disabledForCI) + } else { + ConditionEvaluationResult.enabled(enabledOnCurrentOs) } + } - return disabledByDefault + private fun createDisabledMessage(annotatedElement: AnnotatedElement, environment: String, allowedOS: Array): String { + return "$annotatedElement" + + " was disabled in the $environment environment" + + " for the current os=${OS.current()}," + + " because allowed environments are: ${allowedOS.joinToString(separator = ", ") { it.name }}" } } \ No newline at end of file