Add @GradleWithJdkTest annotation.
Adding this annotation to the test will provide requested JDKs + Gradle versions matrix as test parameter. It is also possible to filter out supported by Gradle version JDKs. ^KT-45745 In Progress
This commit is contained in:
@@ -85,6 +85,23 @@ plugins {
|
||||
A bunch of additional useful assertions available to use, such as file assertions, output assertions and task assertions. If you want to
|
||||
add a new assertion, add as a reviewer someone from Kotlin build tools team.
|
||||
|
||||
##### Additional test helpers
|
||||
|
||||
Whenever you need to test combination of different JDKs and Gradle versions - you could use `@GradleWithJdkTest` instead of `@GradleTest`.
|
||||
Then test method will receive requires JDKs as a second parameter:
|
||||
```kotlin
|
||||
@JdkVersions(version = [JavaVersion.VERSION_11, JavaVersion.VERSION_17])
|
||||
@GradleWithJdkTest
|
||||
fun someTest(
|
||||
gradleVersion: GradleVersion,
|
||||
providedJdk: JdkVersions.ProvidedJdk
|
||||
) {
|
||||
project("simple", gradleVersion, buildJdk = providedJdk.location) {
|
||||
build("assemble")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### Deprecated tests setup
|
||||
|
||||
When you create a new test, figure out which Gradle versions it is supposed to run on. Then, when you instantiate a test project, specify one of:
|
||||
|
||||
+2
-2
@@ -17,8 +17,8 @@ import java.lang.annotation.Target;
|
||||
// Workaround for https://youtrack.jetbrains.com/issue/IDEA-265284
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@KGPBaseTest.GradleTestVersions
|
||||
@GradleTestVersions
|
||||
@ParameterizedTest(name = "{0}: {displayName}")
|
||||
@ArgumentsSource(KGPBaseTest.GradleArgumentsProvider.class)
|
||||
@ArgumentsSource(GradleArgumentsProvider.class)
|
||||
public @interface GradleTest {
|
||||
}
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.testbase;
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
// Has to be java annotation
|
||||
// Workaround for https://youtrack.jetbrains.com/issue/IDEA-265284
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@GradleTestVersions
|
||||
@JdkVersions
|
||||
@ParameterizedTest(name = "{1} with {0}: {displayName}")
|
||||
@ArgumentsSource(GradleAndJdkArgumentsProvider.class)
|
||||
public @interface GradleWithJdkTest {
|
||||
}
|
||||
-62
@@ -5,17 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.testbase
|
||||
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.jetbrains.kotlin.test.WithMuteInDatabase
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.extension.ExtensionContext
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import org.junit.jupiter.params.provider.Arguments
|
||||
import org.junit.jupiter.params.provider.ArgumentsProvider
|
||||
import java.nio.file.Path
|
||||
import java.util.stream.Stream
|
||||
import kotlin.streams.asStream
|
||||
|
||||
/**
|
||||
* Base class for all Kotlin Gradle plugin integration tests.
|
||||
@@ -28,60 +22,4 @@ abstract class KGPBaseTest {
|
||||
|
||||
@TempDir
|
||||
lateinit var workingDir: Path
|
||||
|
||||
class GradleArgumentsProvider : ArgumentsProvider {
|
||||
override fun provideArguments(
|
||||
context: ExtensionContext
|
||||
): Stream<out Arguments> {
|
||||
var nextSuperclass: Class<*>? = context.testClass.get().superclass
|
||||
val superClassSequence = if (nextSuperclass != null) {
|
||||
generateSequence {
|
||||
val currentSuperclass = nextSuperclass
|
||||
nextSuperclass = nextSuperclass?.superclass
|
||||
currentSuperclass
|
||||
}
|
||||
} else {
|
||||
emptySequence()
|
||||
}
|
||||
|
||||
val versionsAnnotation = sequenceOf(
|
||||
context.testMethod.get(),
|
||||
context.testClass.get()
|
||||
)
|
||||
.plus(superClassSequence)
|
||||
.mapNotNull { declaration ->
|
||||
declaration.annotations.firstOrNull { it is GradleTestVersions }
|
||||
}
|
||||
.firstOrNull() as GradleTestVersions?
|
||||
?: context.testMethod.get().annotations
|
||||
.mapNotNull { annotation ->
|
||||
annotation.annotationClass.annotations.firstOrNull { it is GradleTestVersions }
|
||||
}
|
||||
.first() as GradleTestVersions
|
||||
|
||||
val minGradleVersion = GradleVersion.version(versionsAnnotation.minVersion)
|
||||
val maxGradleVersion = GradleVersion.version(versionsAnnotation.maxVersion)
|
||||
val additionalGradleVersions = versionsAnnotation
|
||||
.additionalVersions
|
||||
.map(GradleVersion::version)
|
||||
additionalGradleVersions.forEach {
|
||||
assert(it in minGradleVersion..maxGradleVersion) {
|
||||
"Additional Gradle version ${it.version} should be between ${minGradleVersion.version} and ${maxGradleVersion.version}"
|
||||
}
|
||||
}
|
||||
|
||||
return setOf(minGradleVersion, *additionalGradleVersions.toTypedArray(), maxGradleVersion)
|
||||
.asSequence()
|
||||
.map { Arguments.of(it) }
|
||||
.asStream()
|
||||
}
|
||||
}
|
||||
|
||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class GradleTestVersions(
|
||||
val minVersion: String = TestVersions.Gradle.MIN_SUPPORTED,
|
||||
val maxVersion: String = TestVersions.Gradle.MAX_SUPPORTED,
|
||||
val additionalVersions: Array<String> = []
|
||||
)
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.gradle.testbase
|
||||
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.junit.jupiter.api.extension.ExtensionContext
|
||||
import org.junit.jupiter.params.provider.Arguments
|
||||
import org.junit.jupiter.params.provider.ArgumentsProvider
|
||||
import java.io.File
|
||||
import java.util.stream.Stream
|
||||
import kotlin.streams.asStream
|
||||
import kotlin.streams.toList
|
||||
|
||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class GradleTestVersions(
|
||||
val minVersion: String = TestVersions.Gradle.MIN_SUPPORTED,
|
||||
val maxVersion: String = TestVersions.Gradle.MAX_SUPPORTED,
|
||||
val additionalVersions: Array<String> = []
|
||||
)
|
||||
|
||||
open class GradleArgumentsProvider : ArgumentsProvider {
|
||||
override fun provideArguments(
|
||||
context: ExtensionContext
|
||||
): Stream<out Arguments> {
|
||||
val versionsAnnotation = findAnnotation<GradleTestVersions>(context)
|
||||
|
||||
val minGradleVersion = GradleVersion.version(versionsAnnotation.minVersion)
|
||||
val maxGradleVersion = GradleVersion.version(versionsAnnotation.maxVersion)
|
||||
val additionalGradleVersions = versionsAnnotation
|
||||
.additionalVersions
|
||||
.map(GradleVersion::version)
|
||||
additionalGradleVersions.forEach {
|
||||
assert(it in minGradleVersion..maxGradleVersion) {
|
||||
"Additional Gradle version ${it.version} should be between ${minGradleVersion.version} and ${maxGradleVersion.version}"
|
||||
}
|
||||
}
|
||||
|
||||
return setOf(minGradleVersion, *additionalGradleVersions.toTypedArray(), maxGradleVersion)
|
||||
.asSequence()
|
||||
.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)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class JdkVersions(
|
||||
val versions: Array<JavaVersion> = [JavaVersion.VERSION_1_8, JavaVersion.VERSION_17],
|
||||
val compatibleWithGradle: Boolean = true
|
||||
) {
|
||||
class ProvidedJdk(
|
||||
val version: JavaVersion,
|
||||
val location: File
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return "JDK $version"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GradleAndJdkArgumentsProvider : GradleArgumentsProvider() {
|
||||
override fun provideArguments(
|
||||
context: ExtensionContext
|
||||
): Stream<out Arguments> {
|
||||
val jdkAnnotation = findAnnotation<JdkVersions>(context)
|
||||
val providedJdks = jdkAnnotation
|
||||
.versions
|
||||
.map {
|
||||
JdkVersions.ProvidedJdk(
|
||||
it,
|
||||
File(System.getProperty("jdk${it.majorVersion}Home"))
|
||||
)
|
||||
}
|
||||
|
||||
val gradleVersions = super.provideArguments(context).map { it.get().first() as GradleVersion }.toList()
|
||||
|
||||
return providedJdks
|
||||
.flatMap { providedJdk ->
|
||||
val minSupportedGradleVersion = jdkGradleCompatibilityMatrix[providedJdk.version]
|
||||
gradleVersions
|
||||
.run {
|
||||
if (jdkAnnotation.compatibleWithGradle && minSupportedGradleVersion != null) {
|
||||
val initialVersionsCount = count()
|
||||
val filteredVersions = filter { it >= minSupportedGradleVersion }
|
||||
if (initialVersionsCount > filteredVersions.count()) {
|
||||
(filteredVersions + minSupportedGradleVersion).toSet()
|
||||
} else {
|
||||
filteredVersions
|
||||
}
|
||||
} else this
|
||||
}
|
||||
.map { it to providedJdk }
|
||||
}
|
||||
.asSequence()
|
||||
.map {
|
||||
Arguments.of(it.first, it.second)
|
||||
}
|
||||
.asStream()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val jdkGradleCompatibilityMatrix = mapOf(
|
||||
JavaVersion.VERSION_14 to GradleVersion.version(TestVersions.Gradle.G_6_3),
|
||||
JavaVersion.VERSION_15 to GradleVersion.version(TestVersions.Gradle.G_6_7),
|
||||
JavaVersion.VERSION_16 to GradleVersion.version(TestVersions.Gradle.G_7_0),
|
||||
JavaVersion.VERSION_17 to GradleVersion.version(TestVersions.Gradle.G_7_3)
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user