[test][debugger] make reading of std{out,err} asynchroneous

- this fix issue on big amount data in stdout or stderr, making program hanging on waiting when appear some room in stdout/stderr buffer

[test][debugger] DevToolsSecurity check and stdio/stderr async processing
This commit is contained in:
Vasily Levchenko
2020-06-29 13:28:46 +02:00
parent c1f0a6048b
commit a92e428289
4 changed files with 67 additions and 12 deletions
+1
View File
@@ -51,6 +51,7 @@ repositories {
}
dependencies {
compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
cli_bc project(path: ':backend.native', configuration: 'cli_bc')
def updateTestData = true
if (project.hasProperty("kotlinProjectPath")) {
@@ -15,6 +15,7 @@ object DistProperties {
private val konancDriver = if (HostManager.host.family == Family.MINGW) "konanc.bat" else "konanc"
val konanc: Path = dist.resolve("bin/$konancDriver")
val lldb: Path = Paths.get("lldb")
val devToolsSecurity: Path = Paths.get("DevToolsSecurity")
val lldbPrettyPrinters: Path = dist.resolve("tools/konan_lldb.py")
private fun requireProp(name: String): String
@@ -5,9 +5,18 @@
package org.jetbrains.kotlin.native.test.debugger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.cli.bc.K2Native
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.io.StringReader
import java.lang.StringBuilder
import java.nio.file.Files
import java.nio.file.Path
import java.time.temporal.ChronoUnit
import java.util.concurrent.TimeUnit
class ToolDriver(
@@ -31,7 +40,7 @@ class ToolDriver(
}
fun runLldb(program: Path, commands: List<String>): String {
val args = listOf("-o", "command script import \"$lldbPrettyPrinters\"") +
val args = listOf("-b", "-o", "command script import \"$lldbPrettyPrinters\"") +
commands.flatMap { listOf("-o", it) }
return subprocess(lldb, program.toString(), "-b", *args.toTypedArray())
.thrownIfFailed()
@@ -63,15 +72,41 @@ data class ProcessOutput(
fun subprocess(program: Path, vararg args: String): ProcessOutput {
val start = System.currentTimeMillis()
val process = ProcessBuilder(program.toString(), *args).start()
val outReader = process.inputStream.bufferedReader()
val errReader = process.errorStream.bufferedReader()
val timeout = 5L
if (!process.waitFor(timeout, TimeUnit.MINUTES)) {
process.destroy()
error("$program is running for more then $timeout minutes")
val out = GlobalScope.async(Dispatchers.IO) {
readStream(process, process.inputStream.buffered())
}
val stdout = outReader.readText()
val stderr = errReader.readText()
return ProcessOutput(program, process, stdout, stderr, System.currentTimeMillis() - start)
}
val err = GlobalScope.async(Dispatchers.IO) {
readStream(process, process.errorStream.buffered())
}
return runBlocking {
try {
val status = process.waitFor(5L, TimeUnit.MINUTES)
if (!status) {
out.cancel()
err.cancel()
error("$program timeouted")
}
}catch (e:Exception) {
out.cancel()
err.cancel()
error(e)
}
ProcessOutput(program, process, out.await(), err.await(), System.currentTimeMillis() - start)
}
}
private fun readStream(process: Process, stream: InputStream): String {
var size = 4096
val buffer = ByteArray(size) { 0 }
val sunk = ByteArrayOutputStream()
while (true) {
size = stream.read(buffer, 0, buffer.size)
if (size < 0 && !process.isAlive)
break
if (size > 0)
sunk.write(buffer, 0, size)
}
return String(sunk.toByteArray())
}
@@ -62,6 +62,15 @@ fun lldbTest(@Language("kotlin") programText: String, lldbSession: String) {
return
}
if (!isOsxDevToolsEnabled) {
println("""Development tools aren't available.
|Please consider to execute:
| ${DistProperties.devToolsSecurity} -enable
|or
| csrutil disable
|to run lldb tests""".trimMargin())
return
}
val lldbSessionSpec = LldbSessionSpecification.parse(lldbSession)
val tmpdir = Files.createTempDirectory("debugger_test")
@@ -76,6 +85,15 @@ fun lldbTest(@Language("kotlin") programText: String, lldbSession: String) {
lldbSessionSpec.match(result)
}
private val isOsxDevToolsEnabled: Boolean by lazy {
//TODO: add OSX checks.
val rawStatus = subprocess(DistProperties.devToolsSecurity, "-status")
println("> status: $rawStatus")
val r = Regex("^.*\\ (enabled|disabled).$")
r.find(rawStatus.stdout)?.destructured?.component1() == "enabled"
}
private val haveLldb: Boolean by lazy {
val lldbVersion = try {
subprocess(DistProperties.lldb, "-version")