Fix Process.waitFor freeze on windows when gradle daemon is stopped during tests
This commit is contained in:
+11
-43
@@ -2,11 +2,12 @@ package org.jetbrains.kotlin.gradle
|
|||||||
|
|
||||||
import com.google.common.io.Files
|
import com.google.common.io.Files
|
||||||
import org.gradle.api.logging.LogLevel
|
import org.gradle.api.logging.LogLevel
|
||||||
|
import org.jetbrains.kotlin.gradle.util.createGradleCommand
|
||||||
|
import org.jetbrains.kotlin.gradle.util.runProcess
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.AfterClass
|
import org.junit.AfterClass
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
private val SYSTEM_LINE_SEPARATOR = System.getProperty("line.separator")
|
private val SYSTEM_LINE_SEPARATOR = System.getProperty("line.separator")
|
||||||
@@ -42,29 +43,12 @@ abstract class BaseGradleIT {
|
|||||||
ranDaemonVersions.clear()
|
ranDaemonVersions.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createGradleCommand(tailParameters: List<String>): List<String> {
|
|
||||||
return if (isWindows())
|
|
||||||
listOf("cmd", "/C", "gradlew.bat") + tailParameters
|
|
||||||
else
|
|
||||||
listOf("/bin/bash", "./gradlew") + tailParameters
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isWindows(): Boolean {
|
|
||||||
return System.getProperty("os.name")!!.contains("Windows")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stopDaemon(ver: String) {
|
fun stopDaemon(ver: String) {
|
||||||
println("Stopping gradle daemon v$ver")
|
println("Stopping gradle daemon v$ver")
|
||||||
val wrapperDir = File(resourcesRootFile, "GradleWrapper-$ver")
|
val wrapperDir = File(resourcesRootFile, "GradleWrapper-$ver")
|
||||||
val cmd = createGradleCommand(arrayListOf("-stop"))
|
val cmd = createGradleCommand(arrayListOf("-stop"))
|
||||||
createProcess(cmd, wrapperDir).waitFor()
|
val result = runProcess(cmd, wrapperDir)
|
||||||
}
|
assert(result.isSuccessful) { "Could not stop daemon: $result" }
|
||||||
|
|
||||||
fun createProcess(cmd: List<String>, projectDir: File): Process {
|
|
||||||
val builder = ProcessBuilder(cmd)
|
|
||||||
builder.directory(projectDir)
|
|
||||||
builder.redirectErrorStream(true)
|
|
||||||
return builder.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@@ -98,8 +82,9 @@ abstract class BaseGradleIT {
|
|||||||
val kotlinSourcesListRegex = Regex("\\[KOTLIN\\] compile iteration: ([^\\r\\n]*)")
|
val kotlinSourcesListRegex = Regex("\\[KOTLIN\\] compile iteration: ([^\\r\\n]*)")
|
||||||
val javaSourcesListRegex = Regex("\\[DEBUG\\] \\[[^\\]]*JavaCompiler\\] Compiler arguments: ([^\\r\\n]*)")
|
val javaSourcesListRegex = Regex("\\[DEBUG\\] \\[[^\\]]*JavaCompiler\\] Compiler arguments: ([^\\r\\n]*)")
|
||||||
}
|
}
|
||||||
val compiledKotlinSources : Iterable<File> by lazy { kotlinSourcesListRegex.findAll(output).asIterable().flatMap { it.groups[1]!!.value.split(", ").map { File(project.projectDir, it).canonicalFile } } }
|
|
||||||
val compiledJavaSources : Iterable<File> by lazy { javaSourcesListRegex.findAll(output).asIterable().flatMap { it.groups[1]!!.value.split(" ").filter { it.endsWith(".java", ignoreCase = true) }.map { File(it).canonicalFile } } }
|
val compiledKotlinSources: Iterable<File> by lazy { kotlinSourcesListRegex.findAll(output).asIterable().flatMap { it.groups[1]!!.value.split(", ").map { File(project.projectDir, it).canonicalFile } } }
|
||||||
|
val compiledJavaSources: Iterable<File> by lazy { javaSourcesListRegex.findAll(output).asIterable().flatMap { it.groups[1]!!.value.split(" ").filter { it.endsWith(".java", ignoreCase = true) }.map { File(it).canonicalFile } } }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Project.build(vararg tasks: String, options: BuildOptions = defaultBuildOptions(), check: CompiledProject.() -> Unit) {
|
fun Project.build(vararg tasks: String, options: BuildOptions = defaultBuildOptions(), check: CompiledProject.() -> Unit) {
|
||||||
@@ -116,13 +101,12 @@ abstract class BaseGradleIT {
|
|||||||
|
|
||||||
private fun Project.runAndCheck(cmd: List<String>, check: CompiledProject.() -> Unit) {
|
private fun Project.runAndCheck(cmd: List<String>, check: CompiledProject.() -> Unit) {
|
||||||
val projectDir = File(workingDir, projectName)
|
val projectDir = File(workingDir, projectName)
|
||||||
if (!projectDir.exists())
|
if (!projectDir.exists()) {
|
||||||
setupWorkingDir()
|
setupWorkingDir()
|
||||||
|
}
|
||||||
|
|
||||||
val process = createProcess(cmd, projectDir)
|
val result = runProcess(cmd, projectDir)
|
||||||
|
CompiledProject(this, result.output, result.exitCode).check()
|
||||||
val (output, resultCode) = readOutput(process)
|
|
||||||
CompiledProject(this, output, resultCode).check()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CompiledProject.assertSuccessful(): CompiledProject {
|
fun CompiledProject.assertSuccessful(): CompiledProject {
|
||||||
@@ -221,22 +205,6 @@ abstract class BaseGradleIT {
|
|||||||
|
|
||||||
private fun String.normalize() = this.lineSequence().joinToString(SYSTEM_LINE_SEPARATOR)
|
private fun String.normalize() = this.lineSequence().joinToString(SYSTEM_LINE_SEPARATOR)
|
||||||
|
|
||||||
private fun readOutput(process: Process): Pair<String, Int> {
|
|
||||||
fun InputStream.readFully(): String {
|
|
||||||
val text = reader().readText()
|
|
||||||
close()
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
|
|
||||||
val stdout = process.inputStream!!.readFully()
|
|
||||||
System.out.println(stdout)
|
|
||||||
val stderr = process.errorStream!!.readFully()
|
|
||||||
System.err.println(stderr)
|
|
||||||
|
|
||||||
val result = process.waitFor()
|
|
||||||
return stdout to result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copyRecursively(source: File, target: File) {
|
fun copyRecursively(source: File, target: File) {
|
||||||
assertTrue(target.isDirectory)
|
assertTrue(target.isDirectory)
|
||||||
val targetFile = File(target, source.name)
|
val targetFile = File(target, source.name)
|
||||||
|
|||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
package org.jetbrains.kotlin.gradle.util
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class ProcessRunResult(
|
||||||
|
private val cmd: List<String>,
|
||||||
|
private val workingDir: File,
|
||||||
|
val exitCode: Int,
|
||||||
|
val output: String
|
||||||
|
) {
|
||||||
|
val isSuccessful: Boolean
|
||||||
|
get() = exitCode == 0
|
||||||
|
|
||||||
|
override fun toString(): String = """
|
||||||
|
Executing process was ${if (isSuccessful) "successful" else "unsuccessful"}
|
||||||
|
Command: ${cmd.joinToString()}
|
||||||
|
Working directory: ${workingDir.absolutePath}
|
||||||
|
Exit code: $exitCode
|
||||||
|
Output: $output
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun runProcess(cmd: List<String>, workingDir: File): ProcessRunResult {
|
||||||
|
val builder = ProcessBuilder(cmd)
|
||||||
|
builder.directory(workingDir)
|
||||||
|
// redirectErrorStream merges stdout and stderr, so it can be get from process.inputStream
|
||||||
|
builder.redirectErrorStream(true)
|
||||||
|
|
||||||
|
val process = builder.start()
|
||||||
|
// important to read inputStream, otherwise the process may hang on some systems
|
||||||
|
val output = process.inputStream!!.bufferedReader().readText()
|
||||||
|
System.out.println(output)
|
||||||
|
val exitCode = process.waitFor()
|
||||||
|
|
||||||
|
return ProcessRunResult(cmd, workingDir, exitCode, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createGradleCommand(tailParameters: List<String>): List<String> {
|
||||||
|
return if (isWindows())
|
||||||
|
listOf("cmd", "/C", "gradlew.bat") + tailParameters
|
||||||
|
else
|
||||||
|
listOf("/bin/bash", "./gradlew") + tailParameters
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isWindows(): Boolean = System.getProperty("os.name")!!.contains("Windows")
|
||||||
Reference in New Issue
Block a user