diff options
| author | historia <historiavg@proton.me> | 2026-08-30 20:42:02 -0400 |
|---|---|---|
| committer | historia <historiavg@proton.me> | 2026-08-30 20:42:02 -0400 |
| commit | a0e3050c6e1e43df3941077afa4ade9a1c4d6ce4 (patch) | |
| tree | d8492bbcbbf6850afc127bae862abe68e1198c0c /app/tests/test_backends_audiocpp.py | |
| parent | 93f106aac2d6411c80a911adac62cd12f80e58be (diff) | |
| download | tts-audiobook-generator-a0e3050c6e1e43df3941077afa4ade9a1c4d6ce4.tar.gz | |
fix: non-clone models correctly supported in tui, restart server when needed
Diffstat (limited to 'app/tests/test_backends_audiocpp.py')
| -rw-r--r-- | app/tests/test_backends_audiocpp.py | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/app/tests/test_backends_audiocpp.py b/app/tests/test_backends_audiocpp.py index 08de777..8b1698b 100644 --- a/app/tests/test_backends_audiocpp.py +++ b/app/tests/test_backends_audiocpp.py @@ -637,6 +637,130 @@ class BuildServerConfigTests(unittest.TestCase): self.assertEqual(entry["mode"], "offline") +class CloneOnlyHostingTests(unittest.TestCase): + """Clone-only family classification and server.json hosting tasks.""" + + def test_clone_only_set_members(self): + for family in ("chatterbox", "confucius4_tts", "echo_tts"): + self.assertTrue(make_server.is_clone_only_family(family)) + + def test_clone_only_from_spec_tasks(self): + self.assertTrue(make_server.is_clone_only_family( + "future_tts", tasks={"clone"})) + + def test_mixed_and_pure_families_are_not_clone_only(self): + self.assertFalse(make_server.is_clone_only_family( + "higgs_audio_tts", tasks={"tts", "clone"})) + self.assertFalse(make_server.is_clone_only_family( + "supertonic", tasks={"tts"})) + + def test_unknown_family_without_tasks_is_not_clone_only(self): + # No spec, no explicit knowledge: keep the generic (tts) hosting. + self.assertFalse(make_server.is_clone_only_family("brand_new")) + + def test_hosting_task_clone_only_family(self): + self.assertEqual(make_server.hosting_task( + {"family": "chatterbox", "tasks": ["tts", "clone", "vc"]}), + "clon") + + def test_hosting_task_regular_family(self): + self.assertEqual(make_server.hosting_task( + {"family": "f5_tts", "tasks": ["tts", "clone"]}), "tts") + + +class BuildEntriesHostingTests(unittest.TestCase): + """_build_entries hosts clone-only families with task "clon".""" + + @staticmethod + def _catalog_entry(family, tasks): + return {"family": family, "display_name": family, + "description": "", "languages": ["en"], "tasks": tasks, + "clone_capable": "clone" in tasks, "packages": [], + "install_id": f"{family}_q8_0", + "default_path": f"models/{family}-GGUF"} + + @staticmethod + def _option(directory): + return {"target_directory": directory, "install_id": "pkg", + "design": False, "recommended": True} + + def _entries(self, catalog_entry): + entries, _, _, _, _ = make_server.wizard._build_entries( + [catalog_entry["family"]], + {catalog_entry["family"]: [self._option(catalog_entry["family"])]}, + {catalog_entry["family"]: catalog_entry}, + lambda install_id: "tts") + return entries + + def test_chatterbox_is_hosted_with_clon(self): + entry = self._entries(self._catalog_entry( + "chatterbox", ["tts", "clone", "vc"]))[0] + self.assertEqual(entry["task"], "clon") + self.assertEqual(entry["family"], "chatterbox") + + def test_clone_only_spec_family_is_hosted_with_clon(self): + entry = self._entries(self._catalog_entry( + "confucius4_tts", ["clone"]))[0] + self.assertEqual(entry["task"], "clon") + + def test_mixed_family_is_hosted_with_tts(self): + entry = self._entries(self._catalog_entry( + "f5_tts", ["tts", "clone"]))[0] + self.assertEqual(entry["task"], "tts") + + +class RehostCloneOnlyEntriesTests(unittest.TestCase): + """server.json repair: clone-only entries re-hosted from "tts".""" + + def setUp(self): + self._td = tempfile.TemporaryDirectory() + self.server_json = Path(self._td.name) / "server.json" + + def tearDown(self): + self._td.cleanup() + + def _data(self, *models): + return {"host": "127.0.0.1", "port": 8080, "backend": "cuda", + "lazy_load": False, "models": list(models)} + + def _read(self): + return json.loads(self.server_json.read_text(encoding="utf-8")) + + def test_chatterbox_tts_entry_is_rehosted_and_persisted(self): + data = self._data({"id": "Chatterbox-GGUF", "family": "chatterbox", + "path": "models/Chatterbox-GGUF", "task": "tts", + "mode": "offline"}) + repaired = make_server.rehost_clone_only_entries(self.server_json, + data) + self.assertEqual(repaired, ["Chatterbox-GGUF"]) + self.assertEqual(data["models"][0]["task"], "clon") + # The fix is written back so the server picks it up on restart. + self.assertEqual(self._read()["models"][0]["task"], "clon") + + def test_non_clone_only_entries_are_untouched(self): + data = self._data({"id": "q", "family": "qwen3_tts", + "path": "models/Q", "task": "tts", + "mode": "offline"}) + self.assertEqual(make_server.rehost_clone_only_entries( + self.server_json, data), []) + self.assertEqual(data["models"][0]["task"], "tts") + self.assertFalse(self.server_json.exists()) + + def test_vdes_and_clon_tasks_are_left_alone(self): + data = self._data({"id": "c", "family": "chatterbox", + "path": "m", "task": "clon", "mode": "offline"}, + {"id": "d", "family": "qwen3_tts", + "path": "m2", "task": "vdes", "mode": "offline"}) + self.assertEqual(make_server.rehost_clone_only_entries( + self.server_json, data), []) + + def test_unusable_document_is_ignored(self): + self.assertEqual(make_server.rehost_clone_only_entries( + self.server_json, {"models": "nope"}), []) + self.assertEqual(make_server.rehost_clone_only_entries( + self.server_json, {}), []) + + class InstallModelsTests(unittest.TestCase): """Printing or auto-running the model install commands.""" |
