[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:
@@ -51,6 +51,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
|
||||||
cli_bc project(path: ':backend.native', configuration: 'cli_bc')
|
cli_bc project(path: ':backend.native', configuration: 'cli_bc')
|
||||||
def updateTestData = true
|
def updateTestData = true
|
||||||
if (project.hasProperty("kotlinProjectPath")) {
|
if (project.hasProperty("kotlinProjectPath")) {
|
||||||
|
|||||||
+1
@@ -15,6 +15,7 @@ object DistProperties {
|
|||||||
private val konancDriver = if (HostManager.host.family == Family.MINGW) "konanc.bat" else "konanc"
|
private val konancDriver = if (HostManager.host.family == Family.MINGW) "konanc.bat" else "konanc"
|
||||||
val konanc: Path = dist.resolve("bin/$konancDriver")
|
val konanc: Path = dist.resolve("bin/$konancDriver")
|
||||||
val lldb: Path = Paths.get("lldb")
|
val lldb: Path = Paths.get("lldb")
|
||||||
|
val devToolsSecurity: Path = Paths.get("DevToolsSecurity")
|
||||||
val lldbPrettyPrinters: Path = dist.resolve("tools/konan_lldb.py")
|
val lldbPrettyPrinters: Path = dist.resolve("tools/konan_lldb.py")
|
||||||
|
|
||||||
private fun requireProp(name: String): String
|
private fun requireProp(name: String): String
|
||||||
|
|||||||
+47
-12
@@ -5,9 +5,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.native.test.debugger
|
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 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.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class ToolDriver(
|
class ToolDriver(
|
||||||
@@ -31,7 +40,7 @@ class ToolDriver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun runLldb(program: Path, commands: List<String>): String {
|
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) }
|
commands.flatMap { listOf("-o", it) }
|
||||||
return subprocess(lldb, program.toString(), "-b", *args.toTypedArray())
|
return subprocess(lldb, program.toString(), "-b", *args.toTypedArray())
|
||||||
.thrownIfFailed()
|
.thrownIfFailed()
|
||||||
@@ -63,15 +72,41 @@ data class ProcessOutput(
|
|||||||
fun subprocess(program: Path, vararg args: String): ProcessOutput {
|
fun subprocess(program: Path, vararg args: String): ProcessOutput {
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
val process = ProcessBuilder(program.toString(), *args).start()
|
val process = ProcessBuilder(program.toString(), *args).start()
|
||||||
val outReader = process.inputStream.bufferedReader()
|
val out = GlobalScope.async(Dispatchers.IO) {
|
||||||
val errReader = process.errorStream.bufferedReader()
|
readStream(process, process.inputStream.buffered())
|
||||||
|
|
||||||
val timeout = 5L
|
|
||||||
if (!process.waitFor(timeout, TimeUnit.MINUTES)) {
|
|
||||||
process.destroy()
|
|
||||||
error("$program is running for more then $timeout minutes")
|
|
||||||
}
|
}
|
||||||
val stdout = outReader.readText()
|
|
||||||
val stderr = errReader.readText()
|
val err = GlobalScope.async(Dispatchers.IO) {
|
||||||
return ProcessOutput(program, process, stdout, stderr, System.currentTimeMillis() - start)
|
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())
|
||||||
|
}
|
||||||
|
|||||||
+18
@@ -62,6 +62,15 @@ fun lldbTest(@Language("kotlin") programText: String, lldbSession: String) {
|
|||||||
return
|
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 lldbSessionSpec = LldbSessionSpecification.parse(lldbSession)
|
||||||
|
|
||||||
val tmpdir = Files.createTempDirectory("debugger_test")
|
val tmpdir = Files.createTempDirectory("debugger_test")
|
||||||
@@ -76,6 +85,15 @@ fun lldbTest(@Language("kotlin") programText: String, lldbSession: String) {
|
|||||||
lldbSessionSpec.match(result)
|
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 {
|
private val haveLldb: Boolean by lazy {
|
||||||
val lldbVersion = try {
|
val lldbVersion = try {
|
||||||
subprocess(DistProperties.lldb, "-version")
|
subprocess(DistProperties.lldb, "-version")
|
||||||
|
|||||||
Reference in New Issue
Block a user