Implementing support for running gradle tests with daemon
KT-8487
This commit is contained in:
committed by
Alexey Tsvetkov
parent
9498235407
commit
cde89cb1e8
+83
-45
@@ -1,23 +1,25 @@
|
|||||||
package org.jetbrains.kotlin.gradle
|
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.junit.After
|
||||||
|
import org.junit.AfterClass
|
||||||
|
import org.junit.Before
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.After
|
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNotEquals
|
import kotlin.test.assertNotEquals
|
||||||
import kotlin.test.fail
|
import kotlin.test.fail
|
||||||
import org.gradle.api.logging.LogLevel
|
|
||||||
|
|
||||||
private val SYSTEM_LINE_SEPARATOR = System.getProperty("line.separator")
|
private val SYSTEM_LINE_SEPARATOR = System.getProperty("line.separator")
|
||||||
|
|
||||||
abstract class BaseGradleIT {
|
abstract class BaseGradleIT {
|
||||||
|
|
||||||
private val resourcesRootFile = File("src/test/resources")
|
protected var workingDir = File(".")
|
||||||
private var workingDir = File(".")
|
|
||||||
|
protected open fun defaultBuildOptions(): BuildOptions = BuildOptions(withDaemon = false)
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
@@ -29,30 +31,80 @@ abstract class BaseGradleIT {
|
|||||||
deleteRecursively(workingDir)
|
deleteRecursively(workingDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuildOptions(val withDaemon: Boolean = false)
|
companion object {
|
||||||
|
protected val ranDaemonVersions = hashSetOf<String>()
|
||||||
|
val resourcesRootFile = File("src/test/resources")
|
||||||
|
|
||||||
class Project(val projectName: String, val wrapperVersion: String = "1.4", val minLogLevel: LogLevel = LogLevel.DEBUG)
|
@AfterClass
|
||||||
|
@JvmStatic
|
||||||
|
@Suppress("unused")
|
||||||
|
fun tearDownAll() {
|
||||||
|
ranDaemonVersions.forEach {
|
||||||
|
println("Stopping gradle daemon v$it")
|
||||||
|
stopDaemon(it)
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
val wrapperDir = File(resourcesRootFile, "GradleWrapper-$ver")
|
||||||
|
val cmd = createGradleCommand(arrayListOf("-stop"))
|
||||||
|
createProcess(cmd, wrapperDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createProcess(cmd: List<String>, projectDir: File): Process {
|
||||||
|
val builder = ProcessBuilder(cmd)
|
||||||
|
builder.directory(projectDir)
|
||||||
|
builder.redirectErrorStream(true)
|
||||||
|
return builder.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun prepareDaemon(version: String) {
|
||||||
|
if (version !in ranDaemonVersions) {
|
||||||
|
stopDaemon(version)
|
||||||
|
ranDaemonVersions.add(version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the second parameter is for using with ToolingAPI, that do not like --daemon/--no-daemon options at all
|
||||||
|
data class BuildOptions(val withDaemon: Boolean = false, val daemonOptionSupported: Boolean = true)
|
||||||
|
|
||||||
|
open inner class Project(val projectName: String, val wrapperVersion: String = "1.4", val minLogLevel: LogLevel = LogLevel.DEBUG) {
|
||||||
|
open val resourcesRoot = File(resourcesRootFile, "testProject/$projectName")
|
||||||
|
val projectDir = File(workingDir, projectName)
|
||||||
|
|
||||||
|
open fun setupWorkingDir() {
|
||||||
|
copyRecursively(this.resourcesRoot, workingDir)
|
||||||
|
copyDirRecursively(File(resourcesRootFile, "GradleWrapper-$wrapperVersion"), projectDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CompiledProject(val project: Project, val output: String, val resultCode: Int)
|
class CompiledProject(val project: Project, val output: String, val resultCode: Int)
|
||||||
|
|
||||||
fun Project.setupWorkingDir() {
|
fun Project.build(vararg tasks: String, options: BuildOptions = defaultBuildOptions(), check: CompiledProject.() -> Unit) {
|
||||||
copyRecursively(File(resourcesRootFile, "testProject/$projectName"), workingDir)
|
|
||||||
copyDirRecursively(File(resourcesRootFile, "GradleWrapper-$wrapperVersion"), File(workingDir, projectName))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Project.build(vararg tasks: String, options: BuildOptions = BuildOptions(), check: CompiledProject.() -> Unit) {
|
|
||||||
val cmd = createBuildCommand(tasks, options)
|
val cmd = createBuildCommand(tasks, options)
|
||||||
|
|
||||||
|
if (options.withDaemon) {
|
||||||
|
prepareDaemon(wrapperVersion)
|
||||||
|
}
|
||||||
|
|
||||||
println("<=== Test build: ${this.projectName} $cmd ===>")
|
println("<=== Test build: ${this.projectName} $cmd ===>")
|
||||||
|
|
||||||
runAndCheck(cmd, check)
|
runAndCheck(cmd, check)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stopDaemon(ver: String) {
|
|
||||||
val wrapperDir = File(resourcesRootFile, "GradleWrapper-$ver")
|
|
||||||
val cmd = createGradleCommand(arrayListOf("-stop"))
|
|
||||||
createProcess(cmd, wrapperDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Project.stopDaemon(check: CompiledProject.() -> Unit) {
|
fun Project.stopDaemon(check: CompiledProject.() -> Unit) {
|
||||||
val cmd = createGradleCommand(arrayListOf("-stop"))
|
val cmd = createGradleCommand(arrayListOf("-stop"))
|
||||||
@@ -121,37 +173,23 @@ abstract class BaseGradleIT {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Project.createBuildCommand(params: Array<out String>, options: BuildOptions): List<String> {
|
private fun Project.createBuildCommand(params: Array<out String>, options: BuildOptions): List<String> =
|
||||||
val pathToKotlinPlugin = "-PpathToKotlinPlugin=" + File("local-repo").absolutePath
|
createGradleCommand(createGradleTailParameters(options, params))
|
||||||
val tailParameters = params.asList() +
|
|
||||||
listOf( pathToKotlinPlugin,
|
|
||||||
if (options.withDaemon) "--daemon" else "--no-daemon",
|
|
||||||
"--${minLogLevel.name.toLowerCase()}",
|
|
||||||
"-Pkotlin.gradle.test=true")
|
|
||||||
|
|
||||||
return createGradleCommand(tailParameters)
|
protected fun Project.createGradleTailParameters(options: BuildOptions, params: Array<out String> = arrayOf()): List<String> =
|
||||||
}
|
params.asList() +
|
||||||
|
listOf("-PpathToKotlinPlugin=" + File("local-repo").absolutePath,
|
||||||
private fun createGradleCommand(tailParameters: List<String>): List<String> {
|
if (options.daemonOptionSupported)
|
||||||
return if (isWindows())
|
if (options.withDaemon) "--daemon"
|
||||||
listOf("cmd", "/C", "gradlew.bat") + tailParameters
|
else "--no-daemon"
|
||||||
else
|
else null,
|
||||||
listOf("/bin/bash", "./gradlew") + tailParameters
|
"--stacktrace",
|
||||||
}
|
"--${minLogLevel.name.toLowerCase()}",
|
||||||
|
"-Pkotlin.gradle.test=true")
|
||||||
|
.filterNotNull()
|
||||||
|
|
||||||
private fun String.normalize() = this.lineSequence().joinToString(SYSTEM_LINE_SEPARATOR)
|
private fun String.normalize() = this.lineSequence().joinToString(SYSTEM_LINE_SEPARATOR)
|
||||||
|
|
||||||
private fun isWindows(): Boolean {
|
|
||||||
return System.getProperty("os.name")!!.contains("Windows")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createProcess(cmd: List<String>, projectDir: File): Process {
|
|
||||||
val builder = ProcessBuilder(cmd)
|
|
||||||
builder.directory(projectDir)
|
|
||||||
builder.redirectErrorStream(true)
|
|
||||||
return builder.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun readOutput(process: Process): Pair<String, Int> {
|
private fun readOutput(process: Process): Pair<String, Int> {
|
||||||
fun InputStream.readFully(): String {
|
fun InputStream.readFully(): String {
|
||||||
val text = reader().readText()
|
val text = reader().readText()
|
||||||
|
|||||||
Reference in New Issue
Block a user