From 8579517a35ef1865fc9b428899d73d52dcb27a14 Mon Sep 17 00:00:00 2001 From: historia Date: Wed, 2 Sep 2026 01:26:09 -0400 Subject: feat: sglang backend support --- app/tests/test_runview.py | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'app/tests/test_runview.py') diff --git a/app/tests/test_runview.py b/app/tests/test_runview.py index 0d99a6a..7f79053 100644 --- a/app/tests/test_runview.py +++ b/app/tests/test_runview.py @@ -237,6 +237,46 @@ class StateTransitionTests(_FakeTui, unittest.TestCase): self.assertEqual(view.server, "error") self.assertEqual(view.log_tail, ["boom"]) + def test_server_exit_keeps_a_known_crash_hint(self): + view, _ = self.make_view() + view.handle_event({"kind": "exited", "name": "sglomni", + "returncode": 1, "log_tail": ["fp8..."], + "hint": "FP8 needs compute capability 8.9+"}) + self.assertEqual(view.phase, "error") + self.assertEqual(view.boot_hint, + "FP8 needs compute capability 8.9+") + + def test_boot_failure_is_recorded_in_the_dated_log(self): + # A failed boot never reaches the converter, so without this the + # dated log the failure pointers name would stay blank. + with tempfile.TemporaryDirectory() as tmp: + log_path = os.path.join(tmp, "audiobook_test.log") + view, _ = self.make_view(log_path=log_path) + view.handle_event({"kind": "starting", "name": "sglomni", + "log_path": "/tmp/sglomni-server.log"}) + view.handle_event({"kind": "exited", "name": "sglomni", + "returncode": 1, "log_tail": ["boom"], + "hint": "FP8 needs compute capability 8.9+"}) + with open(log_path, encoding="utf-8") as logf: + text = logf.read() + self.assertIn("ERROR - server exited with code 1", text) + self.assertIn("WARNING - hint: FP8 needs compute capability 8.9+", + text) + self.assertIn("the server's own output is in /tmp/sglomni-server.log", + text) + + def test_boot_timeout_is_recorded_without_optional_detail(self): + with tempfile.TemporaryDirectory() as tmp: + log_path = os.path.join(tmp, "audiobook_test.log") + view, _ = self.make_view(log_path=log_path) + view.handle_event({"kind": "timeout", "name": "sglomni", + "seconds": 1200, "log_tail": []}) + with open(log_path, encoding="utf-8") as logf: + text = logf.read() + self.assertIn("ERROR - server did not become ready in time", text) + self.assertNotIn("hint:", text) + self.assertNotIn("the server's own output is in", text) + def test_server_down_during_convert(self): view, _ = self.make_view() view.handle_event({"kind": "book", "index": 1, "total": 1, @@ -397,6 +437,25 @@ class RenderTests(_FakeTui, unittest.TestCase): self.assertIn("not responding", text) self.assertIn("the server is not responding", text) + def test_error_summary_draws_the_boot_hint(self): + view, screen = self.make_view() + view.handle_event({"kind": "exited", "name": "sglomni", + "returncode": 1, "log_tail": [], + "hint": "FP8 needs compute capability 8.9+"}) + view.render() + self.assertIn("FP8 needs compute capability 8.9+", + self._strings(screen)) + + def test_error_screen_names_the_server_log(self): + view, screen = self.make_view() + view.handle_event({"kind": "starting", "name": "sglomni", + "log_path": "/tmp/sglomni-server.log"}) + view.handle_event({"kind": "exited", "name": "sglomni", + "returncode": 1, "log_tail": ["boom"]}) + view.render() + self.assertIn("server log: /tmp/sglomni-server.log", + self._strings(screen)) + def test_summary_screen_after_done(self): view, screen = self.make_view() view.handle_event({"kind": "book", "index": 1, "total": 1, @@ -645,6 +704,28 @@ class RunLoopTests(_FakeTui, unittest.TestCase): self.assertIn("Full details in the log file: /tmp/runs/a.log", mk_notice.call_args[0][0]) + def test_stop_and_exit_boot_failure_names_reason_hint_and_server_log(self): + # A run that dies in the boot phase must not summarize as a bare + # "No books were converted": the reason, the known-crash hint, + # and the server's own log path all land in the summary. + with patch.object(runview.servers, "stop"), \ + patch.object(runview.common, + "record_post_tui_notice") as mk_notice: + view, screen = self.make_view([], stop_and_exit=True, + log_path="/tmp/runs/a.log") + view._queue.put({"kind": "starting", "name": "sglomni", + "log_path": "/tmp/sglomni-server.log"}) + view._queue.put({"kind": "exited", "name": "sglomni", + "returncode": 1, "log_tail": [], + "hint": "FP8 needs compute capability 8.9+"}) + view.run() + text = mk_notice.call_args[0][0] + self.assertIn("No books were converted", text) + self.assertIn("Failure: server exited with code 1", text) + self.assertIn("hint: FP8 needs compute capability 8.9+", text) + self.assertIn("server log: /tmp/sglomni-server.log", text) + self.assertIn("Full details in the log file: /tmp/runs/a.log", text) + class WorkerTests(_FakeTui, unittest.TestCase): """The worker thread's handoff into audiobook.convert.""" -- cgit v1.2.3