diff options
Diffstat (limited to 'app/tests/test_backends_servers.py')
| -rw-r--r-- | app/tests/test_backends_servers.py | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/app/tests/test_backends_servers.py b/app/tests/test_backends_servers.py index 987ff24..201d5b6 100644 --- a/app/tests/test_backends_servers.py +++ b/app/tests/test_backends_servers.py @@ -78,6 +78,108 @@ class StartTests(unittest.TestCase): ok = servers.start(self.spec) self.assertFalse(ok) + def _boot_proc(self): + proc = MagicMock() + proc.pid = 4242 + proc.poll.return_value = None + return proc + + def test_cwd_passed_to_popen(self): + """A spec with a cwd spawns the server in that working directory. + + audio.cpp resolves model_specs/<family>.json relative to its + process working directory, so the hub must start it from the + checkout. + """ + spec = ServerSpec("test", "http://127.0.0.1:9999", + [str(self.exe)], cwd=Path("/opt/audio.cpp")) + proc = self._boot_proc() + with patch.object(servers, "LOG_DIR", self.dir), \ + patch("subprocess.Popen", return_value=proc) as mk, \ + patch("backends.common.server_running", + side_effect=[False, True]), \ + patch("time.sleep"): + ok = servers.start(spec) + self.assertTrue(ok) + kwargs = mk.call_args.kwargs + self.assertEqual(kwargs.get("cwd"), "/opt/audio.cpp") + + def test_identity_spec_waits_for_http_identity(self): + """Readiness needs the server to answer HTTP as its identity. + + A TCP-accepting but still-booting server (lazy model load, slow + listen-before-serve) must not count as ready. + """ + spec = ServerSpec("test", "http://127.0.0.1:9999", + [str(self.exe)], identity="audiocpp") + proc = self._boot_proc() + with patch.object(servers, "LOG_DIR", self.dir), \ + patch("subprocess.Popen", return_value=proc), \ + patch("backends.common.server_running", return_value=True), \ + patch.object(servers.probe, "identify_server", + side_effect=[None, None, "audiocpp"]), \ + patch("time.sleep"): + ok = servers.start(spec) + self.assertTrue(ok) + + def test_faster_identity_requires_model_loaded(self): + """The faster identity additionally waits for /health model_loaded.""" + spec = ServerSpec("test", "http://127.0.0.1:9999", + [str(self.exe)], identity="faster") + proc = self._boot_proc() + with patch.object(servers, "LOG_DIR", self.dir), \ + patch("subprocess.Popen", return_value=proc), \ + patch("backends.common.server_running", return_value=True), \ + patch.object(servers.probe, "identify_server", + return_value="faster"), \ + patch.object(servers.probe, "faster_model_loaded", + side_effect=[False, True]), \ + patch("time.sleep"): + ok = servers.start(spec) + self.assertTrue(ok) + + def test_progress_receives_boot_events(self): + events = [] + proc = self._boot_proc() + with patch.object(servers, "LOG_DIR", self.dir), \ + patch("subprocess.Popen", return_value=proc), \ + patch("backends.common.server_running", + side_effect=[False, True]), \ + patch("time.sleep"): + ok = servers.start(self.spec, progress=events.append) + self.assertTrue(ok) + kinds = [event["kind"] for event in events] + self.assertEqual(kinds, ["starting", "ready"]) + self.assertEqual(events[0]["pid"], 4242) + self.assertIn("--port", events[0]["argv"]) + + def test_cancel_aborts_boot_kills_process_and_reports(self): + import threading + cancel = threading.Event() + cancel.set() + proc = self._boot_proc() + with patch.object(servers, "LOG_DIR", self.dir), \ + patch("subprocess.Popen", return_value=proc), \ + patch("backends.common.server_running", return_value=False), \ + patch.object(servers, "_kill_pid", return_value=True) as mk, \ + patch("time.sleep"): + ok = servers.start(self.spec, cancel=cancel) + self.assertFalse(ok) + mk.assert_called_once_with(4242) + self.assertFalse((self.dir / "test-server.pid").exists()) + + def test_console_progress_prints_events(self): + import io + from contextlib import redirect_stdout + buf = io.StringIO() + with redirect_stdout(buf): + servers._console_progress({"kind": "running", "name": "test", + "url": "http://127.0.0.1:9999"}) + servers._console_progress({"kind": "error", "message": "boom"}) + out = buf.getvalue() + self.assertIn("already running", out) + self.assertIn("boom", out) + class StopTests(unittest.TestCase): def setUp(self): |
