Migrate KotlinDaemonIT tests to new test dsl.

^KT-45745 In Progress
This commit is contained in:
Yahor Berdnikau
2021-11-03 11:41:11 +01:00
parent a6436adc17
commit 5a11446c79
@@ -16,100 +16,139 @@
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.tooling.internal.consumer.ConnectorServices
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.compilerRunner.* import org.jetbrains.kotlin.compilerRunner.*
import org.junit.Assert import org.jetbrains.kotlin.gradle.testbase.*
import org.junit.Test import org.junit.jupiter.api.DisplayName
import java.io.File import java.nio.file.Paths
import kotlin.test.assertTrue import kotlin.test.assertTrue
// todo: test client file creation/deletion // todo: test client file creation/deletion
// todo: test daemon start (does not start every build) // todo: test daemon start (does not start every build)
// todo: test daemon shutdown when gradle daemon dies // todo: test daemon shutdown when gradle daemon dies
class KotlinDaemonIT : BaseGradleIT() { @DisplayName("Kotlin daemon base behaviour")
class KotlinDaemonIT : KGPDaemonsBaseTest() {
@Test override val defaultBuildOptions: BuildOptions = super.defaultBuildOptions
fun testDaemonMultiproject() { .copy(
fun String.findAllStringsPrefixed(prefix: String): Array<String> { logLevel = LogLevel.DEBUG
val result = arrayListOf<String>() )
val regex = ("$prefix([^\\r\\n]*)").toRegex()
for (match in regex.findAll(this)) {
result.add(match.groupValues[1])
}
return result.toTypedArray()
}
val project = Project("multiprojectWithDependency") @DisplayName("Kotlin daemon is reused in multiproject")
val strategyCLIArg = "-Dkotlin.compiler.execution.strategy=daemon" @GradleTest
fun testDaemonMultiproject(gradleVersion: GradleVersion) {
fun checkAfterNonIncrementalBuild(output: String) { project("multiprojectWithDependency", gradleVersion) {
val createdSessions = output.findAllStringsPrefixed(CREATED_SESSION_FILE_PREFIX) gradleProperties.append(
assert(createdSessions.size == 1) { "Created multiple sessions per build ${createdSessions.joinToString()}" } "\nkotlin.compiler.execution.strategy=daemon"
val existingSessions = output.findAllStringsPrefixed(EXISTING_SESSION_FILE_PREFIX)
Assert.assertArrayEquals(
"Existing sessions don't match created sessions for two module projects",
createdSessions,
existingSessions
) )
val deletedSessions = output.findAllStringsPrefixed(DELETED_SESSION_FILE_PREFIX) build("build") {
Assert.assertArrayEquals("Deleted sessions don't match created sessions", createdSessions, deletedSessions) assertOutputDoesNotContain(COULD_NOT_CONNECT_TO_DAEMON_MESSAGE)
} assertKotlinDaemonReusesOnlyOneSession()
}
project.build("build", strategyCLIArg) { build("clean", "build") {
assertNotContains(COULD_NOT_CONNECT_TO_DAEMON_MESSAGE) assertOutputDoesNotContain(COULD_NOT_CONNECT_TO_DAEMON_MESSAGE)
checkAfterNonIncrementalBuild(output) assertKotlinDaemonReusesOnlyOneSession()
} }
project.build("clean", "build", strategyCLIArg) { build("build") {
assertNotContains(COULD_NOT_CONNECT_TO_DAEMON_MESSAGE) assert(output.findAllStringsPrefixed(CREATED_SESSION_FILE_PREFIX).isEmpty()) {
checkAfterNonIncrementalBuild(output) "Sessions should not be created (incremental build)"
} }
project.build("build", strategyCLIArg) { assert(output.findAllStringsPrefixed(EXISTING_SESSION_FILE_PREFIX).isEmpty()) {
val createdSessions = output.findAllStringsPrefixed(CREATED_SESSION_FILE_PREFIX) "Sessions should not be existing (incremental build)"
Assert.assertArrayEquals("Sessions should not be created (incremental build)", createdSessions, emptyArray()) }
val existingSessions = output.findAllStringsPrefixed(EXISTING_SESSION_FILE_PREFIX) assert(output.findAllStringsPrefixed(DELETED_SESSION_FILE_PREFIX).isEmpty()) {
Assert.assertArrayEquals("Sessions should not be existing (incremental build)", existingSessions, emptyArray()) "Sessions should not be deleted (incremental build)"
}
val deletedSessions = output.findAllStringsPrefixed(DELETED_SESSION_FILE_PREFIX)
Assert.assertArrayEquals("Sessions should not be deleted (incremental build)", deletedSessions, emptyArray())
}
}
@Test
fun testClientFileIsDeletedOnExit() {
val project = Project("kotlinProject")
val options = defaultBuildOptions().copy(withDaemon = false)
project.build("assemble", options = options) {
val regex = Regex("(?m)($CREATED_CLIENT_FILE_PREFIX|$EXISTING_CLIENT_FILE_PREFIX)(.+)$")
val clientFiles = regex.findAll(output).toList().map { File(it.groupValues[2]) }
assert(clientFiles.isNotEmpty()) { "No client files in log" }
clientFiles.forEach { clientFile ->
assert(!clientFile.exists()) { "Client file $clientFile is expected to be deleted!" }
} }
} }
} }
@Test @DisplayName("Client file is deleted on exit")
fun testGradleBuildClasspathShouldNotBeLeakedIntoDaemonClasspath() { @GradleTest
val testProject = Project("kotlinProject") fun testClientFileIsDeletedOnExit(gradleVersion: GradleVersion) {
testProject.setupWorkingDir() project("kotlinProject", gradleVersion) {
build("assemble") {
val regex = "(?m)($CREATED_CLIENT_FILE_PREFIX|$EXISTING_CLIENT_FILE_PREFIX)(.+)$".toRegex()
val clientFiles = regex.findAll(output).map { Paths.get(it.groupValues[2]) }.toList()
assert(clientFiles.isNotEmpty()) { "No client files in log" }
testProject.build("assemble") { // Stop daemons
assertGradleClasspathNotLeaked() ConnectorServices.reset()
Thread.sleep(2000) // Kotlin daemon stops itself after 1 sec of Gradle daemon
clientFiles.forEach { clientFile ->
assertFileNotExists(clientFile)
}
}
} }
} }
private fun CompiledProject.assertGradleClasspathNotLeaked() { @DisplayName("Gradle build classpath should not leak into Kotlin daemon")
assertContains("Kotlin compiler classpath:") @GradleTest
val daemonClasspath = output.lineSequence().find { fun testGradleBuildClasspathShouldNotBeLeakedIntoDaemonClasspath(gradleVersion: GradleVersion) {
it.contains("Kotlin compiler classpath:") project("kotlinProject", gradleVersion) {
}!! build("assemble") {
assertGradleClasspathNotLeaked()
}
}
}
private fun BuildResult.assertGradleClasspathNotLeaked() {
assertOutputContains("Kotlin compiler classpath:")
val daemonClasspath = output
.lineSequence()
.first {
it.contains("Kotlin compiler classpath:")
}
assertTrue("Daemon classpath contains embeddable daemon jar leaked from Gradle dist classpath: $daemonClasspath") { assertTrue("Daemon classpath contains embeddable daemon jar leaked from Gradle dist classpath: $daemonClasspath") {
!daemonClasspath.contains(".gradle/wrapper/dists") !daemonClasspath.contains(".gradle/wrapper/dists")
} }
} }
private fun BuildResult.assertKotlinDaemonReusesOnlyOneSession() {
val createdSessions = output.findAllStringsPrefixed(CREATED_SESSION_FILE_PREFIX)
assert(createdSessions.size == 1) {
"""
|${printBuildOutput()}
|
|Created multiple sessions per build: ${createdSessions.joinToString()}
""".trimMargin()
}
val existingSessions = output.findAllStringsPrefixed(EXISTING_SESSION_FILE_PREFIX)
assert(createdSessions == createdSessions) {
"""
|${printBuildOutput()}
|
|Existing sessions don't match created sessions for two module projects.
|Created sessions:
|${createdSessions.joinToString(separator = "\n")}
|Existing sessions:
|${existingSessions.joinToString(separator = "\n")}
""".trimMargin()
}
val deletedSessions = output.findAllStringsPrefixed(DELETED_SESSION_FILE_PREFIX)
assert(createdSessions == deletedSessions) {
"""
|${printBuildOutput()}
|
|Deleted sessions don't match created sessions.
|Created sessions:
|${createdSessions.joinToString(separator = "\n")}
|Deleted sessions:
|${deletedSessions.joinToString(separator = "\n")}
""".trimMargin()
}
}
private fun String.findAllStringsPrefixed(prefix: String): List<String> =
("$prefix([^\\r\\n]*)").toRegex().findAll(this).map { it.groupValues[1] }.toList()
} }