refactored OsCondition behavior with multiple same annotations on the same target
#KT-51553 In Progress
This commit is contained in:
committed by
Space Team
parent
dd9e127d2c
commit
548ebbaf90
-1
@@ -18,7 +18,6 @@ import java.lang.annotation.Target;
|
|||||||
@Target({ElementType.METHOD})
|
@Target({ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@GradleTestVersions
|
@GradleTestVersions
|
||||||
@OsCondition
|
|
||||||
@AndroidTestVersions
|
@AndroidTestVersions
|
||||||
@ParameterizedTest(name = "AGP {1} with {0}: {displayName}")
|
@ParameterizedTest(name = "AGP {1} with {0}: {displayName}")
|
||||||
@ArgumentsSource(GradleAndAgpArgumentsProvider.class)
|
@ArgumentsSource(GradleAndAgpArgumentsProvider.class)
|
||||||
|
|||||||
-1
@@ -17,7 +17,6 @@ import java.lang.annotation.Target;
|
|||||||
// Workaround for https://youtrack.jetbrains.com/issue/IDEA-265284
|
// Workaround for https://youtrack.jetbrains.com/issue/IDEA-265284
|
||||||
@Target({ElementType.METHOD})
|
@Target({ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@OsCondition
|
|
||||||
@GradleTestVersions
|
@GradleTestVersions
|
||||||
@ParameterizedTest(name = "{0}: {displayName}")
|
@ParameterizedTest(name = "{0}: {displayName}")
|
||||||
@ArgumentsSource(GradleArgumentsProvider.class)
|
@ArgumentsSource(GradleArgumentsProvider.class)
|
||||||
|
|||||||
-1
@@ -18,7 +18,6 @@ import java.lang.annotation.Target;
|
|||||||
@Target({ElementType.METHOD})
|
@Target({ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@GradleTestVersions
|
@GradleTestVersions
|
||||||
@OsCondition
|
|
||||||
@JdkVersions
|
@JdkVersions
|
||||||
@ParameterizedTest(name = "{1} with {0}: {displayName}")
|
@ParameterizedTest(name = "{1} with {0}: {displayName}")
|
||||||
@ArgumentsSource(GradleAndJdkArgumentsProvider.class)
|
@ArgumentsSource(GradleAndJdkArgumentsProvider.class)
|
||||||
|
|||||||
+1
-3
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.gradle
|
|||||||
|
|
||||||
import org.gradle.api.JavaVersion
|
import org.gradle.api.JavaVersion
|
||||||
import org.gradle.api.logging.LogLevel
|
import org.gradle.api.logging.LogLevel
|
||||||
import org.gradle.api.logging.configuration.WarningMode
|
|
||||||
import org.gradle.testkit.runner.BuildResult
|
import org.gradle.testkit.runner.BuildResult
|
||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.tasks.USING_JVM_INCREMENTAL_COMPILATION_MESSAGE
|
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.jetbrains.kotlin.gradle.util.testResolveAllConfigurations
|
||||||
import org.junit.jupiter.api.Disabled
|
import org.junit.jupiter.api.Disabled
|
||||||
import org.junit.jupiter.api.DisplayName
|
import org.junit.jupiter.api.DisplayName
|
||||||
import org.junit.jupiter.api.condition.EnabledOnOs
|
|
||||||
import org.junit.jupiter.api.condition.OS
|
import org.junit.jupiter.api.condition.OS
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.util.zip.ZipFile
|
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")
|
@DisplayName("KT-52392: Setup with different windows disks does not fail configuration")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
@EnabledOnOs(OS.WINDOWS)
|
@OsCondition(supportedOn = [OS.WINDOWS], enabledOnCI = [OS.WINDOWS])
|
||||||
fun testDifferentDisksSetupDoesNotFailConfiguration(gradleVersion: GradleVersion) {
|
fun testDifferentDisksSetupDoesNotFailConfiguration(gradleVersion: GradleVersion) {
|
||||||
project("simple".withPrefix, gradleVersion) {
|
project("simple".withPrefix, gradleVersion) {
|
||||||
fun findAnotherRoot() = ('A'..'Z').first { !projectPath.root.startsWith(it.toString()) }
|
fun findAnotherRoot() = ('A'..'Z').first { !projectPath.root.startsWith(it.toString()) }
|
||||||
|
|||||||
+1
-2
@@ -10,11 +10,10 @@ import org.jetbrains.kotlin.gradle.testbase.*
|
|||||||
import org.jetbrains.kotlin.konan.target.HostManager
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import org.junit.jupiter.api.DisplayName
|
import org.junit.jupiter.api.DisplayName
|
||||||
import org.junit.jupiter.api.condition.EnabledOnOs
|
|
||||||
import org.junit.jupiter.api.condition.OS
|
import org.junit.jupiter.api.condition.OS
|
||||||
import kotlin.test.fail
|
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")
|
@DisplayName("Tests for Apple Silicon builds")
|
||||||
@NativeGradlePluginTests
|
@NativeGradlePluginTests
|
||||||
class AppleSiliconIT : KGPBaseTest() {
|
class AppleSiliconIT : KGPBaseTest() {
|
||||||
|
|||||||
+1
-2
@@ -9,7 +9,6 @@ import org.gradle.api.logging.LogLevel
|
|||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.testbase.*
|
import org.jetbrains.kotlin.gradle.testbase.*
|
||||||
import org.junit.jupiter.api.DisplayName
|
import org.junit.jupiter.api.DisplayName
|
||||||
import org.junit.jupiter.api.condition.EnabledOnOs
|
|
||||||
import org.junit.jupiter.api.condition.OS
|
import org.junit.jupiter.api.condition.OS
|
||||||
import kotlin.io.path.appendText
|
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")
|
@DisplayName("Links release XCFramework from two gradle modules")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun shouldLinkXCFrameworkFromTwoModules(gradleVersion: GradleVersion) {
|
fun shouldLinkXCFrameworkFromTwoModules(gradleVersion: GradleVersion) {
|
||||||
|
|||||||
+1
-2
@@ -8,11 +8,10 @@ package org.jetbrains.kotlin.gradle.native
|
|||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.testbase.*
|
import org.jetbrains.kotlin.gradle.testbase.*
|
||||||
import org.junit.jupiter.api.DisplayName
|
import org.junit.jupiter.api.DisplayName
|
||||||
import org.junit.jupiter.api.condition.EnabledOnOs
|
|
||||||
import org.junit.jupiter.api.condition.OS
|
import org.junit.jupiter.api.condition.OS
|
||||||
import kotlin.io.path.appendText
|
import kotlin.io.path.appendText
|
||||||
|
|
||||||
@EnabledOnOs(OS.MAC)
|
@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC])
|
||||||
@DisplayName("Tests for K/N with cocoapods")
|
@DisplayName("Tests for K/N with cocoapods")
|
||||||
@NativeGradlePluginTests
|
@NativeGradlePluginTests
|
||||||
class NativeLibraryDslWithCocoapodsIT : KGPBaseTest() {
|
class NativeLibraryDslWithCocoapodsIT : KGPBaseTest() {
|
||||||
|
|||||||
+1
-2
@@ -12,14 +12,13 @@ import org.jetbrains.kotlin.gradle.utils.Xcode
|
|||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import org.junit.jupiter.api.AfterAll
|
import org.junit.jupiter.api.AfterAll
|
||||||
import org.junit.jupiter.api.DisplayName
|
import org.junit.jupiter.api.DisplayName
|
||||||
import org.junit.jupiter.api.condition.EnabledOnOs
|
|
||||||
import org.junit.jupiter.api.condition.OS
|
import org.junit.jupiter.api.condition.OS
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
@DisplayName("tests for the K/N XCode simulator test infrastructure")
|
@DisplayName("tests for the K/N XCode simulator test infrastructure")
|
||||||
@NativeGradlePluginTests
|
@NativeGradlePluginTests
|
||||||
@EnabledOnOs(OS.MAC)
|
@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC])
|
||||||
class NativeXcodeSimulatorTestsIT : KGPBaseTest() {
|
class NativeXcodeSimulatorTestsIT : KGPBaseTest() {
|
||||||
private val defaultIosSimulator by lazy {
|
private val defaultIosSimulator by lazy {
|
||||||
val xcode = Xcode ?: error("XCode is expected to be defined")
|
val xcode = Xcode ?: error("XCode is expected to be defined")
|
||||||
|
|||||||
+1
-2
@@ -10,10 +10,9 @@ import org.jetbrains.kotlin.gradle.testbase.*
|
|||||||
import org.jetbrains.kotlin.gradle.util.replaceFirst
|
import org.jetbrains.kotlin.gradle.util.replaceFirst
|
||||||
import org.jetbrains.kotlin.gradle.util.replaceText
|
import org.jetbrains.kotlin.gradle.util.replaceText
|
||||||
import org.junit.jupiter.api.DisplayName
|
import org.junit.jupiter.api.DisplayName
|
||||||
import org.junit.jupiter.api.condition.EnabledOnOs
|
|
||||||
import org.junit.jupiter.api.condition.OS
|
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")
|
@DisplayName("Tests for K/N with apple XCFramework")
|
||||||
@NativeGradlePluginTests
|
@NativeGradlePluginTests
|
||||||
class XCFrameworkIT : KGPBaseTest() {
|
class XCFrameworkIT : KGPBaseTest() {
|
||||||
|
|||||||
+1
@@ -28,6 +28,7 @@ import java.nio.file.Path
|
|||||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||||
@WithMuteInDatabase
|
@WithMuteInDatabase
|
||||||
@TestDataPath("\$CONTENT_ROOT/resources/testProject")
|
@TestDataPath("\$CONTENT_ROOT/resources/testProject")
|
||||||
|
@OsCondition
|
||||||
abstract class KGPBaseTest {
|
abstract class KGPBaseTest {
|
||||||
open val defaultBuildOptions = BuildOptions()
|
open val defaultBuildOptions = BuildOptions()
|
||||||
|
|
||||||
|
|||||||
+29
-28
@@ -23,6 +23,35 @@ annotation class GradleTestVersions(
|
|||||||
val additionalVersions: Array<String> = []
|
val additionalVersions: Array<String> = []
|
||||||
)
|
)
|
||||||
|
|
||||||
|
inline fun <reified T : Annotation> 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 {
|
open class GradleArgumentsProvider : ArgumentsProvider {
|
||||||
override fun provideArguments(
|
override fun provideArguments(
|
||||||
context: ExtensionContext
|
context: ExtensionContext
|
||||||
@@ -48,34 +77,6 @@ open class GradleArgumentsProvider : ArgumentsProvider {
|
|||||||
.map { Arguments.of(it) }
|
.map { Arguments.of(it) }
|
||||||
.asStream()
|
.asStream()
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : Annotation> 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)
|
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS)
|
||||||
|
|||||||
+43
-13
@@ -10,37 +10,67 @@ import org.junit.jupiter.api.extension.ConditionEvaluationResult
|
|||||||
import org.junit.jupiter.api.extension.ExecutionCondition
|
import org.junit.jupiter.api.extension.ExecutionCondition
|
||||||
import org.junit.jupiter.api.extension.ExtendWith
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
import org.junit.jupiter.api.extension.ExtensionContext
|
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)
|
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@ExtendWith(ExecutionOnOsCondition::class)
|
@ExtendWith(ExecutionOnOsCondition::class)
|
||||||
annotation class OsCondition(
|
annotation class OsCondition(
|
||||||
val supportedOn: Array<OS> = [OS.LINUX, OS.MAC, OS.WINDOWS],
|
val supportedOn: Array<OS> = [OS.LINUX, OS.MAC, OS.WINDOWS],
|
||||||
val enabledOnCI: Array<OS> = [OS.LINUX, OS.WINDOWS]
|
val enabledOnCI: Array<OS> = [OS.LINUX, OS.WINDOWS],
|
||||||
)
|
)
|
||||||
|
|
||||||
internal class ExecutionOnOsCondition : ExecutionCondition {
|
internal class ExecutionOnOsCondition : ExecutionCondition {
|
||||||
|
|
||||||
|
private val logger = LoggerFactory.getLogger(ExecutionOnOsCondition::class.java)
|
||||||
|
|
||||||
private val isUnderTeamcity = System.getenv("TEAMCITY_VERSION") != null
|
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 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 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"
|
private val disabledForCI = "Disabled for operating system: " + System.getProperty("os.name") + " on CI"
|
||||||
|
|
||||||
override fun evaluateExecutionCondition(context: ExtensionContext): ConditionEvaluationResult {
|
override fun evaluateExecutionCondition(context: ExtensionContext): ConditionEvaluationResult {
|
||||||
val annotation = AnnotationUtils.findAnnotation(context.element, OsCondition::class.java)
|
val annotation = findAnnotation<OsCondition>(context)
|
||||||
if (annotation.isPresent) {
|
|
||||||
val supportedOn = annotation.get().supportedOn
|
|
||||||
val enabledOnCI = annotation.get().enabledOnCI
|
|
||||||
|
|
||||||
return if (!supportedOn.any { it.isCurrentOs })
|
val supportedOn = annotation.supportedOn
|
||||||
ConditionEvaluationResult.disabled(notSupportedOnCurrentOs)
|
val enabledOnCI = annotation.enabledOnCI
|
||||||
else if (isUnderTeamcity && !enabledOnCI.any { it.isCurrentOs })
|
|
||||||
ConditionEvaluationResult.disabled(disabledForCI)
|
return if (supportedOn.none { it.isCurrentOs }) {
|
||||||
else ConditionEvaluationResult.enabled(enabledOnCurrentOs)
|
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<OS>): String {
|
||||||
|
return "$annotatedElement" +
|
||||||
|
" was disabled in the $environment environment" +
|
||||||
|
" for the current os=${OS.current()}," +
|
||||||
|
" because allowed environments are: ${allowedOS.joinToString(separator = ", ") { it.name }}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user