From 81cedd49009f16fde1c676137c823a0331f879e2 Mon Sep 17 00:00:00 2001 From: Said Boudjelda Date: Sat, 17 Oct 2026 21:47:11 +0200 Subject: [PATCH] test(chaos): ProbeExecutorTest's exec stub keeps the stream open until the client has read the exit status cmdProbeComparesTheOutputOfACommandThatExitedZero failed PR #374's CI with "ended without an exit status". The cause is in fabric8's mockwebserver. Its WebSocketSession queues the open messages one at a time, and its executor closes the socket as soon as no message is pending. When it sent the output before the status was queued, it closed the socket first, and exitCode() completed with null. waitFor(50) did not help, because a ready-made StatusStreamMessage keeps a delay of 0. On main, the two exit-status tests failed 1 run in 1,000. execWithStatus now also expects a client message that never comes. The mock keeps a socket open while it waits for one, so the client closes the socket itself once it has read the status: 0 failures in 4,000 runs. ProbeExecutor is unchanged. fabric8's Vert.x socket reports the close in frame order, so a status the API server sends before its close frame is always read first. --- .../com/bmscomp/kates/chaos/ProbeExecutorTest.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/kates/src/test/java/com/bmscomp/kates/chaos/ProbeExecutorTest.java b/kates/src/test/java/com/bmscomp/kates/chaos/ProbeExecutorTest.java index c259a734..aa2c16d7 100644 --- a/kates/src/test/java/com/bmscomp/kates/chaos/ProbeExecutorTest.java +++ b/kates/src/test/java/com/bmscomp/kates/chaos/ProbeExecutorTest.java @@ -402,9 +402,12 @@ private void exec(String pod, Object... messages) { } /** - * Answers the exec of {@link #cmdProbe} with {@code messages} and then a status frame. + * Answers the exec of {@link #cmdProbe} with {@code messages} and then a status frame, and leaves + * the stream open: the client closes it once it has read the status. * - *

Exec status is emitted last; a small wait keeps websocket close from racing it. + *

The mock closes a stream as soon as no message is pending, and it queues the messages one at a + * time, so it could close after sending the first, before the status was queued (1 run in 1,000). A + * client message it waits for, which never comes, keeps it from closing. */ private void execWithStatus(String pod, int exitCode, Object... messages) { server.expect() @@ -412,8 +415,11 @@ private void execWithStatus(String pod, int exitCode, Object... messages) { .withPath(execPath(pod)) .andUpgradeToWebSocket() .open(messages) - .waitFor(50) + .immediately() .andEmit(new StatusStreamMessage(exitCode)) + .expect("never sent") + .andEmit("unused") + .always() .done() .always(); }