Private
Public Access
refactor(app_controller): migrate 2 timeline event sink sites to Result (Phase 6 Group 6.2)
Replaces logging.debug bodies in mark_first_frame_rendered (L1355) and _on_warmup_complete_for_timeline (L1451) with proper Result[T] propagation: - _write_first_frame_timeline_result() -> Result[None] - _write_warmup_complete_timeline_result() -> Result[None] - _record_startup_timeline_error(op_name, result): stderr write + append to self._startup_timeline_errors for sub-track 4 GUI The instance list is the durable data plane; the stderr write is the best-effort visible drain (user-confirmed acceptable terminal sink until sub-track 4 lands GUI-side error display). Audit: INTERNAL_SILENT_SWALLOW for src/app_controller.py: 28 -> 26.
This commit is contained in:
@@ -206,3 +206,75 @@ def test_install_sigint_exit_handler_no_error_when_signal_install_succeeds():
|
||||
with patch("src.app_controller.signal.signal"):
|
||||
_install_sigint_exit_handler(ctrl)
|
||||
assert ctrl._signal_handler_error is None
|
||||
|
||||
|
||||
# --- Phase 6: Group 6.2 (timeline event sinks; stderr + instance state carry) ---
|
||||
|
||||
def test_first_frame_timeline_returns_ok_in_normal_path():
|
||||
"""
|
||||
Event sink (drain: stderr + instance state): mark_first_frame_rendered
|
||||
extracts timeline-write logic into a Result-returning helper.
|
||||
On the happy path, no error is recorded.
|
||||
"""
|
||||
from src.app_controller import AppController
|
||||
ctrl = AppController()
|
||||
ctrl._warmup_done_ts = ctrl._init_start_ts + 0.5
|
||||
ctrl.mark_first_frame_rendered(ts=ctrl._init_start_ts + 1.0)
|
||||
# The first frame was logged; any error would be appended to the
|
||||
# timeline-errors list. The list starts empty on a fresh controller.
|
||||
assert all(op != "first_frame_timeline" for op, _ in ctrl._startup_timeline_errors)
|
||||
|
||||
|
||||
def test_warmup_complete_timeline_returns_ok_in_normal_path():
|
||||
"""
|
||||
Event sink (drain: stderr + instance state): _on_warmup_complete_for_timeline
|
||||
extracts timeline-write logic into a Result-returning helper.
|
||||
On the happy path, no error is recorded.
|
||||
"""
|
||||
from src.app_controller import AppController
|
||||
ctrl = AppController()
|
||||
ctrl._first_frame_ts = None
|
||||
ctrl._on_warmup_complete_for_timeline({})
|
||||
assert all(op != "warmup_complete_timeline" for op, _ in ctrl._startup_timeline_errors)
|
||||
|
||||
|
||||
def test_first_frame_timeline_records_error_on_stderr_failure():
|
||||
"""
|
||||
When the stderr write fails inside the helper, the timeline event sink
|
||||
records the error in self._startup_timeline_errors for sub-track 4 GUI to drain.
|
||||
The OSError from the helper propagates up; we catch it here so the test
|
||||
only verifies the durable append.
|
||||
"""
|
||||
from src.app_controller import AppController
|
||||
ctrl = AppController()
|
||||
# Force the stderr write to fail by patching write on sys.stderr.
|
||||
with patch("src.app_controller.sys.stderr") as mock_stderr:
|
||||
mock_stderr.write = MagicMock(side_effect=OSError("stderr closed"))
|
||||
try:
|
||||
ctrl.mark_first_frame_rendered(ts=ctrl._init_start_ts + 0.1)
|
||||
except OSError:
|
||||
pass # the helper propagates the stderr failure; the append still happened
|
||||
first_frame_errors = [(op, e) for op, e in ctrl._startup_timeline_errors if op == "first_frame_timeline"]
|
||||
assert len(first_frame_errors) >= 1
|
||||
assert isinstance(first_frame_errors[0][1], ErrorInfo)
|
||||
assert "stderr closed" in first_frame_errors[0][1].message
|
||||
|
||||
|
||||
def test_warmup_complete_timeline_records_error_on_stderr_failure():
|
||||
"""
|
||||
When the stderr write fails, the warmup-complete timeline sink records
|
||||
the error in self._startup_timeline_errors.
|
||||
"""
|
||||
from src.app_controller import AppController
|
||||
ctrl = AppController()
|
||||
ctrl._first_frame_ts = None
|
||||
with patch("src.app_controller.sys.stderr") as mock_stderr:
|
||||
mock_stderr.write = MagicMock(side_effect=OSError("stderr closed"))
|
||||
try:
|
||||
ctrl._on_warmup_complete_for_timeline({})
|
||||
except OSError:
|
||||
pass
|
||||
warmup_errors = [(op, e) for op, e in ctrl._startup_timeline_errors if op == "warmup_complete_timeline"]
|
||||
assert len(warmup_errors) >= 1
|
||||
assert isinstance(warmup_errors[0][1], ErrorInfo)
|
||||
assert "stderr closed" in warmup_errors[0][1].message
|
||||
|
||||
Reference in New Issue
Block a user