Migrated ExecutionStrategyIT tests to new DSL

^KT-45745 In Progress
This commit is contained in:
Yahor Berdnikau
2022-01-18 13:51:24 +01:00
parent 12d8b189a9
commit 5f22bcd03b
7 changed files with 163 additions and 119 deletions
@@ -1,85 +1,140 @@
package org.jetbrains.kotlin.gradle package org.jetbrains.kotlin.gradle
import org.gradle.api.logging.LogLevel
import org.gradle.testkit.runner.BuildResult
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.util.checkedReplace import org.jetbrains.kotlin.gradle.util.checkedReplace
import org.jetbrains.kotlin.gradle.util.getFileByName import org.junit.jupiter.api.DisplayName
import org.jetbrains.kotlin.gradle.util.modify
import org.junit.Assert
import org.junit.Test
import java.io.File
@DisplayName("Kotlin JS compile execution strategy")
class ExecutionStrategyJsIT : ExecutionStrategyIT() { class ExecutionStrategyJsIT : ExecutionStrategyIT() {
override fun setupProject(project: Project) { override fun setupProject(project: TestProject) {
super.setupProject(project) super.setupProject(project)
val buildGradle = File(project.projectDir, "app/build.gradle")
buildGradle.modify { project.subProject("app").buildGradle.modify {
it.replace("apply plugin: \"kotlin\"", "apply plugin: \"kotlin2js\"") + it.replace(
"\ncompileKotlin2Js.kotlinOptions.outputFile = \"web/js/out.js\"" "id \"org.jetbrains.kotlin.jvm\"",
"id \"org.jetbrains.kotlin.js\""
) +
"""
|
|afterEvaluate {
| tasks.named('compileKotlinJs') {
| kotlinOptions.outputFile = "${'$'}{project.projectDir}/web/js/out.js"
| }
|}
|
""".trimMargin()
} }
} }
override fun CompiledProject.checkOutput() { override fun BuildResult.checkOutput(project: TestProject) {
assertFileExists("web/js/out.js") project.subProject("app").assertFileInProjectExists("web/js/out.js")
} }
override fun CompiledProject.checkOutputAfterChange() { override fun BuildResult.checkOutputAfterChange(project: TestProject) {
assertFileExists("web/js/out.js") project.subProject("app").assertFileInProjectExists("web/js/out.js")
} }
} }
@DisplayName("Kotlin JVM compile execution strategy")
class ExecutionStrategyJvmIT : ExecutionStrategyIT() { class ExecutionStrategyJvmIT : ExecutionStrategyIT() {
override fun CompiledProject.checkOutput() { override fun BuildResult.checkOutput(project: TestProject) {
val classesDir = kotlinClassesDir(subproject = "app") + "foo/" with(project) {
assertFileExists("${classesDir}MainKt.class") val classesDir = subProject("app").kotlinClassesDir().resolve("foo")
assertFileExists("${classesDir}A.class") assertFileExists(classesDir.resolve("MainKt.class"))
assertFileExists("${classesDir}B.class") assertFileExists(classesDir.resolve("A.class"))
assertFileExists(classesDir.resolve("B.class"))
}
} }
override fun CompiledProject.checkOutputAfterChange() { override fun BuildResult.checkOutputAfterChange(project: TestProject) {
val classesDir = kotlinClassesDir(subproject = "app") + "foo/" with(project) {
assertFileExists("${classesDir}MainKt.class") val classesDir = subProject("app").kotlinClassesDir().resolve("foo")
assertFileExists("${classesDir}A.class") assertFileExists(classesDir.resolve("MainKt.class"))
assertNoSuchFile("${classesDir}B.class") assertFileExists(classesDir.resolve("A.class"))
assertFileNotExists(classesDir.resolve("B.class"))
}
} }
} }
abstract class ExecutionStrategyIT : BaseGradleIT() { abstract class ExecutionStrategyIT : KGPDaemonsBaseTest() {
@Test override val defaultBuildOptions: BuildOptions = super.defaultBuildOptions.copy(
fun testDaemon() { logLevel = LogLevel.DEBUG
doTestExecutionStrategy(KotlinCompilerExecutionStrategy.DAEMON, addHeapDumpOptions = false) )
@DisplayName("Compilation via Kotlin daemon")
@GradleTest
fun testDaemon(gradleVersion: GradleVersion) {
doTestExecutionStrategy(
gradleVersion,
KotlinCompilerExecutionStrategy.DAEMON,
addHeapDumpOptions = false
)
} }
@Test @DisplayName("Compilation via Kotlin daemon enabled using system property")
fun testDaemonViaSystemProperty() { @GradleTest
doTestExecutionStrategy(KotlinCompilerExecutionStrategy.DAEMON, addHeapDumpOptions = false, viaSystemProperty = true) fun testDaemonViaSystemProperty(gradleVersion: GradleVersion) {
doTestExecutionStrategy(
gradleVersion,
KotlinCompilerExecutionStrategy.DAEMON,
addHeapDumpOptions = false,
viaSystemProperty = true
)
} }
@Test @DisplayName("Compilation inside Gradle daemon")
fun testInProcess() { @GradleTest
doTestExecutionStrategy(KotlinCompilerExecutionStrategy.IN_PROCESS) fun testInProcess(gradleVersion: GradleVersion) {
doTestExecutionStrategy(
gradleVersion,
KotlinCompilerExecutionStrategy.IN_PROCESS
)
} }
@Test @DisplayName("Compilation inside Gradle daemon enabled using system property")
fun testInProcessViaSystemProperty() { @GradleTest
doTestExecutionStrategy(KotlinCompilerExecutionStrategy.IN_PROCESS, viaSystemProperty = true) fun testInProcessViaSystemProperty(gradleVersion: GradleVersion) {
doTestExecutionStrategy(
gradleVersion,
KotlinCompilerExecutionStrategy.IN_PROCESS,
viaSystemProperty = true
)
} }
@Test @DisplayName("Compilation via separate compiler process")
fun testOutOfProcess() { @GradleTest
doTestExecutionStrategy(KotlinCompilerExecutionStrategy.OUT_OF_PROCESS) fun testOutOfProcess(gradleVersion: GradleVersion) {
doTestExecutionStrategy(
gradleVersion,
KotlinCompilerExecutionStrategy.OUT_OF_PROCESS
)
} }
@Test @DisplayName("Compilation via separate compiler process enabled via system property")
fun testOutOfProcessViaSystemProperty() { @GradleTest
doTestExecutionStrategy(KotlinCompilerExecutionStrategy.OUT_OF_PROCESS, viaSystemProperty = true) fun testOutOfProcessViaSystemProperty(gradleVersion: GradleVersion) {
doTestExecutionStrategy(
gradleVersion,
KotlinCompilerExecutionStrategy.OUT_OF_PROCESS,
viaSystemProperty = true
)
} }
private fun doTestExecutionStrategy( private fun doTestExecutionStrategy(
gradleVersion: GradleVersion,
executionStrategy: KotlinCompilerExecutionStrategy, executionStrategy: KotlinCompilerExecutionStrategy,
addHeapDumpOptions: Boolean = true, addHeapDumpOptions: Boolean = true,
viaSystemProperty: Boolean = false viaSystemProperty: Boolean = false
) { ) {
with(Project("kotlinBuiltins", addHeapDumpOptions = addHeapDumpOptions)) { project(
projectName = "kotlinBuiltins",
gradleVersion = gradleVersion,
addHeapDumpOptions = addHeapDumpOptions
) {
setupProject(this) setupProject(this)
val cliArgPrefix = if (viaSystemProperty) "-D" else "-P" val cliArgPrefix = if (viaSystemProperty) "-D" else "-P"
@@ -87,53 +142,44 @@ abstract class ExecutionStrategyIT : BaseGradleIT() {
val finishMessage = "Finished executing kotlin compiler using $executionStrategy strategy" val finishMessage = "Finished executing kotlin compiler using $executionStrategy strategy"
build("build", strategyCLIArg) { build("build", strategyCLIArg) {
assertSuccessful() assertOutputContains(finishMessage)
assertContains(finishMessage) checkOutput(this@project)
checkOutput() assertNoBuildWarnings()
assertNoWarnings()
if (executionStrategy == KotlinCompilerExecutionStrategy.DAEMON) { if (executionStrategy == KotlinCompilerExecutionStrategy.DAEMON) {
checkCompileDaemon() // 256m is the default value for Gradle 5.0+
assertKotlinDaemonJvmOptions(
listOf("-XX:MaxMetaspaceSize=256m", "-ea")
)
} }
} }
val classesKt = projectDir.getFileByName("classes.kt") val classesKt = subProject("app").kotlinSourcesDir().resolve("classes.kt")
classesKt.modify { classesKt.modify {
it.checkedReplace("class B", "//class B") it.checkedReplace("class B", "//class B")
} }
build("build", strategyCLIArg) { build("build", strategyCLIArg) {
assertSuccessful() assertOutputContains(finishMessage)
assertContains(finishMessage) checkOutputAfterChange(this@project)
checkOutputAfterChange() assertNoBuildWarnings()
assertNoWarnings()
} }
} }
} }
private fun CompiledProject.checkCompileDaemon() { protected open fun setupProject(project: TestProject) {
val m = "Kotlin compile daemon JVM options: \\[(.*?)\\]".toRegex().find(output) project.subProject("app").buildGradle.append(
?: error("Could not find Kotlin compile daemon JVM options in Gradle's output") //language=Groovy
val kotlinDaemonJvmArgs = m.groupValues[1].split(",").mapTo(LinkedHashSet()) { it.trim() } """
|
fun assertDaemonArgsContain(arg: String) { |tasks
Assert.assertTrue( | .withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile)
"Expected '$arg' in kotlin daemon JVM args, got: $kotlinDaemonJvmArgs", | .configureEach {
arg in kotlinDaemonJvmArgs | kotlinOptions.allWarningsAsErrors = true
) | }
} """.trimMargin()
// 256m is the default value for Gradle 5.0+
assertDaemonArgsContain("-XX:MaxMetaspaceSize=256m")
assertDaemonArgsContain("-ea")
}
protected open fun setupProject(project: Project) {
project.setupWorkingDir()
File(project.projectDir, "app/build.gradle").appendText(
"\ntasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all { kotlinOptions.allWarningsAsErrors = true }"
) )
} }
protected abstract fun CompiledProject.checkOutput() protected abstract fun BuildResult.checkOutput(project: TestProject)
protected abstract fun CompiledProject.checkOutputAfterChange() protected abstract fun BuildResult.checkOutputAfterChange(project: TestProject)
} }
@@ -224,11 +224,21 @@ class Kotlin2JsGradlePluginIT : AbstractKotlin2JsGradlePluginIT(false) {
project("kotlinBuiltins", gradleVersion) { project("kotlinBuiltins", gradleVersion) {
subProject("app").buildGradle.modify { originalScript -> subProject("app").buildGradle.modify { originalScript ->
buildString { buildString {
append(originalScript.replace("apply plugin: \"kotlin\"", "apply plugin: \"kotlin2js\"")) append(
originalScript.replace(
"id \"org.jetbrains.kotlin.jvm\"",
"id \"org.jetbrains.kotlin.js\""
)
)
append( append(
""" """
| |
|compileKotlin2Js.kotlinOptions.outputFile = "out/out.js" |afterEvaluate {
| tasks.named('compileKotlinJs') {
| kotlinOptions.outputFile = "${'$'}{project.projectDir}/out/out.js"
| }
|}
|
""".trimMargin() """.trimMargin()
) )
} }
@@ -6,11 +6,8 @@
package org.jetbrains.kotlin.gradle package org.jetbrains.kotlin.gradle
import org.gradle.api.logging.LogLevel import org.gradle.api.logging.LogLevel
import org.gradle.testkit.runner.BuildResult
import org.gradle.tooling.internal.consumer.ConnectorServices
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.AfterEach
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
@DisplayName("Kotlin daemon JVM args") @DisplayName("Kotlin daemon JVM args")
@@ -171,26 +168,4 @@ class KotlinDaemonJvmArgsTest : KGPDaemonsBaseTest() {
} }
} }
} }
private fun BuildResult.assertKotlinDaemonJvmOptions(
expectedOptions: List<String>
) {
val jvmArgsCommonMessage = "Kotlin compile daemon JVM options: "
assertOutputContains(jvmArgsCommonMessage)
val argsRegex = "\\[.+?]".toRegex()
val argsStrings = output.lineSequence()
.filter { it.contains(jvmArgsCommonMessage) }
.map {
argsRegex.findAll(it).last().value.removePrefix("[").removeSuffix("]").split(", ")
}
val containsArgs = argsStrings.any {
it.containsAll(expectedOptions)
}
assert(containsArgs) {
printBuildOutput()
"${argsStrings.toList()} does not contain expected args: $expectedOptions"
}
}
} }
@@ -190,3 +190,28 @@ fun BuildResult.assertIncrementalCompilation(
""".trimMargin() """.trimMargin()
} }
} }
/**
* Asserts compilation is running via Kotlin daemon with given jvm arguments.
*/
fun BuildResult.assertKotlinDaemonJvmOptions(
expectedJvmArgs: List<String>
) {
val jvmArgsCommonMessage = "Kotlin compile daemon JVM options: "
assertOutputContains(jvmArgsCommonMessage)
val argsRegex = "\\[.+?]".toRegex()
val argsStrings = output.lineSequence()
.filter { it.contains(jvmArgsCommonMessage) }
.map {
argsRegex.findAll(it).last().value.removePrefix("[").removeSuffix("]").split(", ")
}
val containsArgs = argsStrings.any {
it.containsAll(expectedJvmArgs)
}
assert(containsArgs) {
printBuildOutput()
"${argsStrings.toList()} does not contain expected args: $expectedJvmArgs"
}
}
@@ -1,10 +1,8 @@
apply plugin: "kotlin" plugins {
id "org.jetbrains.kotlin.jvm"
}
repositories { repositories {
mavenLocal() mavenLocal()
mavenCentral() mavenCentral()
} }
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
@@ -1,9 +0,0 @@
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
@@ -141,7 +141,6 @@ private fun writeArgumentsToFile(directory: File, argsArray: Array<String>): Fil
Files.createTempFile(directory.toPath(), prefix, suffix).toFile() Files.createTempFile(directory.toPath(), prefix, suffix).toFile()
else else
Files.createTempFile(prefix, suffix).toFile() Files.createTempFile(prefix, suffix).toFile()
compilerOptions.deleteOnExit()
compilerOptions.writeText(argsArray.joinToString(" ") { "\"${StringEscapeUtils.escapeJava(it)}\"" }) compilerOptions.writeText(argsArray.joinToString(" ") { "\"${StringEscapeUtils.escapeJava(it)}\"" })
return compilerOptions return compilerOptions
} }