aboutsummaryrefslogtreecommitdiff
path: root/app/tests/test_backends_audiocpp.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/tests/test_backends_audiocpp.py')
-rw-r--r--app/tests/test_backends_audiocpp.py122
1 files changed, 122 insertions, 0 deletions
diff --git a/app/tests/test_backends_audiocpp.py b/app/tests/test_backends_audiocpp.py
index e2b09d0..563ed78 100644
--- a/app/tests/test_backends_audiocpp.py
+++ b/app/tests/test_backends_audiocpp.py
@@ -1148,5 +1148,127 @@ class FetchServerEndpointsTests(unittest.TestCase):
make_server.fetch_server_voices("http://h", "qwen"))
+class MissingModelEntriesTests(unittest.TestCase):
+ """missing_model_entries: server.json paths vs. files on disk."""
+
+ def setUp(self):
+ self._tmp = tempfile.TemporaryDirectory()
+ self.dir = Path(self._tmp.name)
+
+ def tearDown(self):
+ self._tmp.cleanup()
+
+ def _server_json(self, models):
+ path = self.dir / "server.json"
+ path.write_text(json.dumps({"models": models}), encoding="utf-8")
+ return path
+
+ def test_relative_path_resolves_against_config_dir(self):
+ (self.dir / "models" / "present").mkdir(parents=True)
+ (self.dir / "models" / "present" / "m.gguf").write_bytes(b"x")
+ path = self._server_json([
+ {"id": "a", "path": "models/present"},
+ {"id": "b", "path": "models/absent"},
+ ])
+ missing = make_server.missing_model_entries(path)
+ self.assertEqual([m["id"] for m in missing], ["b"])
+
+ def test_empty_directory_counts_as_missing(self):
+ (self.dir / "models" / "empty").mkdir(parents=True)
+ path = self._server_json([{"id": "a", "path": "models/empty"}])
+ self.assertEqual(len(make_server.missing_model_entries(path)), 1)
+
+ def test_absolute_paths_honored(self):
+ target = self.dir / "absolute"
+ target.mkdir()
+ (target / "m.gguf").write_bytes(b"x")
+ path = self._server_json([{"id": "a", "path": str(target)}])
+ self.assertEqual(make_server.missing_model_entries(path), [])
+
+ def test_unreadable_json_returns_empty(self):
+ path = self.dir / "server.json"
+ path.write_text("not json", encoding="utf-8")
+ self.assertEqual(make_server.missing_model_entries(path), [])
+
+ def test_no_models_returns_empty(self):
+ path = self._server_json([])
+ self.assertEqual(make_server.missing_model_entries(path), [])
+
+
+class ModelInstallHintsTests(unittest.TestCase):
+ """model_install_hints: maps missing paths to the install command."""
+
+ def test_maps_path_to_install_id_via_catalog(self):
+ import tempfile
+ with tempfile.TemporaryDirectory() as td:
+ checkout = Path(td)
+ specs = checkout / "model_specs"
+ specs.mkdir()
+ (specs / "qwen3_tts.json").write_text(json.dumps({
+ "family": "qwen3_tts", "category": "tts",
+ "tasks": ["tts"],
+ "packages": [{
+ "id": "qwen3_tts_0_6b_base_q8_0", "format": "gguf",
+ "target_directory": "Qwen3-TTS-12Hz-0.6B-Base-GGUF",
+ }],
+ }), encoding="utf-8")
+ missing = [{"id": "qwen", "rel": "models/Qwen3-TTS-12Hz-0.6B-Base-GGUF"}]
+ hints = make_server.model_install_hints(checkout, missing)
+ self.assertEqual(len(hints), 1)
+ self.assertIn("qwen3_tts_0_6b_base_q8_0", hints[0])
+
+ def test_unmapped_path_names_the_path(self):
+ import tempfile
+ with tempfile.TemporaryDirectory() as td:
+ checkout = Path(td)
+ (checkout / "model_specs").mkdir()
+ hints = make_server.model_install_hints(
+ checkout, [{"id": "x", "rel": "models/nope"}])
+ self.assertIn("models/nope", hints[0])
+ self.assertNotIn("install", hints[0])
+
+
+class DetectServerSpecTests(unittest.TestCase):
+ """detect(): the server spec carries the checkout cwd + identity."""
+
+ def _checkout(self):
+ tmp = tempfile.TemporaryDirectory()
+ self.addCleanup(tmp.cleanup)
+ checkout = Path(tmp.name)
+ (checkout / "model_specs").mkdir()
+ build = checkout / "build" / "linux-cuda-release" / "bin"
+ build.mkdir(parents=True)
+ (build / "audiocpp_server").write_bytes(b"x")
+ (checkout / "server.json").write_text(json.dumps({
+ "models": [{"id": "qwen", "family": "qwen3_tts",
+ "path": "models/Qwen3-TTS-12Hz-0.6B-Base-GGUF"}],
+ }), encoding="utf-8")
+ return checkout
+
+ def test_spec_has_cwd_and_identity(self):
+ checkout = self._checkout()
+ with patch.object(make_server, "find_local_checkout",
+ return_value=checkout), \
+ patch.object(make_server, "_detect_remote",
+ return_value=(False, {})):
+ status = make_server.detect()
+ self.assertEqual(len(status.servers), 1)
+ spec = status.servers[0]
+ self.assertEqual(spec.cwd, checkout)
+ self.assertEqual(spec.identity, "audiocpp")
+ self.assertIn("--config", spec.argv)
+
+ def test_models_missing_flag_and_details(self):
+ checkout = self._checkout()
+ with patch.object(make_server, "find_local_checkout",
+ return_value=checkout), \
+ patch.object(make_server, "_detect_remote",
+ return_value=(False, {})):
+ status = make_server.detect()
+ self.assertTrue(status.models_missing)
+ self.assertTrue(any("not downloaded" in line
+ for line in status.details))
+
+
if __name__ == "__main__":
unittest.main()