Enable assertions in Kotlin Compile Daemon process

#KT-32992 Fixed
This commit is contained in:
Alexey Tsvetkov
2019-07-27 19:00:38 +03:00
parent 560f1483e8
commit 317c39f27d
7 changed files with 127 additions and 21 deletions
@@ -314,9 +314,14 @@ fun configureDaemonJVMOptions(opts: DaemonJVMOptions,
System.getProperty(COMPILE_DAEMON_LOG_PATH_PROPERTY)?.let { opts.jvmParams.add("D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"$it\"") } System.getProperty(COMPILE_DAEMON_LOG_PATH_PROPERTY)?.let { opts.jvmParams.add("D$COMPILE_DAEMON_LOG_PATH_PROPERTY=\"$it\"") }
System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY)?.let { opts.jvmParams.add("D$KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY") } System.getProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY)?.let { opts.jvmParams.add("D$KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY") }
} }
if (opts.jvmParams.none { it.matches(jvmAssertArgsRegex) }) {
opts.jvmParams.add("ea")
}
return opts return opts
} }
private val jvmAssertArgsRegex = "(es?a|ds?a|(enable|disable)(system)?assertions)(${'$'}|:)".toRegex()
fun configureDaemonJVMOptions(vararg additionalParams: String, fun configureDaemonJVMOptions(vararg additionalParams: String,
inheritMemoryLimits: Boolean, inheritMemoryLimits: Boolean,
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.daemon
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt import com.intellij.openapi.util.io.FileUtilRt
import junit.framework.Assert
import junit.framework.TestCase import junit.framework.TestCase
import org.jetbrains.kotlin.cli.AbstractCliTest import org.jetbrains.kotlin.cli.AbstractCliTest
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
@@ -187,6 +188,53 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
} }
} }
fun testDaemonAssertsOptions() {
val allAssetionsArgs = setOf(
"-ea", "-enableassertions",
"-da", "-disableassertions",
"-esa", "-enablesystemassertions",
"-dsa", "-disablesystemassertions"
)
fun assertionsJvmArgs() = configureDaemonJVMOptions(
inheritMemoryLimits = true,
inheritOtherJvmOptions = false,
inheritAdditionalProperties = true
).mappers.flatMap { it.toArgs("-") }.filter { it in allAssetionsArgs }.joinToString(", ")
for (assertArgValue in allAssetionsArgs) {
withDaemonJvmOptionsSetTo(assertArgValue) {
Assert.assertEquals(assertArgValue, assertionsJvmArgs())
}
}
withDaemonJvmOptionsSetTo(null) {
Assert.assertEquals("-ea", assertionsJvmArgs())
}
}
private fun withDaemonJvmOptionsSetTo(newValue: String?, fn: () -> Unit) {
val backup = getAndSetSystemProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY, newValue)
try {
fn()
} finally {
getAndSetSystemProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY, backup)
}
}
private fun getAndSetSystemProperty(property: String, newValue: String?): String? {
val oldValue = System.getProperty(property)
if (newValue != null) {
System.setProperty(property, newValue)
} else {
System.clearProperty(property)
}
return oldValue
}
fun testDaemonOptionsParsing() { fun testDaemonOptionsParsing() {
val backupOptions = System.getProperty(COMPILE_DAEMON_OPTIONS_PROPERTY) val backupOptions = System.getProperty(COMPILE_DAEMON_OPTIONS_PROPERTY)
try { try {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.daemon.experimental.integration package org.jetbrains.kotlin.daemon.experimental.integration
import junit.framework.Assert
import junit.framework.TestCase import junit.framework.TestCase
import kotlinx.coroutines.* import kotlinx.coroutines.*
import org.jetbrains.kotlin.cli.AbstractCliTest import org.jetbrains.kotlin.cli.AbstractCliTest
@@ -264,6 +265,53 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
} }
} }
fun ignore_testDaemonAssertsOptions() {
val allAssetionsArgs = setOf(
"-ea", "-enableassertions",
"-da", "-disableassertions",
"-esa", "-enablesystemassertions",
"-dsa", "-disablesystemassertions"
)
fun assertionsJvmArgs() = configureDaemonJVMOptions(
inheritMemoryLimits = true,
inheritOtherJvmOptions = false,
inheritAdditionalProperties = true
).mappers.flatMap { it.toArgs("-") }.filter { it in allAssetionsArgs }.joinToString(", ")
for (assertArgValue in allAssetionsArgs) {
withDaemonJvmOptionsSetTo(assertArgValue) {
Assert.assertEquals(assertArgValue, assertionsJvmArgs())
}
}
withDaemonJvmOptionsSetTo(null) {
Assert.assertEquals("-ea", assertionsJvmArgs())
}
}
private fun withDaemonJvmOptionsSetTo(newValue: String?, fn: () -> Unit) {
val backup = getAndSetSystemProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY, newValue)
try {
fn()
} finally {
getAndSetSystemProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY, backup)
}
}
private fun getAndSetSystemProperty(property: String, newValue: String?): String? {
val oldValue = System.getProperty(property)
if (newValue != null) {
System.setProperty(property, newValue)
} else {
System.clearProperty(property)
}
return oldValue
}
fun ignore_testDaemonOptionsParsing() { fun ignore_testDaemonOptionsParsing() {
val backupOptions = System.getProperty(COMPILE_DAEMON_OPTIONS_PROPERTY) val backupOptions = System.getProperty(COMPILE_DAEMON_OPTIONS_PROPERTY)
try { try {
@@ -734,7 +734,6 @@ abstract class BaseGradleIT {
// Workaround: override a console type set in the user machine gradle.properties (since Gradle 4.3): // Workaround: override a console type set in the user machine gradle.properties (since Gradle 4.3):
add("--console=plain") add("--console=plain")
add("-Dkotlin.daemon.ea=true")
addAll(options.freeCommandLineArgs) addAll(options.freeCommandLineArgs)
} }
@@ -1,6 +1,5 @@
package org.jetbrains.kotlin.gradle package org.jetbrains.kotlin.gradle
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.util.checkedReplace import org.jetbrains.kotlin.gradle.util.checkedReplace
import org.jetbrains.kotlin.gradle.util.getFileByName import org.jetbrains.kotlin.gradle.util.getFileByName
import org.jetbrains.kotlin.gradle.util.modify import org.jetbrains.kotlin.gradle.util.modify
@@ -66,23 +65,14 @@ abstract class ExecutionStrategyIT : BaseGradleIT() {
val strategyCLIArg = "-Dkotlin.compiler.execution.strategy=$executionStrategy" val strategyCLIArg = "-Dkotlin.compiler.execution.strategy=$executionStrategy"
val finishMessage = "Finished executing kotlin compiler using $executionStrategy strategy" val finishMessage = "Finished executing kotlin compiler using $executionStrategy strategy"
val isGradleAtLeast50 = project.testGradleVersionAtLeast("5.0")
project.build("build", strategyCLIArg) { project.build("build", strategyCLIArg) {
assertSuccessful() assertSuccessful()
assertContains(finishMessage) assertContains(finishMessage)
checkOutput() checkOutput()
assertNoWarnings() assertNoWarnings()
if (executionStrategy == "daemon" && isGradleAtLeast50) { if (executionStrategy == "daemon") {
val m = "Kotlin compile daemon JVM options: \\[(.*?)\\]".toRegex().find(output) checkCompileDaemon()
?: error("Could not find Kotlin compile daemon JVM options in Gradle's output")
val kotlinDaemonJvmArgs = m.groupValues[1].split(",").map { it.trim() }
val maxMetaspaceArg = "-XX:MaxMetaspaceSize=256m"
Assert.assertTrue(
"Kotlin daemon JVM args do not contain '$maxMetaspaceArg': $kotlinDaemonJvmArgs",
maxMetaspaceArg in kotlinDaemonJvmArgs
)
} }
} }
@@ -98,6 +88,28 @@ abstract class ExecutionStrategyIT : BaseGradleIT() {
} }
} }
private fun CompiledProject.checkCompileDaemon() {
val isGradleAtLeast50 = project.testGradleVersionAtLeast("5.0")
val m = "Kotlin compile daemon JVM options: \\[(.*?)\\]".toRegex().find(output)
?: error("Could not find Kotlin compile daemon JVM options in Gradle's output")
val kotlinDaemonJvmArgs = m.groupValues[1].split(",").mapTo(LinkedHashSet()) { it.trim() }
fun assertDaemonArgsContain(arg: String) {
Assert.assertTrue(
"Expected '$arg' in kotlin daemon JVM args, got: $kotlinDaemonJvmArgs",
arg in kotlinDaemonJvmArgs
)
}
if (isGradleAtLeast50) {
// 256m is the default value for Gradle 5.0+
assertDaemonArgsContain("-XX:MaxMetaspaceSize=256m")
}
assertDaemonArgsContain("-ea")
}
protected open fun setupProject(project: Project) { protected open fun setupProject(project: Project) {
project.setupWorkingDir() project.setupWorkingDir()
File(project.projectDir, "app/build.gradle").appendText( File(project.projectDir, "app/build.gradle").appendText(
@@ -153,14 +153,10 @@ internal open class GradleCompilerRunner(protected val task: Task) {
sessionIsAliveFlagFile: File, sessionIsAliveFlagFile: File,
compilerFullClasspath: List<File>, compilerFullClasspath: List<File>,
messageCollector: MessageCollector, messageCollector: MessageCollector,
isDebugEnabled: Boolean, isDebugEnabled: Boolean
enableAssertions: Boolean
): CompileServiceSession? { ): CompileServiceSession? {
val compilerId = CompilerId.makeCompilerId(compilerFullClasspath) val compilerId = CompilerId.makeCompilerId(compilerFullClasspath)
val additionalJvmParams = arrayListOf<String>() val additionalJvmParams = arrayListOf<String>()
if (enableAssertions) {
additionalJvmParams.add("ea")
}
return KotlinCompilerRunnerUtils.newDaemonConnection( return KotlinCompilerRunnerUtils.newDaemonConnection(
compilerId, clientIsAliveFlagFile, sessionIsAliveFlagFile, compilerId, clientIsAliveFlagFile, sessionIsAliveFlagFile,
messageCollector = messageCollector, messageCollector = messageCollector,
@@ -150,7 +150,6 @@ internal class GradleKotlinCompilerWork @Inject constructor(
private fun compileWithDaemon(messageCollector: MessageCollector): ExitCode? { private fun compileWithDaemon(messageCollector: MessageCollector): ExitCode? {
val isDebugEnabled = log.isDebugEnabled || System.getProperty("kotlin.daemon.debug.log")?.toBoolean() ?: true val isDebugEnabled = log.isDebugEnabled || System.getProperty("kotlin.daemon.debug.log")?.toBoolean() ?: true
val enableAssertions = System.getProperty("kotlin.daemon.ea")?.toBoolean() ?: false
val daemonMessageCollector = val daemonMessageCollector =
if (isDebugEnabled) messageCollector else MessageCollector.NONE if (isDebugEnabled) messageCollector else MessageCollector.NONE
@@ -161,8 +160,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
sessionFlagFile, sessionFlagFile,
compilerFullClasspath, compilerFullClasspath,
daemonMessageCollector, daemonMessageCollector,
isDebugEnabled = isDebugEnabled, isDebugEnabled = isDebugEnabled
enableAssertions = enableAssertions
) )
} catch (e: Throwable) { } catch (e: Throwable) {
log.error("Caught an exception trying to connect to Kotlin Daemon:") log.error("Caught an exception trying to connect to Kotlin Daemon:")