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})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@GradleTestVersions
|
||||
@OsCondition
|
||||
@AndroidTestVersions
|
||||
@ParameterizedTest(name = "AGP {1} with {0}: {displayName}")
|
||||
@ArgumentsSource(GradleAndAgpArgumentsProvider.class)
|
||||
|
||||
-1
@@ -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)
|
||||
|
||||
-1
@@ -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)
|
||||
|
||||
+1
-3
@@ -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()) }
|
||||
|
||||
+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.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() {
|
||||
|
||||
+1
-2
@@ -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) {
|
||||
|
||||
+1
-2
@@ -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() {
|
||||
|
||||
+1
-2
@@ -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")
|
||||
|
||||
+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.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() {
|
||||
|
||||
+1
@@ -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()
|
||||
|
||||
|
||||
+29
-28
@@ -23,6 +23,35 @@ annotation class GradleTestVersions(
|
||||
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 {
|
||||
override fun provideArguments(
|
||||
context: ExtensionContext
|
||||
@@ -48,34 +77,6 @@ open class GradleArgumentsProvider : ArgumentsProvider {
|
||||
.map { Arguments.of(it) }
|
||||
.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)
|
||||
|
||||
+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.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> = [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 {
|
||||
|
||||
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<OsCondition>(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<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