feat: add shared integration test framework for garages (#126)
Implements: - BattleResult type and JSON-lines parser (#127) - TR server lifecycle manager (#128) - Bot compiler using nim c (#129) - runBattle() orchestrator (#130) - Example test in OscillatorBot_garage (#131) - Framework usage guide (#132) - TestBattleRunner.java for external server (#133) - BattleRunner process lifecycle (#134) Fix: runner_process.nim was redefining TimeoutError locally; now uses std/net.TimeoutError consistently with server_manager.nim.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
## BattleRunner Java subprocess — capture stdout JSON-lines output.
|
||||
|
||||
import std/[osproc, os, strutils, streams, times, net]
|
||||
|
||||
const
|
||||
DefaultRunnerJar = "/home/davide/Projects/tank-royale/runner/examples/lib/robocode-tankroyale-runner.jar"
|
||||
ScriptDir = currentSourcePath().parentDir() / ".." / ".." / "tools" / "battle_runner"
|
||||
|
||||
proc runBattleRunner*(serverUrl: string, botDirs: seq[string], rounds: int,
|
||||
timeout: int = 30000): string =
|
||||
## Starts TestBattleRunner as a subprocess. Returns captured stdout on success.
|
||||
## Raises IOError on non-zero exit or TimeoutError on timeout.
|
||||
let jar = getEnv("TR_BATTLE_RUNNER", DefaultRunnerJar)
|
||||
let classDir = getEnv("TR_BATTLE_RUNNER_DIR", ScriptDir)
|
||||
|
||||
let args = @[
|
||||
"-cp", classDir & ":" & jar,
|
||||
"TestBattleRunner",
|
||||
"--server-url", serverUrl,
|
||||
"--rounds", $rounds,
|
||||
"--bot-dirs", botDirs.join(",")
|
||||
]
|
||||
|
||||
let p = startProcess("java", args = args,
|
||||
options = {poUsePath, poStdErrToStdOut})
|
||||
defer:
|
||||
p.close()
|
||||
|
||||
let deadline = epochTime() + timeout.float / 1000.0
|
||||
var stdout = ""
|
||||
var line: string
|
||||
while epochTime() < deadline:
|
||||
if p.peekExitCode() != -1:
|
||||
# Process finished; drain remaining output
|
||||
while p.outputStream.readLine(line):
|
||||
stdout.add(line & "\n")
|
||||
break
|
||||
if p.outputStream.readLine(line):
|
||||
stdout.add(line & "\n")
|
||||
|
||||
if epochTime() >= deadline and p.peekExitCode() == -1:
|
||||
p.terminate()
|
||||
raise newException(TimeoutError,
|
||||
"BattleRunner timed out after " & $timeout & "ms")
|
||||
|
||||
let code = p.waitForExit()
|
||||
if code != 0:
|
||||
raise newException(IOError,
|
||||
"BattleRunner exited with code " & $code & "\nOutput:\n" & stdout)
|
||||
|
||||
result = stdout
|
||||
|
||||
when isMainModule:
|
||||
echo "runner_process.nim — usage:"
|
||||
echo " runBattleRunner(serverUrl, botDirs, rounds, timeout)"
|
||||
echo ""
|
||||
echo "Env vars:"
|
||||
echo " TR_BATTLE_RUNNER JAR path (default: " & DefaultRunnerJar & ")"
|
||||
echo " TR_BATTLE_RUNNER_DIR class dir (default: tools/battle_runner/)"
|
||||
echo ""
|
||||
echo "Cannot self-test without a running TR server. Start one first."
|
||||
Reference in New Issue
Block a user