Skip to content

Commit 8743f41

Browse files
committed
Add and use ProcessUtil
1 parent d408714 commit 8743f41

File tree

2 files changed

+104
-12
lines changed

2 files changed

+104
-12
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import java.io.Reader
2+
import java.time.Duration
3+
import java.util.concurrent.TimeUnit
4+
import kotlin.concurrent.thread
5+
6+
object ProcessUtil {
7+
data class Result(
8+
val exitCode: Int,
9+
val stdout: String,
10+
val stderr: String,
11+
val isTimeout: Boolean, // true if the process was terminated due to timeout
12+
)
13+
14+
fun run(
15+
command: List<String>,
16+
input: String? = null,
17+
timeout: Duration? = null,
18+
builder: ProcessBuilder.() -> Unit = {},
19+
): Result {
20+
val reader = input?.reader() ?: "".reader()
21+
return run(command, reader, timeout, builder)
22+
}
23+
24+
fun run(
25+
command: List<String>,
26+
input: Reader,
27+
timeout: Duration? = null,
28+
builder: ProcessBuilder.() -> Unit = {},
29+
): Result {
30+
val process = ProcessBuilder(command).apply(builder).start()
31+
return communicate(process, input, timeout)
32+
}
33+
34+
private fun communicate(
35+
process: Process,
36+
input: Reader,
37+
timeout: Duration?,
38+
): Result {
39+
// Handle process input (stdin)
40+
val stdinThread = thread {
41+
process.outputStream.bufferedWriter().use { writer ->
42+
input.copyTo(writer)
43+
writer.flush()
44+
}
45+
}
46+
47+
// Capture process output (stdout)
48+
val stdout = StringBuilder()
49+
val stdoutThread = thread {
50+
process.inputStream.bufferedReader().useLines { lines ->
51+
lines.forEach { stdout.appendLine(it) }
52+
}
53+
}
54+
55+
// Capture process error output (stderr)
56+
val stderr = StringBuilder()
57+
val stderrThread = thread {
58+
process.errorStream.bufferedReader().useLines { lines ->
59+
lines.forEach { stderr.appendLine(it) }
60+
}
61+
}
62+
63+
// Start all threads
64+
stdinThread.start()
65+
stdoutThread.start()
66+
stderrThread.start()
67+
68+
// Wait for completion
69+
val isTimeout = if (timeout != null) {
70+
!process.waitFor(timeout.toMillis(), TimeUnit.MILLISECONDS)
71+
} else {
72+
process.waitFor()
73+
false
74+
}
75+
76+
// If timeout occurred, destroy the process forcibly
77+
if (isTimeout) {
78+
process.destroyForcibly()
79+
}
80+
81+
// Wait for stream threads to finish
82+
stdinThread.join()
83+
stdoutThread.join()
84+
stderrThread.join()
85+
86+
return Result(
87+
exitCode = if (isTimeout) -1 else process.exitValue(),
88+
stdout = stdout.toString(),
89+
stderr = stderr.toString(),
90+
isTimeout = isTimeout
91+
)
92+
}
93+
}

jacodb-ets/build.gradle.kts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,21 +93,20 @@ tasks.register("generateTestResources") {
9393
"-t",
9494
)
9595
println("Running: '${cmd.joinToString(" ")}'")
96-
val process = ProcessBuilder(cmd).directory(resources).start()
97-
val ok = process.waitFor(10, TimeUnit.MINUTES)
98-
99-
val stdout = process.inputStream.bufferedReader().readText().trim()
100-
if (stdout.isNotBlank()) {
101-
println("[STDOUT]:\n--------\n$stdout\n--------")
96+
val result = ProcessUtil.run(cmd) {
97+
directory(resources)
10298
}
103-
val stderr = process.errorStream.bufferedReader().readText().trim()
104-
if (stderr.isNotBlank()) {
105-
println("[STDERR]:\n--------\n$stderr\n--------")
99+
if (result.stdout.isNotBlank()) {
100+
println("[STDOUT]:\n--------\n${result.stdout}\n--------")
106101
}
107-
108-
if (!ok) {
102+
if (result.stderr.isNotBlank()) {
103+
println("[STDERR]:\n--------\n${result.stderr}\n--------")
104+
}
105+
if (result.isTimeout) {
109106
println("Timeout!")
110-
process.destroy()
107+
}
108+
if (result.exitCode != 0) {
109+
println("Exit code: ${result.exitCode}")
111110
}
112111

113112
println("Done generating test resources in %.1fs".format((System.currentTimeMillis() - startTime) / 1000.0))

0 commit comments

Comments
 (0)