hyf

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

commit 951b345c7aff3c88fb5d376302e00538641a1a1a
parent 2b74f41d3a6ea63706609e43fc6cc4098b3c5867
Author: triesap <tyson@radroots.org>
Date:   Tue, 22 Sep 2026 22:30:51 +0000

test(hyf): prove stdio fork rollback and simultaneous stream pressure

- Build argv before owning descriptors so no pre-fork exception window can
  leak the stdio pipes, and exercise the three-pipe fork rollback with an
  injected failure through the same handler as a real fork failure
- Interleave stdout and stderr flooding so concurrent pressure on both
  streams is exercised end to end without deadlock
- 68/68 provider-helper and 7/7 repo-local-process tests pass

Diffstat:
Mtests/parent_lifecycle.mojo | 7++++++-
Mtests/stdio_process_helper.mojo | 6++++--
Mtests/stdio_stderr_flood_entrypoint.mojo | 16++++++++++------
Mtests/test_provider_helpers.mojo | 14++++++++++++++
4 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/tests/parent_lifecycle.mojo b/tests/parent_lifecycle.mojo @@ -78,11 +78,16 @@ struct PipeFds(Copyable, Movable): @fieldwise_init -struct PipeTriple(Movable): +struct PipeTriple(Copyable, Movable): var stdin_pipe: PipeFds var stdout_pipe: PipeFds var stderr_pipe: PipeFds + def __copyinit__(out self, existing: Self): + self.stdin_pipe = existing.stdin_pipe.copy() + self.stdout_pipe = existing.stdout_pipe.copy() + self.stderr_pipe = existing.stderr_pipe.copy() + def close_pipe(pipe: PipeFds): close_fd(pipe.read_fd) diff --git a/tests/stdio_process_helper.mojo b/tests/stdio_process_helper.mojo @@ -152,8 +152,9 @@ def run_stdio_entrypoint_with_deadline( arg1: String, deadline_ms: Int, ) raises -> Value: - var pipes = make_three_pipes() - + # Build argv before owning any descriptors so no exception window can leak + # pipes between creation and the fork; fork failure alone is handled by the + # rollback helper. var command = String("mojo") var include_flag = String("-I") var include_path = String("src") @@ -181,6 +182,7 @@ def run_stdio_entrypoint_with_deadline( process_arg1.as_c_string_slice() ) + var pipes = make_three_pipes() var stdin_read_fd = pipes.stdin_pipe.read_fd var stdin_write_fd = pipes.stdin_pipe.write_fd var stdout_read_fd = pipes.stdout_pipe.read_fd diff --git a/tests/stdio_stderr_flood_entrypoint.mojo b/tests/stdio_stderr_flood_entrypoint.mojo @@ -1,7 +1,7 @@ -"""Test-only stdio entrypoint that floods stderr before reading stdin. +"""Test-only stdio entrypoint that floods stdout and stderr interleaved. -Exercises LC04: the parent must drain stderr concurrently with writing the -request instead of deadlocking on a full stderr pipe, and must bound the +Exercises LC04: the parent must drain stdout and stderr concurrently with +writing the request instead of deadlocking on a full pipe, and must bound the diagnostics it retains with a distinct overflow cause. """ @@ -9,9 +9,13 @@ from std.sys import stderr def main(): - var chunk = String("") + var out_chunk = String("") for _ in range(1000): - chunk += "e" + out_chunk += "o" + var err_chunk = String("") + for _ in range(1000): + err_chunk += "e" for _ in range(100): - print(chunk, file=stderr) + print(out_chunk) + print(err_chunk, file=stderr) print('{"ok":true}') diff --git a/tests/test_provider_helpers.mojo b/tests/test_provider_helpers.mojo @@ -21,6 +21,7 @@ from parent_lifecycle import ( descriptor_census, dup2_fd, fork_owned_or_close, + fork_owned_or_close3, fork_pid, make_pipe, make_three_pipes, @@ -1279,6 +1280,19 @@ def test_fork_failure_closes_owned_pipes() raises: assert_equal(open_fd_count_checked(), before) +def test_stdio_fork_failure_closes_all_owned_pipes() raises: + # LC01: the stdio helper's fork failure must close all three pipe pairs. + var before = open_fd_count_checked() + var pipes = make_three_pipes() + var message = "" + try: + _ = fork_owned_or_close3(pipes.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,