Migrate UpToDateIT to new test dsl

^KT-45745 In Progress
This commit is contained in:
Yahor Berdnikau
2022-03-04 18:42:37 +01:00
parent 745b591b2e
commit 10f43b9fd7
@@ -1,60 +1,77 @@
package org.jetbrains.kotlin.gradle package org.jetbrains.kotlin.gradle
import org.jetbrains.kotlin.gradle.util.modify import org.gradle.testkit.runner.BuildResult
import org.junit.Assert import org.gradle.util.GradleVersion
import org.junit.Assume import org.jetbrains.kotlin.gradle.testbase.*
import org.junit.Test import org.junit.jupiter.api.DisplayName
import java.io.File import java.io.File
import java.nio.file.Path
import kotlin.io.path.appendText
import kotlin.io.path.deleteExisting
import kotlin.io.path.exists
import kotlin.test.assertTrue
class UpToDateIT : BaseGradleIT() { @DisplayName("Kotlin options change")
@Test @JvmGradlePluginTests
fun testLanguageVersionChange() { class UpToDateIT : KGPBaseTest() {
@DisplayName("Language version change")
@GradleTest
fun testLanguageVersionChange(gradleVersion: GradleVersion) {
testMutations( testMutations(
*propertyMutationChain( gradleVersion,
propertyMutationChain(
"compileKotlin.kotlinOptions.languageVersion", "compileKotlin.kotlinOptions.languageVersion",
"null", "'1.5'", "'1.4'", "null" "null", "'1.6'", "'1.5'", "'1.4'", "null"
) )
) )
} }
@Test @DisplayName("Api version change")
fun testApiVersionChange() { @GradleTest
fun testApiVersionChange(gradleVersion: GradleVersion) {
testMutations( testMutations(
*propertyMutationChain( gradleVersion,
propertyMutationChain(
"compileKotlin.kotlinOptions.apiVersion", "compileKotlin.kotlinOptions.apiVersion",
"null", "'1.5'", "'1.4'", "null" "null", "'1.6'", "'1.5'", "'1.4'", "null"
) )
) )
} }
@Test @DisplayName("Misc changes")
fun testOther() { @GradleTest
fun testOther(gradleVersion: GradleVersion) {
testMutations( testMutations(
emptyMutation, gradleVersion,
OptionMutation("compileKotlin.kotlinOptions.jvmTarget", "'1.6'", "'1.8'"), setOf(
OptionMutation("compileKotlin.kotlinOptions.freeCompilerArgs", "[]", "['-Xallow-kotlin-package']"), emptyMutation,
OptionMutation("kotlin.experimental.coroutines", "'error'", "'enable'"), OptionMutation("compileKotlin.kotlinOptions.jvmTarget", "'1.8'", "'11'"),
OptionMutation("archivesBaseName", "'someName'", "'otherName'"), OptionMutation("compileKotlin.kotlinOptions.freeCompilerArgs", "[]", "['-Xallow-kotlin-package']"),
subpluginOptionMutation, OptionMutation("archivesBaseName", "'someName'", "'otherName'"),
externalOutputMutation, subpluginOptionMutation,
compilerClasspathMutation externalOutputMutation,
compilerClasspathMutation
)
) )
} }
private fun testMutations(vararg mutations: ProjectMutation) { private fun testMutations(
val project = Project("kotlinProject") gradleVersion: GradleVersion,
project.setupWorkingDir() mutations: Set<ProjectMutation>
mutations.forEach { ) {
it.initProject(project) project("kotlinProject", gradleVersion) {
project.build("classes") { assertSuccessful() } mutations.forEach { mutation ->
mutation.initProject(this)
build("classes")
it.mutateProject(project) mutation.mutateProject(this)
project.build("classes") { build("classes") {
try { try {
assertSuccessful() mutation.checkAfterRebuild(this)
it.checkAfterRebuild(this) } catch (e: Throwable) {
} catch (e: Throwable) { throw RuntimeException("Mutation '${mutation.name}' has failed", e)
throw RuntimeException("Mutation '${it.name}' has failed", e) }
} }
} }
} }
@@ -63,48 +80,59 @@ class UpToDateIT : BaseGradleIT() {
private val emptyMutation = object : ProjectMutation { private val emptyMutation = object : ProjectMutation {
override val name = "emptyMutation" override val name = "emptyMutation"
override fun initProject(project: Project) = Unit override fun initProject(project: TestProject) = Unit
override fun mutateProject(project: Project) = Unit override fun mutateProject(project: TestProject) = Unit
override fun checkAfterRebuild(compiledProject: CompiledProject) = with(compiledProject) { override fun checkAfterRebuild(buildResult: BuildResult) = with(buildResult) {
assertTasksUpToDate(listOf(":compileKotlin")) assertTasksUpToDate(":compileKotlin")
} }
} }
private val compilerClasspathMutation = object : ProjectMutation { private val compilerClasspathMutation = object : ProjectMutation {
override val name = "compilerClasspathMutation" override val name = "compilerClasspathMutation"
private val compilerClasspathRegex = "compiler_cp=\\[(.*)]".toRegex()
lateinit var originalCompilerCp: List<String> lateinit var originalCompilerCp: List<String>
val originalPaths get() = originalCompilerCp.map { it.replace("\\", "/") }.joinToString(", ") { "'$it'" } val originalPaths get() = originalCompilerCp.map { it.replace("\\", "/") }.joinToString(", ") { "'$it'" }
override fun initProject(project: Project) = with(project) { override fun initProject(project: TestProject) = with(project) {
buildGradle.appendText( buildGradle.appendText(
"\nafterEvaluate { println 'compiler_cp=' + compileKotlin.getDefaultCompilerClasspath\$kotlin_gradle_plugin().toList() }" "\nafterEvaluate { println 'compiler_cp=' + compileKotlin.getDefaultCompilerClasspath\$kotlin_gradle_plugin().toList() }"
) )
build("clean") { originalCompilerCp = "compiler_cp=\\[(.*)]".toRegex().find(output)!!.groupValues[1].split(", ") } build("clean") {
buildGradle.appendText("""${'\n'} originalCompilerCp = compilerClasspathRegex.find(output)!!.groupValues[1].split(", ")
}
buildGradle.appendText(
"""
// Add Kapt to the project to test its input checks as well: // Add Kapt to the project to test its input checks as well:
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
compileKotlin.getDefaultCompilerClasspath${'$'}kotlin_gradle_plugin().setFrom(files($originalPaths).toList()) compileKotlin.getDefaultCompilerClasspath${'$'}kotlin_gradle_plugin().setFrom(files($originalPaths).toList())
afterEvaluate { afterEvaluate {
kaptGenerateStubsKotlin.getDefaultCompilerClasspath${'$'}kotlin_gradle_plugin().setFrom(files($originalPaths).toList()) kaptGenerateStubsKotlin.getDefaultCompilerClasspath${'$'}kotlin_gradle_plugin().setFrom(files($originalPaths).toList())
} }
""".trimIndent()) """.trimIndent()
)
} }
override fun mutateProject(project: Project) = with(project) { override fun mutateProject(project: TestProject) = with(project) {
buildGradle.modify { buildGradle.modify {
val modifiedClasspath = originalCompilerCp.map { val modifiedClasspath = originalCompilerCp.map {
val file = File(it) val file = File(it)
val newFile = File(projectDir, file.nameWithoutExtension + "-1.jar") val newFile = projectPath.resolve(file.nameWithoutExtension + "-1.jar").toFile()
file.copyTo(newFile) file.copyTo(newFile)
newFile.absolutePath newFile.absolutePath
}.reversed() }.reversed()
it.replace(originalPaths, modifiedClasspath.joinToString(", ") { "'${it.replace("\\", "/")}'" })
it.replace(
originalPaths,
modifiedClasspath.joinToString(", ") { "'${it.replace("\\", "/")}'" }
)
} }
} }
override fun checkAfterRebuild(compiledProject: CompiledProject) = with(compiledProject) { override fun checkAfterRebuild(buildResult: BuildResult) = with(buildResult) {
assertTasksExecuted(":compileKotlin", ":kaptGenerateStubsKotlin", ":kaptKotlin") assertTasksExecuted(":compileKotlin", ":kaptGenerateStubsKotlin", ":kaptKotlin")
} }
} }
@@ -112,20 +140,21 @@ class UpToDateIT : BaseGradleIT() {
private val subpluginOptionMutation = object : ProjectMutation { private val subpluginOptionMutation = object : ProjectMutation {
override val name: String get() = "subpluginOptionMutation" override val name: String get() = "subpluginOptionMutation"
override fun initProject(project: Project) = with(project) { override fun initProject(project: TestProject) = with(project) {
buildGradle.appendText( buildGradle.appendText(
"\n" + """ """
plugins.apply("org.jetbrains.kotlin.plugin.allopen") plugins.apply("org.jetbrains.kotlin.plugin.allopen")
allOpen { annotation("allopen.Foo"); annotation("allopen.Bar") } allOpen { annotation("allopen.Foo"); annotation("allopen.Bar") }
""".trimIndent() """.trimIndent()
) )
} }
override fun mutateProject(project: Project) = with(project) { override fun mutateProject(project: TestProject) = with(project) {
buildGradle.modify { it.replace("allopen.Foo", "allopen.Baz") } buildGradle.modify { it.replace("allopen.Foo", "allopen.Baz") }
} }
override fun checkAfterRebuild(compiledProject: CompiledProject) = with(compiledProject) { override fun checkAfterRebuild(buildResult: BuildResult) = with(buildResult) {
assertTasksExecuted(":compileKotlin") assertTasksExecuted(":compileKotlin")
} }
} }
@@ -133,40 +162,46 @@ class UpToDateIT : BaseGradleIT() {
private val externalOutputMutation = object : ProjectMutation { private val externalOutputMutation = object : ProjectMutation {
override val name = "externalOutputMutation" override val name = "externalOutputMutation"
override fun initProject(project: Project) = Unit override fun initProject(project: TestProject) = Unit
lateinit var helloWorldKtClass: File lateinit var helloWorldKtClass: Path
override fun mutateProject(project: Project) = with(project) { override fun mutateProject(project: TestProject) = with(project) {
val kotlinOutputPath = project.classesDir() val kotlinOutputPath = kotlinClassesDir()
helloWorldKtClass = File(projectDir, kotlinOutputPath + "demo/KotlinGreetingJoiner.class") helloWorldKtClass = kotlinOutputPath.resolve("demo/KotlinGreetingJoiner.class")
Assume.assumeTrue(helloWorldKtClass.exists()) assertTrue(helloWorldKtClass.exists())
helloWorldKtClass.delete(); Unit helloWorldKtClass.deleteExisting()
} }
override fun checkAfterRebuild(compiledProject: CompiledProject) = with(compiledProject) { override fun checkAfterRebuild(buildResult: BuildResult) = with(buildResult) {
assertTasksExecuted(":compileKotlin") assertTasksExecuted(":compileKotlin")
Assert.assertTrue(helloWorldKtClass.exists()) assertTrue(helloWorldKtClass.exists())
} }
} }
private val BaseGradleIT.Project.buildGradle get() = File(projectDir, "build.gradle")
private interface ProjectMutation { private interface ProjectMutation {
fun initProject(project: Project) fun initProject(project: TestProject)
fun mutateProject(project: Project) fun mutateProject(project: TestProject)
fun checkAfterRebuild(compiledProject: CompiledProject) fun checkAfterRebuild(buildResult: BuildResult)
val name: String val name: String
} }
private fun propertyMutationChain(path: String, vararg values: String): Array<ProjectMutation> = private fun propertyMutationChain(
arrayListOf<ProjectMutation>().apply { path: String,
for (i in 1..values.lastIndex) { vararg values: String
add(OptionMutation(path, values[i - 1], values[i], shouldInit = i == 1)) ): Set<OptionMutation> = values
} .drop(1)
.mapIndexed { index, value ->
}.toTypedArray() val actualIndex = index + 1
OptionMutation(
path,
values[actualIndex - 1],
value,
index == 0
)
}
.toSet()
private inner class OptionMutation( private inner class OptionMutation(
private val path: String, private val path: String,
@@ -176,17 +211,17 @@ class UpToDateIT : BaseGradleIT() {
) : ProjectMutation { ) : ProjectMutation {
override val name = "OptionMutation(path='$path', oldValue='$oldValue', newValue='$newValue')" override val name = "OptionMutation(path='$path', oldValue='$oldValue', newValue='$newValue')"
override fun initProject(project: Project) = with(project) { override fun initProject(project: TestProject) = with(project) {
if (shouldInit) { if (shouldInit) {
buildGradle.appendText("\n$path = $oldValue") buildGradle.appendText("\n$path = $oldValue")
} }
} }
override fun mutateProject(project: Project) = with(project) { override fun mutateProject(project: TestProject) = with(project) {
buildGradle.modify { it.replace("$path = $oldValue", "$path = $newValue") } buildGradle.modify { it.replace("$path = $oldValue", "$path = $newValue") }
} }
override fun checkAfterRebuild(compiledProject: CompiledProject) = with(compiledProject) { override fun checkAfterRebuild(buildResult: BuildResult) = with(buildResult) {
assertTasksExecuted(":compileKotlin") assertTasksExecuted(":compileKotlin")
} }
} }