From 5c3db8f500ff206f3a675d8f4184cb0d61f94804 Mon Sep 17 00:00:00 2001 From: historia Date: Fri, 28 Aug 2026 02:43:27 -0400 Subject: feat: cuda arch detection for shorter builds, build failure detection --- app/tests/test_backends_common.py | 57 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'app/tests/test_backends_common.py') diff --git a/app/tests/test_backends_common.py b/app/tests/test_backends_common.py index a94994b..08ffc2c 100644 --- a/app/tests/test_backends_common.py +++ b/app/tests/test_backends_common.py @@ -2,8 +2,9 @@ The streaming mode of ``run_console_subprocess`` (used by the in-TUI task view) is exercised with a real child process: output lines are captured and -forwarded, cancellation kills the child and returns 130, and an on_cancel -hook runs first. +forwarded, cancellation kills the child and returns 130, an on_cancel hook +runs first, and the no-output stall watchdog kills a wedged child and +returns 124. """ import sys @@ -51,6 +52,58 @@ class RunConsoleSubprocessStreamingTests(unittest.TestCase): self.assertEqual(touched, [True]) +class RunConsoleSubprocessStallTests(unittest.TestCase): + """The no-output watchdog: a silent child is killed and reported 124.""" + + def test_stall_kills_a_silent_child_and_returns_124(self): + lines = [] + rc = common.run_console_subprocess( + [sys.executable, "-c", + "import sys, time; print('start', flush=True); " + "time.sleep(60)"], + emit=lines.append, stall_timeout=0.5) + self.assertEqual(rc, 124) + self.assertEqual(lines[0], "start") + # The stall is announced to the view before the kill. + self.assertTrue(any("[ERROR]" in line and "No output" in line + for line in lines), lines) + + def test_no_stall_while_output_keeps_flowing(self): + lines = [] + rc = common.run_console_subprocess( + [sys.executable, "-c", + "import sys, time\n" + "for _ in range(6):\n" + " print('tick', flush=True)\n" + " time.sleep(0.2)\n"], + emit=lines.append, stall_timeout=1.0) + self.assertEqual(rc, 0) + self.assertEqual(lines, ["tick"] * 6) + + def test_console_path_has_no_watchdog(self): + # Without emit the child inherits the terminal; stall_timeout is + # a no-op there (the caller sees raw output and can Ctrl-C). + rc = common.run_console_subprocess( + [sys.executable, "-c", "print('hi')"], stall_timeout=0.001) + self.assertEqual(rc, 0) + + +class RunConsoleSubprocessQuietTimeoutTests(unittest.TestCase): + """A timed-out quiet probe returns a failed result, never raises.""" + + def test_timeout_returns_failed_result(self): + proc = common.run_console_subprocess_quiet( + [sys.executable, "-c", "import time; time.sleep(30)"], + timeout=0.5) + self.assertIsNotNone(proc) + self.assertEqual(proc.returncode, -1) + + def test_untimed_probe_still_reports_the_exit_code(self): + proc = common.run_console_subprocess_quiet( + [sys.executable, "-c", "import sys; sys.exit(5)"]) + self.assertEqual(proc.returncode, 5) + + class GitCloneTests(unittest.TestCase): def test_git_clone_console_passes_through(self): with mock.patch.object(common, "run_console_subprocess", -- cgit v1.2.3