57a1915b10
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.
68 lines
1.9 KiB
Nim
68 lines
1.9 KiB
Nim
## TR server lifecycle manager — lazy singleton for integration tests.
|
|
## Start with ensureServer(), query with getServerUrl().
|
|
|
|
import std/[osproc, net, os, strutils, times, streams, exitprocs]
|
|
|
|
const
|
|
DefaultJar = "/home/davide/Projects/tank-royale/server/build/libs/robocode-tankroyale-server-0.35.5-all.jar"
|
|
ReadySignal = "Starting server on port"
|
|
StartupTimeout = 15.0 # seconds
|
|
|
|
var
|
|
serverProc: Process = nil
|
|
serverPort: int = 0
|
|
|
|
proc findFreePort(): int =
|
|
let s = newSocket()
|
|
s.bindAddr(Port(0))
|
|
let (_, port) = s.getLocalAddr()
|
|
result = port.int
|
|
s.close()
|
|
|
|
proc ensureServer*() =
|
|
if serverProc != nil: return
|
|
|
|
let jar = getEnv("TR_SERVER_JAR", DefaultJar)
|
|
if not fileExists(jar):
|
|
raise newException(IOError, "TR server JAR not found: " & jar &
|
|
"\nSet TR_SERVER_JAR env var to override.")
|
|
|
|
serverPort = findFreePort()
|
|
serverProc = startProcess("java",
|
|
args = @["-jar", jar, "--port", $serverPort, "--enable-initial-position"],
|
|
options = {poUsePath, poStdErrToStdOut})
|
|
|
|
exitprocs.addExitProc(proc() =
|
|
if serverProc != nil:
|
|
serverProc.terminate()
|
|
serverProc.close()
|
|
)
|
|
|
|
# Wait for ready signal
|
|
let deadline = epochTime() + StartupTimeout
|
|
var ready = false
|
|
while epochTime() < deadline:
|
|
var line: string
|
|
discard serverProc.outputStream.readLine(line)
|
|
if ReadySignal in line:
|
|
ready = true
|
|
break
|
|
if not ready:
|
|
serverProc.terminate()
|
|
serverProc.close()
|
|
serverProc = nil
|
|
raise newException(TimeoutError, "TR server did not start within " & $StartupTimeout & "s")
|
|
|
|
proc getServerUrl*(): string =
|
|
if serverPort == 0:
|
|
raise newException(CatchableError, "Server not started — call ensureServer() first")
|
|
"ws://localhost:" & $serverPort
|
|
|
|
when isMainModule:
|
|
echo "Starting TR server..."
|
|
ensureServer()
|
|
echo "Server ready at: ", getServerUrl()
|
|
echo "Sleeping 2s then exiting (addExitProc will kill server)..."
|
|
os.sleep(2000)
|
|
echo "Done."
|