hyf

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

commit e7dcfb47d2ae66191784083edd9c889a85411b9a
parent f5a8a94c5c98df3dc98447fff0bed52012cc1b94
Author: triesap <tyson@radroots.org>
Date:   Mon, 21 Sep 2026 19:42:11 +0000

test: expose swallowed failures and qualify harness (C001A)

Diffstat:
Mpixi.toml | 4++++
Atests/harness_canary_assert_fail.mojo | 13+++++++++++++
Atests/harness_canary_error_fail.mojo | 13+++++++++++++
Atests/harness_canary_pass.mojo | 12++++++++++++
Atests/safe_tempdir.mojo | 30++++++++++++++++++++++++++++++
Mtests/stdio_process_helper.mojo | 4++--
Atests/test_harness_self_test.mojo | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtests/test_hyf.mojo | 12++++++------
Mtests/test_persistent_stdio.mojo | 18+++++++++---------
Mtests/test_repo_local_process_contract.mojo | 4++--
Mtests/test_soak.mojo | 4++--
Mtests/test_stdio_contract.mojo | 50+++++++++++++++++++++++++-------------------------
Mtests/test_traceability.mojo | 8++++----
Atools/check_harness_runner_exit.sh | 40++++++++++++++++++++++++++++++++++++++++
14 files changed, 219 insertions(+), 50 deletions(-)

diff --git a/pixi.toml b/pixi.toml @@ -20,6 +20,8 @@ flare = { git = "https://github.com/triesap/mojo_flare.git", rev = "14aa338d8c4f [tasks] run = "mojo run -I src src/main.mojo" test-unit = "mojo -I src tests/test_hyf.mojo" +test-harness = "mojo -I src -I tests tests/test_harness_self_test.mojo" +test-harness-runner-exit = "sh tools/check_harness_runner_exit.sh" test-runtime = "mojo -I src tests/test_runtime_paths.mojo" test-repo-local-process = "mojo -I src tests/test_repo_local_process_contract.mojo" test-stdio = "mojo -I src tests/test_stdio_contract.mojo" @@ -49,6 +51,8 @@ test-runtime-contract = { depends-on = [ ] } test = { depends-on = [ "test-unit", + "test-harness", + "test-harness-runner-exit", "test-domain", "test-assist", "test-jev", diff --git a/tests/harness_canary_assert_fail.mojo b/tests/harness_canary_assert_fail.mojo @@ -0,0 +1,13 @@ +from std.testing import TestSuite, assert_true + +from safe_tempdir import SafeTempDir + + +def test_canary_assertion_fails() raises: + with SafeTempDir() as temp_dir: + _ = temp_dir + assert_true(False) + + +def main() raises: + TestSuite.discover_tests[__functions_in_module()]().run() diff --git a/tests/harness_canary_error_fail.mojo b/tests/harness_canary_error_fail.mojo @@ -0,0 +1,13 @@ +from std.testing import TestSuite + +from safe_tempdir import SafeTempDir + + +def test_canary_generic_error_fails() raises: + with SafeTempDir() as temp_dir: + _ = temp_dir + raise Error("intentional harness canary error") + + +def main() raises: + TestSuite.discover_tests[__functions_in_module()]().run() diff --git a/tests/harness_canary_pass.mojo b/tests/harness_canary_pass.mojo @@ -0,0 +1,12 @@ +from std.testing import TestSuite, assert_true + +from safe_tempdir import SafeTempDir + + +def test_canary_passes() raises: + with SafeTempDir() as temp_dir: + assert_true(temp_dir.byte_length() > 0) + + +def main() raises: + TestSuite.discover_tests[__functions_in_module()]().run() diff --git a/tests/safe_tempdir.mojo b/tests/safe_tempdir.mojo @@ -0,0 +1,30 @@ +"""Non-swallowing temporary-directory context manager for tests. + +The Mojo 1.0.0b1 `std.tempfile.TemporaryDirectory.__exit__` suppresses an +exception raised inside its `with` body, which silently masks failing +assertions. This wrapper delegates enter/exit to the standard implementation +but discards the suppression return value so body exceptions propagate +normally. + +Use `SafeTempDir` anywhere a test currently uses `TemporaryDirectory` as a +`with` context manager. The interface is identical: `__enter__` returns the +temporary directory path as a `String`. +""" + +from std.tempfile import TemporaryDirectory as _StdTemporaryDirectory + + +struct SafeTempDir: + var _inner: _StdTemporaryDirectory + + def __init__(out self) raises: + self._inner = _StdTemporaryDirectory() + + def __enter__(mut self) raises -> String: + return self._inner.__enter__() + + def __exit__(mut self) raises: + # Discard the inner return value deliberately: the standard + # implementation returns a suppression flag that would otherwise swallow + # an exception raised in the `with` body. + self._inner.__exit__() diff --git a/tests/stdio_process_helper.mojo b/tests/stdio_process_helper.mojo @@ -2,7 +2,7 @@ import std.os from std.os import Pipe, Process from std.ffi import CStringSlice, c_int, external_call from std.sys._libc import close -from std.tempfile import TemporaryDirectory +from safe_tempdir import SafeTempDir from json import Value, loads @@ -151,7 +151,7 @@ def run_stdio_entrypoint_with_2_args( def run_hyf_stdio(request_json: String) raises -> Value: var response = Value(None) - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: with ScopedEnvVar(HYF_PATHS_PROFILE_ENV, "repo_local"): with ScopedEnvVar(HYF_PATHS_REPO_LOCAL_ROOT_ENV, temp_dir): response = run_stdio_entrypoint("src/main.mojo", request_json) diff --git a/tests/test_harness_self_test.mojo b/tests/test_harness_self_test.mojo @@ -0,0 +1,57 @@ +from std.os.path import exists +from std.testing import TestSuite, assert_true + +from safe_tempdir import SafeTempDir + + +def test_safe_tempdir_propagates_assertion_failure() raises: + var caught = False + try: + with SafeTempDir() as temp_dir: + _ = temp_dir + assert_true(False) + except: + caught = True + assert_true(caught) + + +def test_safe_tempdir_propagates_generic_error() raises: + var caught = False + try: + with SafeTempDir() as temp_dir: + _ = temp_dir + raise Error("intentional generic harness error") + except: + caught = True + assert_true(caught) + + +def test_safe_tempdir_nested_contexts_are_distinct_and_cleaned() raises: + var outer_path = String("") + var inner_path = String("") + with SafeTempDir() as outer: + outer_path = outer + with SafeTempDir() as inner: + inner_path = inner + assert_true(exists(inner_path)) + assert_true(exists(outer_path)) + assert_true(outer_path != inner_path) + assert_true(not exists(outer_path)) + assert_true(not exists(inner_path)) + + +def test_safe_tempdir_cleans_up_on_exception() raises: + var path = String("") + var caught = False + try: + with SafeTempDir() as temp_dir: + path = temp_dir + raise Error("intentional cleanup harness error") + except: + caught = True + assert_true(caught) + assert_true(not exists(path)) + + +def main() raises: + TestSuite.discover_tests[__functions_in_module()]().run() diff --git a/tests/test_hyf.mojo b/tests/test_hyf.mojo @@ -7,7 +7,7 @@ from std.testing import ( assert_raises, assert_true, ) -from std.tempfile import TemporaryDirectory +from safe_tempdir import SafeTempDir from json import Value, loads, validate @@ -78,7 +78,7 @@ struct ScopedEnvVar: def _dispatch(line: String) raises -> Value: var result = Value(None) - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var runtime_context = resolve_startup_context( RuntimeStartupInput( env_paths_profile="repo_local", @@ -381,7 +381,7 @@ def test_repo_local_fixture_loader_reads_all_mirrored_scenarios() raises: def test_fixture_loader_reads_top_level_request_and_expected_structurally() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var scenario_path = Path(temp_dir) / "scenario.json" scenario_path.write_text( "{" @@ -883,7 +883,7 @@ def test_invalid_request_preserves_request_and_trace_correlation() raises: def test_internal_error_is_bounded_on_wire() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var diagnostics_dir = Path(temp_dir) / "hyf-internal-diagnostics" with ScopedEnvVar( _HYF_DIAGNOSTICS_DIR_ENV, diagnostics_dir.__fspath__() @@ -913,7 +913,7 @@ def _assert_internal_error_is_bounded(result: Value) raises: def test_internal_error_diagnostics_records_detail() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var diagnostics_dir = Path(temp_dir) / "hyf-internal-diagnostics" with ScopedEnvVar( @@ -1262,7 +1262,7 @@ def test_fixture_validator_accepts_corpus_and_rejects_corruptions() raises: mutations.append("empty_requirements") mutations.append("activation_step_mismatch") for mutation in mutations: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var base = Path(temp_dir) _write_min_fixture_corpus(base, mutation) assert_true( diff --git a/tests/test_persistent_stdio.mojo b/tests/test_persistent_stdio.mojo @@ -1,5 +1,5 @@ from std.collections import List -from std.tempfile import TemporaryDirectory +from safe_tempdir import SafeTempDir from std.testing import TestSuite, assert_equal, assert_true from fixture_assertions import load_scenario_request_json @@ -23,7 +23,7 @@ def _context(temp_dir: String) raises -> RuntimeStartupContext: def test_persistent_session_processes_multiple_frames() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var context = _context(temp_dir) var frames = List[String]() frames.append(load_scenario_request_json("scenarios/status_ok.json")) @@ -36,7 +36,7 @@ def test_persistent_session_processes_multiple_frames() raises: def test_session_recovers_from_malformed_frame() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var context = _context(temp_dir) var frames = List[String]() frames.append(load_scenario_request_json("scenarios/status_ok.json")) @@ -54,7 +54,7 @@ def main() raises: def test_session_preserves_order_and_recovers_after_malformed() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var context = _context(temp_dir) var frames = List[String]() frames.append(load_scenario_request_json("scenarios/status_ok.json")) @@ -69,7 +69,7 @@ def test_session_preserves_order_and_recovers_after_malformed() raises: def test_session_rejects_oversized_frame() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var context = _context(temp_dir) var huge = "{\"version\":1,\"request_id\":\"big\"," for _ in range(200000): @@ -83,7 +83,7 @@ def test_session_rejects_oversized_frame() raises: def test_farm_update_operation_is_gated_until_enabled() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var context = _context(temp_dir) var request = ( '{"version":1,"request_id":"farm-op-1","capability":"farm_update.interpret",' @@ -99,7 +99,7 @@ def test_farm_update_operation_is_gated_until_enabled() raises: def test_buyer_match_operation_is_gated_until_enabled() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var context = _context(temp_dir) var request = ( '{"version":1,"request_id":"match-op-1","capability":"buyer_request.match",' @@ -119,7 +119,7 @@ def test_new_operation_wire_frames_are_gated() raises: var wire_dir = _dir_of() / "fixtures" / "hyf_v1_jev" / "wire" var manifest = _load_fixture_json(wire_dir / "manifest.json") assert_equal(manifest["spec_id"].string_value(), "hyf_v1_jev") - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var context = _context(temp_dir) for name in manifest["scenarios"].array_items(): var scenario = _load_fixture_json(wire_dir / name.string_value()) @@ -132,7 +132,7 @@ def test_new_operation_wire_frames_are_gated() raises: def test_long_session_processes_many_frames_in_order() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var context = _context(temp_dir) var frames = List[String]() for index in range(50): diff --git a/tests/test_repo_local_process_contract.mojo b/tests/test_repo_local_process_contract.mojo @@ -1,5 +1,5 @@ from std.testing import TestSuite, assert_equal, assert_true -from std.tempfile import TemporaryDirectory +from safe_tempdir import SafeTempDir from json import Value from fixture_assertions import load_scenario_request_json @@ -25,7 +25,7 @@ def _assert_runtime_status_path_under_repo_local_root( def test_src_main_consumes_repo_local_env_without_outer_wrapper() raises: - with TemporaryDirectory() as repo_local_root: + with SafeTempDir() as repo_local_root: with ScopedEnvVar(HYF_PATHS_PROFILE_ENV, "repo_local"): with ScopedEnvVar(HYF_PATHS_REPO_LOCAL_ROOT_ENV, repo_local_root): var response = run_stdio_entrypoint( diff --git a/tests/test_soak.mojo b/tests/test_soak.mojo @@ -1,5 +1,5 @@ from std.collections import List -from std.tempfile import TemporaryDirectory +from safe_tempdir import SafeTempDir from std.testing import TestSuite, assert_equal, assert_true from fixture_assertions import load_scenario_request_json @@ -23,7 +23,7 @@ def _context(temp_dir: String) raises -> RuntimeStartupContext: def test_bounded_process_soak_200_frames() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var context = _context(temp_dir) var frames = List[String]() for _ in range(200): diff --git a/tests/test_stdio_contract.mojo b/tests/test_stdio_contract.mojo @@ -2,7 +2,7 @@ import std.os from std.os.path import exists from std.pathlib import Path from std.testing import assert_equal, assert_true, TestSuite -from std.tempfile import TemporaryDirectory +from safe_tempdir import SafeTempDir from json import Value from fixture_assertions import ( @@ -191,7 +191,7 @@ def _assert_query_rewrite_provider_fallback_with_deadline( deadline_ms: Int, requests: Int, ) raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var provider_port = reserve_loopback_port() var provider_stub = spawn_max_local_stub(provider_port, mode, requests) var startup_config_path = Path(temp_dir) / "explicit-hyf-config.toml" @@ -256,7 +256,7 @@ def _assert_query_rewrite_provider_fallback( def _assert_query_rewrite_runtime_config_fallback( config_text: String, expected_reason: String, request_id: String ) raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var startup_config_path = Path(temp_dir) / "explicit-hyf-config.toml" startup_config_path.write_text(config_text) with ScopedEnvVar(HYF_PATHS_PROFILE_ENV, "repo_local"): @@ -301,7 +301,7 @@ def _assert_query_rewrite_runtime_config_fallback( def _assert_query_rewrite_runtime_config_fallback_without_provenance( config_text: String, expected_reason: String, request_id: String ) raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var startup_config_path = Path(temp_dir) / "explicit-hyf-config.toml" startup_config_path.write_text(config_text) with ScopedEnvVar(HYF_PATHS_PROFILE_ENV, "repo_local"): @@ -338,7 +338,7 @@ def _assert_query_rewrite_runtime_config_fallback_without_provenance( def _assert_invalid_runtime_config_load_error( config_text: String, expected_error_fragment: String ) raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var startup_config_path = Path(temp_dir) / "invalid-hyf-config.toml" startup_config_path.write_text(config_text) with ScopedEnvVar(HYF_PATHS_PROFILE_ENV, "repo_local"): @@ -370,7 +370,7 @@ def _assert_invalid_runtime_config_load_error( def _assert_valid_runtime_config_load(config_text: String) raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var startup_config_path = Path(temp_dir) / "explicit-hyf-config.toml" startup_config_path.write_text(config_text) with ScopedEnvVar(HYF_PATHS_PROFILE_ENV, "repo_local"): @@ -465,7 +465,7 @@ def test_status_success() raises: def test_status_reports_repo_local_runtime_truth() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var startup_config_path = Path(temp_dir) / "explicit-hyf-config.toml" with ScopedEnvVar(HYF_PATHS_PROFILE_ENV, "repo_local"): with ScopedEnvVar(HYF_PATHS_REPO_LOCAL_ROOT_ENV, temp_dir): @@ -678,7 +678,7 @@ def test_status_reports_repo_local_runtime_truth() raises: def test_status_loads_valid_runtime_config_truthfully() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var startup_config_path = Path(temp_dir) / "explicit-hyf-config.toml" startup_config_path.write_text( _unavailable_max_local_runtime_config_toml() @@ -856,7 +856,7 @@ def test_status_loads_valid_runtime_config_truthfully() raises: def test_status_reports_invalid_runtime_config_without_crashing() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var startup_config_path = Path(temp_dir) / "invalid-hyf-config.toml" startup_config_path.write_text( '[runtime]\ndefault_execution_mode = "assisted"\n' @@ -932,7 +932,7 @@ def test_status_reports_invalid_runtime_config_without_crashing() raises: def test_status_reports_unconfigured_assisted_runtime_truthfully() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var startup_config_path = Path(temp_dir) / "explicit-hyf-config.toml" startup_config_path.write_text( '[service]\ntransport = "stdio"\n\n' @@ -978,7 +978,7 @@ def test_status_reports_unconfigured_assisted_runtime_truthfully() raises: def test_status_reports_non_2xx_max_local_health_truthfully() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var provider_port = reserve_loopback_port() var provider_stub = spawn_max_local_stub( provider_port, "health_non_2xx", 1 @@ -1021,7 +1021,7 @@ def test_status_reports_non_2xx_max_local_health_truthfully() raises: def test_status_reports_ready_max_local_provider_truthfully() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var provider_port = reserve_loopback_port() var provider_stub = spawn_max_local_stub( provider_port, "query_rewrite_ok", 1 @@ -1101,7 +1101,7 @@ def test_status_reports_ready_max_local_provider_truthfully() raises: def test_status_bounds_max_local_health_probe_timeout() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var provider_port = reserve_loopback_port() var provider_stub = spawn_max_local_stub( provider_port, "health_timeout", 1 @@ -1410,7 +1410,7 @@ def test_status_allows_inline_table_quoted_route_mentions() raises: def test_capabilities_reports_configured_provider_runtime_truthfully() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var startup_config_path = Path(temp_dir) / "explicit-hyf-config.toml" startup_config_path.write_text( _unavailable_max_local_runtime_config_toml() @@ -1470,7 +1470,7 @@ def test_capabilities_reports_configured_provider_runtime_truthfully() raises: def test_capabilities_reports_ready_max_local_provider_truthfully() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var provider_port = reserve_loopback_port() var provider_stub = spawn_max_local_stub( provider_port, "query_rewrite_ok", 1 @@ -1534,7 +1534,7 @@ def test_capabilities_reports_ready_max_local_provider_truthfully() raises: def test_capabilities_bounds_max_local_health_probe_timeout() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var provider_port = reserve_loopback_port() var provider_stub = spawn_max_local_stub( provider_port, "health_timeout", 1 @@ -1586,7 +1586,7 @@ def test_capabilities_bounds_max_local_health_probe_timeout() raises: def test_query_rewrite_falls_back_deterministically_when_provider_is_unavailable() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var startup_config_path = Path(temp_dir) / "explicit-hyf-config.toml" startup_config_path.write_text( _unavailable_max_local_runtime_config_toml() @@ -1658,7 +1658,7 @@ def test_query_rewrite_fallback_metadata_is_visible_without_provenance() raises: def test_assisted_semantic_rank_falls_back_as_unsupported_provider_capability() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var startup_config_path = Path(temp_dir) / "explicit-hyf-config.toml" startup_config_path.write_text( _unavailable_max_local_runtime_config_toml() @@ -1705,7 +1705,7 @@ def test_assisted_semantic_rank_falls_back_as_unsupported_provider_capability() def test_query_rewrite_uses_max_local_provider_when_ready() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var provider_port = reserve_loopback_port() var provider_stub = spawn_max_local_stub( provider_port, "query_rewrite_ok", 2 @@ -1875,7 +1875,7 @@ def test_query_rewrite_falls_back_on_provider_error_payload() raises: def test_status_reports_configured_but_deferred_custody_truthfully() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var identity_dir = Path(temp_dir) / "secrets" / "services" / "hyf" _ = std.os.makedirs(identity_dir.__fspath__(), exist_ok=True) (identity_dir / "identity.secret.json").write_text( @@ -1952,7 +1952,7 @@ def test_status_reports_configured_but_deferred_custody_truthfully() raises: def test_status_clears_repo_local_root_outside_repo_local_profile() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: with ScopedEnvVar(HYF_PATHS_PROFILE_ENV, "interactive_user"): with ScopedEnvVar(HYF_PATHS_REPO_LOCAL_ROOT_ENV, temp_dir): var response = run_stdio_entrypoint( @@ -1981,7 +1981,7 @@ def test_status_clears_repo_local_root_outside_repo_local_profile() raises: def test_status_reports_effective_diagnostics_override_truthfully() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var diagnostics_override_dir = ( Path(temp_dir) / "debug-diagnostics-override" ) @@ -2074,7 +2074,7 @@ def test_query_rewrite_success() raises: def test_query_rewrite_does_not_create_protected_local_artifacts() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: with ScopedEnvVar(HYF_PATHS_PROFILE_ENV, "repo_local"): with ScopedEnvVar(HYF_PATHS_REPO_LOCAL_ROOT_ENV, temp_dir): var response = run_stdio_entrypoint( @@ -2189,7 +2189,7 @@ def test_missing_input_fails_explicitly() raises: def test_internal_error_is_bounded_on_wire() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: with ScopedEnvVar(HYF_PATHS_PROFILE_ENV, "repo_local"): with ScopedEnvVar(HYF_PATHS_REPO_LOCAL_ROOT_ENV, temp_dir): var response = run_stdio_entrypoint( @@ -2223,7 +2223,7 @@ def test_internal_error_is_bounded_on_wire() raises: def test_internal_error_records_detail_in_canonical_runtime_diagnostics_dir() raises: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var diagnostics_dir = ( Path(temp_dir) / "logs" / "services" / "hyf" / "diagnostics" ) diff --git a/tests/test_traceability.mojo b/tests/test_traceability.mojo @@ -1,7 +1,7 @@ import std.os from std.collections import List from std.pathlib import Path, _dir_of_current_file -from std.tempfile import TemporaryDirectory +from safe_tempdir import SafeTempDir from std.testing import TestSuite, assert_equal, assert_true from json import loads @@ -84,7 +84,7 @@ def test_requirement_traceability_accepts_registry_and_rejects_dangling() raises mutations.append("dangling_dependency") mutations.append("duplicate_step") for mutation in mutations: - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var base = Path(temp_dir) _make_corpus(base, mutation) assert_true( @@ -97,7 +97,7 @@ def test_step_state_contract_is_valid_and_rejects_corruption() raises: var path = _dir_of_current_file() / "requirements" / "hyf_v1_jev.step_states.json" assert_equal(len(validate_step_states(path.__fspath__())), 0) - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var base = Path(temp_dir) _write( base / "states.json", @@ -105,7 +105,7 @@ def test_step_state_contract_is_valid_and_rejects_corruption() raises: '"passed_requires_executed_evidence":true,"rules":["x"]}', ) assert_true(len(validate_step_states((base / "states.json").__fspath__())) > 0) - with TemporaryDirectory() as temp_dir: + with SafeTempDir() as temp_dir: var base = Path(temp_dir) _write( base / "states.json", diff --git a/tools/check_harness_runner_exit.sh b/tools/check_harness_runner_exit.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env sh +# Negative controls for test-harness exception propagation. +# +# A failing assertion or a raised error inside SafeTempDir must make the Mojo +# test runner exit nonzero. A passing canary must exit zero. This proves the +# SafeTempDir wrapper does not reintroduce the TemporaryDirectory masking +# behavior. +set -eu + +root="$(cd "$(dirname "$0")/.." && pwd)" + +run_canary() { + if mojo -I "$root/src" -I "$root/tests" "$1" >/dev/null 2>&1; then + printf '0' + else + printf '1' + fi +} + +assert_fail="$(run_canary "$root/tests/harness_canary_assert_fail.mojo")" +error_fail="$(run_canary "$root/tests/harness_canary_error_fail.mojo")" +pass_ok="$(run_canary "$root/tests/harness_canary_pass.mojo")" + +status=0 +if [ "$assert_fail" -eq 0 ]; then + echo "harness canary: failing assertion did not fail the runner" >&2 + status=1 +fi +if [ "$error_fail" -eq 0 ]; then + echo "harness canary: raised error did not fail the runner" >&2 + status=1 +fi +if [ "$pass_ok" -ne 0 ]; then + echo "harness canary: passing canary unexpectedly failed" >&2 + status=1 +fi +if [ "$status" -eq 0 ]; then + echo "harness runner-exit canaries: ok" +fi +exit "$status"