aboutsummaryrefslogtreecommitdiff
path: root/app/tests/test_hub.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/tests/test_hub.py')
-rw-r--r--app/tests/test_hub.py222
1 files changed, 141 insertions, 81 deletions
diff --git a/app/tests/test_hub.py b/app/tests/test_hub.py
index 8e71104..94ea286 100644
--- a/app/tests/test_hub.py
+++ b/app/tests/test_hub.py
@@ -2654,8 +2654,8 @@ class ConvertFlowTests(unittest.TestCase):
patch.object(hub.config, "STOP_SERVER_AND_EXIT", True):
self._mock_preflight()
self._answer_form(backend="sglomni", model_id=entry.key,
- voice="Vivian", named_voice="", clone="",
- clone_dir="/tmp", instructions="")
+ voice="Vivian", clone_dir="/tmp",
+ instructions="")
cmd = self._convert(None, [self._ready("sglomni",
"SGLang-Omni")])
self.assertEqual(cmd[1], hub.BACKEND_SGLOMNI)
@@ -2668,6 +2668,39 @@ class ConvertFlowTests(unittest.TestCase):
def test_sglomni_managed_clone_model_routes_the_reference(self):
entry = hub.sglomni_backend.entry_by_key("higgs_audio_v3_tts")
self._patch_sglomni_installed([entry])
+ with tempfile.TemporaryDirectory() as td:
+ ref = Path(td) / "ref.wav"
+ ref.write_bytes(b"RIFF")
+ with patch.object(hub.config, "AUDIO_FORMAT", "m4b"), \
+ patch.object(hub.config, "LANGUAGE", "English"), \
+ patch.object(hub.config, "SPEED", 1.0), \
+ patch.object(hub.config, "DEBUG", False), \
+ patch.object(hub.config, "STOP_SERVER_AND_EXIT", True):
+ self._mock_preflight()
+ self._answer_form(backend="sglomni", model_id=entry.key,
+ voice=str(ref), clone_dir=td,
+ instructions="")
+ cmd = self._convert(None, [self._ready("sglomni",
+ "SGLang-Omni")])
+ fields = self.tui.forms_seen[-1][1]
+ voice_field = self._field("voice")
+ next(f for f in fields
+ if f["key"] == "sglomni.clone_dir")["value"] = td
+ wav_labels = [label for label, _ in
+ voice_field["choices"](fields)]
+ kwargs = cmd[2]
+ self.assertEqual(kwargs["clone"], str(ref))
+ # The .wav pick rides the clone kwarg; no named voice is sent.
+ self.assertNotIn("voice", kwargs)
+ # The combined Voice menu opens on the built-in default voice,
+ # with the built-in entry above the clone directory's .wavs.
+ self.assertEqual(voice_field["value"], "")
+ self.assertEqual(wav_labels, ["<built-in voice>", "ref.wav"])
+
+ def test_sglomni_managed_clone_model_blank_pick_uses_builtin_voice(self):
+ """A blank Voice pick on Higgs narrates with the model's own voice."""
+ entry = hub.sglomni_backend.entry_by_key("higgs_audio_v3_tts")
+ self._patch_sglomni_installed([entry])
with patch.object(hub.config, "AUDIO_FORMAT", "m4b"), \
patch.object(hub.config, "LANGUAGE", "English"), \
patch.object(hub.config, "SPEED", 1.0), \
@@ -2675,15 +2708,12 @@ class ConvertFlowTests(unittest.TestCase):
patch.object(hub.config, "STOP_SERVER_AND_EXIT", True):
self._mock_preflight()
self._answer_form(backend="sglomni", model_id=entry.key,
- voice="", named_voice="",
- clone="/tmp/ref.wav", clone_dir="/tmp",
- instructions="")
+ voice="", clone_dir="/tmp", instructions="")
cmd = self._convert(None, [self._ready("sglomni",
"SGLang-Omni")])
kwargs = cmd[2]
- self.assertEqual(kwargs["clone"], "/tmp/ref.wav")
- # A reference wins over any named voice: ref_audio drives the clone.
- self.assertIsNone(kwargs["voice"])
+ self.assertNotIn("clone", kwargs)
+ self.assertNotIn("voice", kwargs)
def test_sglomni_managed_design_model_sends_instructions(self):
entry = hub.sglomni_backend.entry_by_key("qwen3_tts_1_7b_voicedesign")
@@ -2695,8 +2725,7 @@ class ConvertFlowTests(unittest.TestCase):
patch.object(hub.config, "STOP_SERVER_AND_EXIT", True):
self._mock_preflight()
self._answer_form(backend="sglomni", model_id=entry.key,
- voice="", named_voice="", clone="",
- clone_dir="/tmp",
+ voice="", clone_dir="/tmp",
instructions="A warm narrator.")
cmd = self._convert(None, [self._ready("sglomni",
"SGLang-Omni")])
@@ -2721,15 +2750,22 @@ class ConvertFlowTests(unittest.TestCase):
self._mock_preflight()
self._answer_form(backend="sglomni-remote",
model_id="higgs_audio_v3_tts",
- voice="", named_voice="narrator",
- clone="", clone_dir="/tmp", instructions="")
+ voice="narrator", clone_dir="/tmp",
+ instructions="")
cmd = self._convert(
None, [self._remote("sglomni", "SGLang-Omni",
url="http://sgl.local:8100")])
+ fields = self.tui.forms_seen[-1][1]
+ voice_field = self._field("voice")
kwargs = cmd[2]
self.assertEqual(kwargs["model_id"], "higgs_audio_v3_tts")
- # An uploaded (named) voice rides the request's voice field.
+ # The uploaded (named) voice joins the combined Voice menu below
+ # the built-in entry, and rides the request's voice field.
+ self.assertEqual(
+ [label for label, _ in voice_field["choices"](fields)],
+ ["<built-in voice>", "narrator"])
self.assertEqual(kwargs["voice"], "narrator")
+ self.assertNotIn("clone", kwargs)
self.assertEqual(kwargs["api_url"], "http://sgl.local:8100")
def test_sglomni_fields_do_not_shadow_audiocpp_fields(self):
@@ -2767,10 +2803,11 @@ class ConvertFlowTests(unittest.TestCase):
patch.object(hub.config, "STOP_SERVER_AND_EXIT", True):
self._mock_preflight()
# Voxtral picked: its run carries the preset voice, and in
- # the form its Voice menu shows while the clone picker hides.
+ # the form its Voice menu shows the preset only (no
+ # built-in entry, no clone .wavs — those belong to the
+ # clone-capable models' combined menu).
self._answer_form(backend="sglomni", model_id="voxtral_tts",
- voice="casual_male", named_voice="",
- clone="", clone_dir="/tmp",
+ voice="casual_male", clone_dir="/tmp",
instructions="")
cmd = self._convert(None, statuses)
fields = self.tui.forms_seen[-1][1]
@@ -2782,12 +2819,12 @@ class ConvertFlowTests(unittest.TestCase):
next(f for f in fields
if f["key"] == "sglomni.model_id")["value"] = \
"voxtral_tts"
- self.assertTrue(self._field("voice")["visible"](fields))
- self.assertIn(
- "casual_male",
- [label for label, _ in
- self._field("voice")["choices"](fields)])
- self.assertFalse(self._field("clone")["visible"](fields))
+ voice_field = self._field("voice")
+ self.assertEqual(voice_field["key"], "sglomni.voice")
+ self.assertTrue(voice_field["visible"](fields))
+ self.assertEqual(
+ [label for label, _ in voice_field["choices"](fields)],
+ ["casual_male"])
# An audio.cpp submission keeps its own picks: SGLang's
# same-named fields must not leak into its run.
with patch.object(hub.audiocpp_backend, "find_local_checkout",
@@ -2799,9 +2836,7 @@ class ConvertFlowTests(unittest.TestCase):
patch.object(hub.config, "STOP_SERVER_AND_EXIT", True):
self._mock_preflight()
self._answer_form(backend="audiocpp", model_id="qwen",
- audiocpp_voice="", instructions="Style.",
- voice="", named_voice="", clone="",
- clone_dir="/tmp")
+ audiocpp_voice="", instructions="Style.")
cmd = self._convert(None, statuses)
self.assertEqual(cmd[2]["model_id"], "qwen")
self.assertEqual(cmd[2]["instructions"], "Style.")
@@ -2809,9 +2844,10 @@ class ConvertFlowTests(unittest.TestCase):
def test_sglomni_every_catalog_model_drives_the_right_form(self):
"""Every catalog entry shows the capability-matched voice fields.
- speaker -> the preset Voice menu; clone with a required reference
- -> the clone picker only; clone that narrates without one -> the
- default-voice pick alongside the clone picker; design -> the
+ speaker -> the preset Voice menu; clone -> the combined Voice
+ menu (the built-in default voice on top when the model can
+ narrate without a reference, then the clone directory's .wavs)
+ beside the Clone .wav directory browser; design -> the
Instructions box.
"""
@@ -2825,59 +2861,83 @@ class ConvertFlowTests(unittest.TestCase):
presets.start()
self.addCleanup(presets.stop)
self._patch_sglomni_installed(list(hub.sglomni_backend.ENTRIES))
- with patch.object(hub.config, "AUDIO_FORMAT", "m4b"), \
- patch.object(hub.config, "LANGUAGE", "English"), \
- patch.object(hub.config, "SPEED", 1.0), \
- patch.object(hub.config, "DEBUG", False), \
- patch.object(hub.config, "STOP_SERVER_AND_EXIT", True):
- self._mock_preflight()
- for entry in hub.sglomni_backend.ENTRIES:
- with self.subTest(entry=entry.key):
- overrides = {"backend": "sglomni",
- "model_id": entry.key,
- "voice": "", "named_voice": "",
- "clone": "", "clone_dir": "/tmp",
- "instructions": ""}
- if entry.capability == "speaker":
- overrides["voice"] = \
- (entry.speakers or ("casual_male",))[0]
- elif entry.capability == "clone":
- overrides["clone"] = "/tmp/ref.wav"
- else: # design
- overrides["instructions"] = "A warm narrator."
- self._answer_form(**overrides)
- cmd = self._convert(None, [
- self._ready("sglomni", "SGLang-Omni")])
- self.assertIsNotNone(cmd)
- kwargs = cmd[2]
- self.assertEqual(kwargs["model_id"], entry.key)
- fields = self.tui.forms_seen[-1][1]
- next(f for f in fields
- if f["key"] == "sglomni.model_id")["value"] = \
- entry.key
- shown = {f["key"] for f in fields
- if f["key"].startswith("sglomni.")
- and f["visible"](fields)}
- expected = {"sglomni.model_id"}
- if entry.capability == "speaker":
- expected.add("sglomni.voice")
- self.assertEqual(
- kwargs.get("voice"),
- (entry.speakers or ("casual_male",))[0])
- self.assertNotIn("clone", kwargs)
- elif entry.capability == "clone":
- expected |= {"sglomni.clone_dir", "sglomni.clone"}
- if not entry.requires_reference:
- expected.add("sglomni.named_voice")
- self.assertEqual(kwargs.get("clone"), "/tmp/ref.wav")
- self.assertIsNone(kwargs.get("voice"))
- else: # design
- expected.add("sglomni.instructions")
- self.assertEqual(kwargs.get("instructions"),
- "A warm narrator.")
- self.assertNotIn("voice", kwargs)
- self.assertNotIn("clone", kwargs)
- self.assertEqual(shown, expected)
+ with tempfile.TemporaryDirectory() as td:
+ ref = Path(td) / "ref.wav"
+ ref.write_bytes(b"RIFF")
+ with patch.object(hub.config, "AUDIO_FORMAT", "m4b"), \
+ patch.object(hub.config, "LANGUAGE", "English"), \
+ patch.object(hub.config, "SPEED", 1.0), \
+ patch.object(hub.config, "DEBUG", False), \
+ patch.object(hub.config, "STOP_SERVER_AND_EXIT", True):
+ self._mock_preflight()
+ for entry in hub.sglomni_backend.ENTRIES:
+ with self.subTest(entry=entry.key):
+ overrides = {"backend": "sglomni",
+ "model_id": entry.key,
+ "voice": "", "clone_dir": td,
+ "instructions": ""}
+ if entry.capability == "speaker":
+ overrides["voice"] = \
+ (entry.speakers or ("casual_male",))[0]
+ elif entry.capability == "clone":
+ if entry.requires_reference:
+ overrides["voice"] = str(ref)
+ else: # design
+ overrides["instructions"] = "A warm narrator."
+ self._answer_form(**overrides)
+ cmd = self._convert(None, [
+ self._ready("sglomni", "SGLang-Omni")])
+ self.assertIsNotNone(cmd)
+ kwargs = cmd[2]
+ self.assertEqual(kwargs["model_id"], entry.key)
+ fields = self.tui.forms_seen[-1][1]
+ next(f for f in fields
+ if f["key"] == "sglomni.model_id")["value"] = \
+ entry.key
+ next(f for f in fields
+ if f["key"] == "sglomni.clone_dir")["value"] \
+ = td
+ shown = {f["key"] for f in fields
+ if f["key"].startswith("sglomni.")
+ and f["visible"](fields)}
+ voice_labels = [
+ label for label, _ in
+ self._field("voice")["choices"](fields)]
+ if entry.capability == "speaker":
+ expected = {"sglomni.model_id", "sglomni.voice"}
+ preset = (entry.speakers
+ or ("casual_male",))[0]
+ self.assertEqual(
+ voice_labels,
+ list(entry.speakers or ("casual_male",)))
+ self.assertEqual(kwargs.get("voice"), preset)
+ self.assertNotIn("clone", kwargs)
+ elif entry.capability == "clone":
+ expected = {"sglomni.model_id", "sglomni.voice",
+ "sglomni.clone_dir"}
+ if entry.requires_reference:
+ # Cannot narrate without a reference: the
+ # menu is the clone directory's .wavs only.
+ self.assertEqual(voice_labels, ["ref.wav"])
+ self.assertEqual(kwargs.get("clone"),
+ str(ref))
+ self.assertNotIn("voice", kwargs)
+ else:
+ # Built-in default voice above the .wavs;
+ # the blank pick narrates without a clone.
+ self.assertEqual(voice_labels,
+ ["<built-in voice>",
+ "ref.wav"])
+ self.assertNotIn("clone", kwargs)
+ self.assertNotIn("voice", kwargs)
+ else: # design
+ expected = {"sglomni.model_id",
+ "sglomni.instructions"}
+ self.assertEqual(kwargs.get("instructions"),
+ "A warm narrator.")
+ self.assertNotIn("voice", kwargs)
+ self.assertNotIn("clone", kwargs)
+ self.assertEqual(shown, expected)
class SelectSpecTests(unittest.TestCase):