Skip to content

Commit 2f0a157

Browse files
committed
Improve timeout tests with safety harness
Removed duplicate sleep-only timeout tests. Added withTimeout to prevent tests from hanging if fix breaks. Tests now verify partial output capture.
1 parent 275dcf3 commit 2f0a157

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

agents/agents-ext/src/jvmTest/kotlin/ai/koog/agents/ext/tool/shell/ExecuteShellCommandToolJvmTest.kt

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import kotlinx.coroutines.delay
66
import kotlinx.coroutines.launch
77
import kotlinx.coroutines.runBlocking
88
import org.junit.jupiter.api.RepeatedTest
9+
import kotlinx.coroutines.withTimeout
910
import org.junit.jupiter.api.Test
1011
import org.junit.jupiter.api.condition.EnabledOnOs
1112
import org.junit.jupiter.api.condition.OS
@@ -327,33 +328,47 @@ class ExecuteShellCommandToolJvmTest {
327328
fun `command with partial output times out`() = runBlocking {
328329
val result: ExecuteShellCommandTool.Result
329330
val executionTimeMs = measureTimeMillis {
330-
result = executeShellCommand("for i in {1..3}; do echo \$i; sleep 1; done", timeoutSeconds = 1)
331+
result = withTimeout(4000L) {
332+
executeShellCommand("for i in {1..10}; do echo \$i; sleep 1; done", timeoutSeconds = 1)
333+
}
331334
}
332335

333-
assertTrue(result.textForLLM().contains("Command timed out after 1 seconds"))
334-
assertTrue(result.textForLLM().startsWith("Command: for i in {1..3}; do echo \$i; sleep 1; done"))
336+
val partialExpected = """
337+
Command: for i in {1..10}; do echo ${'$'}i; sleep 1; done
338+
1
339+
""".trimIndent()
340+
341+
val output = result.textForLLM()
342+
assertTrue(output.contains(partialExpected))
343+
assertTrue(output.contains("Command timed out after 1 seconds"))
335344
assertNull(result.exitCode)
336-
assertTrue(executionTimeMs <= 1200, "Timeout should occur quickly, but took ${executionTimeMs}ms")
345+
assertTrue(executionTimeMs < 3000, "Should timeout at 1s, but took ${executionTimeMs}ms")
337346
}
338347

339348
@Test
340349
@EnabledOnOs(OS.WINDOWS)
341350
fun `command with partial output times out on Windows`() = runBlocking {
342351
val result: ExecuteShellCommandTool.Result
343352
val executionTimeMs = measureTimeMillis {
344-
result = executeShellCommand(
345-
"""cmd /c "echo 1 & echo 2 & echo 3 & powershell -Command Start-Sleep -Seconds 2"""",
346-
timeoutSeconds = 1
347-
)
353+
result = withTimeout(5000L) {
354+
executeShellCommand(
355+
"""cmd /c "echo 1 & echo 2 & echo 3 & timeout 10"""",
356+
timeoutSeconds = 1
357+
)
358+
}
348359
}
349360

350-
assertTrue(result.textForLLM().contains("Command timed out after 1 seconds"))
351-
assertTrue(
352-
result.textForLLM()
353-
.startsWith("Command: cmd /c \"echo 1 & echo 2 & echo 3 & powershell -Command Start-Sleep -Seconds 2\"")
354-
)
361+
val partialExpected = """
362+
Command: cmd /c "echo 1 & echo 2 & echo 3 & timeout 10"
363+
1
364+
365+
""".trimIndent()
366+
367+
val output = result.textForLLM()
368+
assertTrue(output.contains(partialExpected))
369+
assertTrue(output.contains("Command timed out after 1 seconds"))
355370
assertNull(result.exitCode)
356-
assertTrue(executionTimeMs <= 1300, "Timeout should occur quickly, but took ${executionTimeMs}ms")
371+
assertTrue(executionTimeMs < 4000, "Should timeout at 1s, but took ${executionTimeMs}ms")
357372
}
358373

359374
// CANCELLATION TESTS

0 commit comments

Comments
 (0)