hyf

Context-aware query service for Radroots
git clone https://radroots.dev/git/hyf.git
Log | Files | Refs | README | LICENSE

commit f31c041d2a0b4aeb1904a4f5187b619280fa8e06
parent cf6325b779deb9dad1192b12eab9f0fc342cf2bb
Author: triesap <tyson@radroots.org>
Date:   Tue, 22 Sep 2026 22:16:45 +0000

test(hyf): prove partial-pipe, fork and duplicate-report cleanup

- Route pipe creation and every fork site through shared rollback handlers so
  a real pipe/fork failure closes the owned descriptors, with injected
  causes exercising the same handler as a real failure
- Reject a second report line as a duplicate_report instead of accepting the
  first as success, with a forged two-line child control
- 67/67 provider-helper tests pass with the affected lanes still green

Diffstat:
Mtests/jev_provider_helper.mojo | 26++++++++++----------------
Mtests/max_local_process_helper.mojo | 18+++++++++---------
Mtests/parent_lifecycle.mojo | 62++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mtests/stdio_process_helper.mojo | 14++------------
Mtests/test_provider_helpers.mojo | 28++++++++++++++++++++++++++++
5 files changed, 99 insertions(+), 49 deletions(-)

diff --git a/tests/jev_provider_helper.mojo b/tests/jev_provider_helper.mojo @@ -20,7 +20,7 @@ from parent_lifecycle import ( child_exit, close_fd, dup2_fd, - fork_pid, + fork_owned_or_close, make_pipe, parse_ready_or_cleanup, set_alarm, @@ -405,7 +405,13 @@ struct SpawnedJevStub(Movable): parsed.requests, parsed.connections, ) - if not report_status_matches_exit( + if self.state.pending != "": + # A second report line after the first is a duplicate/malformed + # report, never a success. + self.state.ok = False + self.state.phase = "parse" + self.state.reason = "duplicate_report" + elif not report_status_matches_exit( status.exited, status.exit_code, parsed.ok ): self.state.ok = False @@ -613,13 +619,7 @@ def _spawn_jev_scripted( ) raises -> SpawnedJevStubAuto: var total = len(scripts) var pipe = make_pipe() - var pid = 0 - try: - pid = fork_pid() - except e: - close_fd(pipe.read_fd) - close_fd(pipe.write_fd) - raise Error("jev stub fork failed: " + String(e)) + var pid = fork_owned_or_close(pipe.copy()) if pid == 0: if dup2_fd(pipe.write_fd, 1) < 0: child_exit(126) @@ -644,13 +644,7 @@ def _spawn_jev_stub( port: Int, mode: String, requests: Int, deadline_ms: Int ) raises -> SpawnedJevStubAuto: var pipe = make_pipe() - var pid = 0 - try: - pid = fork_pid() - except e: - close_fd(pipe.read_fd) - close_fd(pipe.write_fd) - raise Error("jev stub fork failed: " + String(e)) + var pid = fork_owned_or_close(pipe.copy()) if pid == 0: if dup2_fd(pipe.write_fd, 1) < 0: child_exit(126) diff --git a/tests/max_local_process_helper.mojo b/tests/max_local_process_helper.mojo @@ -22,7 +22,7 @@ from parent_lifecycle import ( child_exit, close_fd, dup2_fd, - fork_pid, + fork_owned_or_close, make_pipe, parse_ready_or_cleanup, set_alarm, @@ -510,7 +510,13 @@ struct SpawnedMaxLocalStub(Movable): parsed.requests, parsed.connections, ) - if not report_status_matches_exit( + if self.state.pending != "": + # A second report line after the first is a duplicate/malformed + # report, never a success. + self.state.ok = False + self.state.phase = "parse" + self.state.reason = "duplicate_report" + elif not report_status_matches_exit( status.exited, status.exit_code, parsed.ok ): self.state.ok = False @@ -658,13 +664,7 @@ def _spawn_max_local( deadline_ms: Int, ) raises -> SpawnedMaxLocalStub: var pipe = make_pipe() - var pid = 0 - try: - pid = fork_pid() - except e: - close_fd(pipe.read_fd) - close_fd(pipe.write_fd) - raise Error("max_local stub fork failed: " + String(e)) + var pid = fork_owned_or_close(pipe.copy()) if pid == 0: if dup2_fd(pipe.write_fd, 1) < 0: child_exit(126) diff --git a/tests/parent_lifecycle.mojo b/tests/parent_lifecycle.mojo @@ -84,26 +84,30 @@ struct PipeTriple(Movable): var stderr_pipe: PipeFds -def close_pipe(var pipe: PipeFds): +def close_pipe(pipe: PipeFds): close_fd(pipe.read_fd) close_fd(pipe.write_fd) def make_three_pipes(inject_fail_after: Int = -1) raises -> PipeTriple: - """Create three owned pipes, closing earlier ones if a later one fails. + """Create three owned pipes, closing earlier ones if any creation fails. - ``inject_fail_after`` is a test-only control: when >= 0 the constructor - raises after that many successful pipes, proving the rollback path. + ``inject_fail_after`` is a test-only control: when >= 0 a failure is + raised after that many successful pipes. The injected failure and a real + ``make_pipe`` failure share the same rollback handler. """ var fds = InlineArray[Int, 6](fill=-1) - for index in range(3): - if inject_fail_after >= 0 and index == inject_fail_after: - for slot in range(6): - close_fd(fds[slot]) - raise Error("lifecycle: injected pipe creation failure") - var pipe = make_pipe() - fds[index * 2] = pipe.read_fd - fds[index * 2 + 1] = pipe.write_fd + try: + for index in range(3): + if inject_fail_after >= 0 and index == inject_fail_after: + raise Error("lifecycle: injected pipe creation failure") + var pipe = make_pipe() + fds[index * 2] = pipe.read_fd + fds[index * 2 + 1] = pipe.write_fd + except: + for slot in range(6): + close_fd(fds[slot]) + raise return PipeTriple( PipeFds(fds[0], fds[1]), PipeFds(fds[2], fds[3]), @@ -111,6 +115,40 @@ def make_three_pipes(inject_fail_after: Int = -1) raises -> PipeTriple: ) +def fork_owned_or_close( + pipe: PipeFds, inject_failure: Bool = False +) raises -> Int: + """Fork the owned child, closing both pipe ends if the fork fails. + + A real ``fork`` failure and the test-only injected failure share the same + rollback handler, so partial-startup cleanup is execution-proven. + """ + try: + if inject_failure: + raise Error("lifecycle: injected fork failure") + return fork_pid() + except: + close_pipe(pipe.copy()) + raise + return -1 + + +def fork_owned_or_close3( + pipes: PipeTriple, inject_failure: Bool = False +) raises -> Int: + """Fork the stdio child, closing all three pipe pairs if the fork fails.""" + try: + if inject_failure: + raise Error("lifecycle: injected fork failure") + return fork_pid() + except: + close_pipe(pipes.stdin_pipe.copy()) + close_pipe(pipes.stdout_pipe.copy()) + close_pipe(pipes.stderr_pipe.copy()) + raise + return -1 + + def ignore_sigpipe(): """Ignore SIGPIPE so a peer-close race surfaces as EPIPE, not parent death. diff --git a/tests/stdio_process_helper.mojo b/tests/stdio_process_helper.mojo @@ -26,7 +26,7 @@ from parent_lifecycle import ( child_exit, close_fd, dup2_fd, - fork_pid, + fork_owned_or_close3, make_three_pipes, now_ms, poll_three, @@ -190,17 +190,7 @@ def run_stdio_entrypoint_with_deadline( var command_ptr = command.as_c_string_slice().unsafe_ptr() var argv_ptr = argv.unsafe_ptr() - var pid = 0 - try: - pid = fork_pid() - except e: - close_fd(stdin_read_fd) - close_fd(stdin_write_fd) - close_fd(stdout_read_fd) - close_fd(stdout_write_fd) - close_fd(stderr_read_fd) - close_fd(stderr_write_fd) - raise Error("stdio-entrypoint fork failed: " + String(e)) + var pid = fork_owned_or_close3(pipes) if pid == 0: if dup2_fd(stdin_read_fd, 0) < 0: child_exit(126) diff --git a/tests/test_provider_helpers.mojo b/tests/test_provider_helpers.mojo @@ -20,6 +20,7 @@ from parent_lifecycle import ( close_fd, descriptor_census, dup2_fd, + fork_owned_or_close, fork_pid, make_pipe, make_three_pipes, @@ -1264,6 +1265,33 @@ def test_partial_pipe_failure_rolls_back() raises: assert_equal(open_fd_count_checked(), before) +def test_fork_failure_closes_owned_pipes() raises: + # LC01: a fork failure must close both ends of the owned pipe. + var before = open_fd_count_checked() + var pipe = make_pipe() + var message = "" + try: + _ = fork_owned_or_close(pipe.copy(), True) + except e: + message = String(e) + assert_true(message.find("injected fork failure") >= 0) + assert_equal(open_fd_count_checked(), before) + + +def test_result_truth_rejects_duplicate_report_line() raises: + var stub = _owned_report_child( + 0, + ( + "result ok phase=complete case=- reason=ok requests=1" + " connections=1\nresult ok phase=complete case=- reason=ok" + " requests=1 connections=1\n" + ), + ) + stub.reap() + assert_true(not stub.ok()) + assert_equal(stub.reason(), "duplicate_report") + + def test_cleanup_failure_is_observable() raises: # LC01/D36: cleanup failure must be observable, never silently swallowed. var state = PipedChildState(