aboutsummaryrefslogtreecommitdiff
path: root/tests/test_make_audiocpp_server_json.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_make_audiocpp_server_json.py')
-rw-r--r--tests/test_make_audiocpp_server_json.py129
1 files changed, 84 insertions, 45 deletions
diff --git a/tests/test_make_audiocpp_server_json.py b/tests/test_make_audiocpp_server_json.py
index f9fa794..2bd262a 100644
--- a/tests/test_make_audiocpp_server_json.py
+++ b/tests/test_make_audiocpp_server_json.py
@@ -304,20 +304,6 @@ class PromptHelperTests(unittest.TestCase):
def tearDown(self):
self._tmp.cleanup()
- def test_ask_wav_dir_reprompts_until_valid(self):
- with patch("builtins.input",
- side_effect=[str(self.folder / "nope"),
- str(self.folder)]):
- self.assertEqual(make_server.ask_wav_dir(), self.folder)
-
- def test_ask_wav_dir_empty_skips(self):
- with patch("builtins.input", return_value=""):
- self.assertIsNone(make_server.ask_wav_dir())
-
- def test_ask_wav_dir_eof_returns_none(self):
- with patch("builtins.input", side_effect=EOFError):
- self.assertIsNone(make_server.ask_wav_dir())
-
def test_ask_port_reprompts_until_valid(self):
with patch("builtins.input", side_effect=["abc", "8081"]):
self.assertEqual(make_server.ask_port(8080), 8081)
@@ -341,6 +327,46 @@ class PromptHelperTests(unittest.TestCase):
"one")
+class ResolveWavDirArgTests(unittest.TestCase):
+ """Path normalization for the required WAV_DIR argument."""
+
+ def setUp(self):
+ self._tmp = tempfile.TemporaryDirectory()
+ self.folder = Path(self._tmp.name)
+
+ def tearDown(self):
+ self._tmp.cleanup()
+
+ def test_resolves_to_absolute(self):
+ self.assertEqual(make_server.resolve_wav_dir_arg(str(self.folder)),
+ self.folder.resolve())
+
+ def test_strips_surrounding_quotes(self):
+ quoted = f'"{self.folder}"'
+ self.assertEqual(make_server.resolve_wav_dir_arg(quoted),
+ self.folder.resolve())
+
+ def test_strips_single_quotes(self):
+ quoted = f"'{self.folder}'"
+ self.assertEqual(make_server.resolve_wav_dir_arg(quoted),
+ self.folder.resolve())
+
+ def test_strips_whitespace(self):
+ self.assertEqual(make_server.resolve_wav_dir_arg(f" {self.folder} "),
+ self.folder.resolve())
+
+ def test_expands_tilde(self):
+ with patch.object(make_server.os.path, "expanduser",
+ return_value=str(self.folder)) as mock_expand:
+ result = make_server.resolve_wav_dir_arg("~/voices")
+ mock_expand.assert_called_once_with("~/voices")
+ self.assertEqual(result, self.folder.resolve())
+
+ def test_trailing_slash_preserved_as_dir(self):
+ self.assertEqual(make_server.resolve_wav_dir_arg(f"{self.folder}/"),
+ self.folder.resolve())
+
+
class MainTests(unittest.TestCase):
def setUp(self):
self._tmp = tempfile.TemporaryDirectory()
@@ -370,14 +396,21 @@ class MainTests(unittest.TestCase):
return make_server.main()
def _defaults(self, models="", host="", port="", backend="",
- lazy="", custom_path="", clone_path="", wav_dir="",
+ lazy="", custom_path="", clone_path="",
confirm="y", prefix=()):
- # First input selects the model family (default: Qwen3-TTS).
+ # First input selects the model family (default: Qwen3-TTS). The
+ # wav directory is always a positional argument, never prompted.
return list(prefix) + ["", models, host, port, backend, lazy,
- custom_path, clone_path, wav_dir, confirm]
+ custom_path, clone_path, confirm]
+
+ def test_required_wav_dir_missing_prints_usage(self):
+ with self.assertRaises(SystemExit) as ctx:
+ self._run(["--output", str(self.output)], inputs=[])
+ self.assertEqual(ctx.exception.code, 2)
+ self.assertFalse(self.output.exists())
def test_default_run_hosts_both_models(self):
- exit_code = self._run(["--output", str(self.output)],
+ exit_code = self._run([str(self.folder), "--output", str(self.output)],
inputs=self._defaults())
self.assertEqual(exit_code, 0)
data = json.loads(self.output.read_text(encoding="utf-8"))
@@ -395,7 +428,7 @@ class MainTests(unittest.TestCase):
self.assertNotIn("voice_presets", data["models"][1])
def test_eof_uses_all_defaults(self):
- exit_code = self._run(["--output", str(self.output)])
+ exit_code = self._run([str(self.folder), "--output", str(self.output)])
self.assertEqual(exit_code, 0)
data = json.loads(self.output.read_text(encoding="utf-8"))
self.assertEqual(data["host"], "127.0.0.1")
@@ -427,7 +460,7 @@ class MainTests(unittest.TestCase):
def test_custom_only_single_model(self):
inputs = ["", "", "", "", "", "", "y"]
exit_code = self._run(
- ["--output", str(self.output), "--models", "custom"],
+ [str(self.folder), "--output", str(self.output), "--models", "custom"],
inputs=inputs)
self.assertEqual(exit_code, 0)
data = json.loads(self.output.read_text(encoding="utf-8"))
@@ -437,8 +470,8 @@ class MainTests(unittest.TestCase):
def test_duplicate_ids_prompt_for_distinct_clone_id(self):
with patch.object(config, "AUDIOCPP_MODEL_ID", "qwen"), \
patch.object(config, "AUDIOCPP_CLONE_MODEL_ID", "qwen"):
- inputs = ["", "1", "qwen-clone-2", "", "", "", "", "", "", "", "y"]
- exit_code = self._run(["--output", str(self.output)],
+ inputs = ["", "1", "qwen-clone-2", "", "", "", "", "", "", "y"]
+ exit_code = self._run([str(self.folder), "--output", str(self.output)],
inputs=inputs)
self.assertEqual(exit_code, 0)
data = json.loads(self.output.read_text(encoding="utf-8"))
@@ -449,7 +482,7 @@ class MainTests(unittest.TestCase):
with patch.object(config, "AUDIOCPP_MODEL_ID", "qwen"), \
patch.object(config, "AUDIOCPP_CLONE_MODEL_ID", "qwen"):
with self.assertRaises(SystemExit) as ctx:
- self._run(["--output", str(self.output)])
+ self._run([str(self.folder), "--output", str(self.output)])
self.assertNotEqual(ctx.exception.code, 0)
self.assertFalse(self.output.exists())
@@ -457,7 +490,7 @@ class MainTests(unittest.TestCase):
with patch.object(config, "AUDIOCPP_API_URL",
"http://127.0.0.1:9999"):
inputs = ["", "", "", "y", "", "", "", "", "", "y"]
- exit_code = self._run(["--output", str(self.output),
+ exit_code = self._run([str(self.folder), "--output", str(self.output),
"--port", "8080"],
inputs=inputs)
self.assertEqual(exit_code, 0)
@@ -470,7 +503,7 @@ class MainTests(unittest.TestCase):
with patch.object(config, "AUDIOCPP_API_URL",
"http://127.0.0.1:9999"):
inputs = ["", "", "", "n", "", "", "", "", "", "y"]
- exit_code = self._run(["--output", str(self.output),
+ exit_code = self._run([str(self.folder), "--output", str(self.output),
"--port", "8080"],
inputs=inputs)
self.assertEqual(exit_code, 0)
@@ -481,7 +514,7 @@ class MainTests(unittest.TestCase):
with patch.object(config, "AUDIOCPP_API_URL",
"http://127.0.0.1:8080"):
inputs = self._defaults()
- exit_code = self._run(["--output", str(self.output)],
+ exit_code = self._run([str(self.folder), "--output", str(self.output)],
inputs=inputs)
self.assertEqual(exit_code, 0)
self.assertEqual(self.fake_config.read_text(encoding="utf-8"),
@@ -489,8 +522,8 @@ class MainTests(unittest.TestCase):
def test_invalid_menu_choice_reprompts(self):
# Family menu default, then an invalid models-menu choice retried.
- inputs = ["", "9", "", "", "", "", "", "", "", "", "y"]
- exit_code = self._run(["--output", str(self.output)],
+ inputs = ["", "9", "", "", "", "", "", "", "", "y"]
+ exit_code = self._run([str(self.folder), "--output", str(self.output)],
inputs=inputs)
self.assertEqual(exit_code, 0)
data = json.loads(self.output.read_text(encoding="utf-8"))
@@ -498,14 +531,14 @@ class MainTests(unittest.TestCase):
def test_confirm_declined_writes_nothing(self):
inputs = self._defaults(confirm="n")
- exit_code = self._run(["--output", str(self.output)],
+ exit_code = self._run([str(self.folder), "--output", str(self.output)],
inputs=inputs)
self.assertEqual(exit_code, 1)
self.assertFalse(self.output.exists())
def test_existing_output_declined_keeps_file(self):
self.output.write_text('{"old": true}', encoding="utf-8")
- exit_code = self._run(["--output", str(self.output)],
+ exit_code = self._run([str(self.folder), "--output", str(self.output)],
inputs=["n"])
self.assertEqual(exit_code, 1)
self.assertEqual(json.loads(self.output.read_text(encoding="utf-8")),
@@ -514,7 +547,7 @@ class MainTests(unittest.TestCase):
def test_existing_output_accepted_overwrites(self):
self.output.write_text('{"old": true}', encoding="utf-8")
inputs = ["y"] + self._defaults()
- exit_code = self._run(["--output", str(self.output)],
+ exit_code = self._run([str(self.folder), "--output", str(self.output)],
inputs=inputs)
self.assertEqual(exit_code, 0)
data = json.loads(self.output.read_text(encoding="utf-8"))
@@ -523,7 +556,8 @@ class MainTests(unittest.TestCase):
def test_force_overwrites_without_prompt(self):
self.output.write_text('{"old": true}', encoding="utf-8")
inputs = self._defaults()
- exit_code = self._run(["--output", str(self.output), "--force"],
+ exit_code = self._run([str(self.folder), "--output", str(self.output),
+ "--force"],
inputs=inputs)
self.assertEqual(exit_code, 0)
data = json.loads(self.output.read_text(encoding="utf-8"))
@@ -531,13 +565,13 @@ class MainTests(unittest.TestCase):
def test_flags_skip_prompts(self):
# Family still asked (no --family flag); port 9000 differs from the
- # config port so its sync prompt fires; custom/clone paths and the
- # wav dir use their defaults.
+ # config port so its sync prompt fires; custom/clone paths use
+ # their defaults.
exit_code = self._run(
- ["--output", str(self.output), "--models", "both",
+ [str(self.folder), "--output", str(self.output), "--models", "both",
"--host", "0.0.0.0", "--port", "9000", "--backend", "cpu",
"--lazy-load"],
- inputs=["", "y", "", "", "", "y"])
+ inputs=["", "y", "", "", "y"])
self.assertEqual(exit_code, 0)
self.assertIn('"http://127.0.0.1:9000"',
self.fake_config.read_text(encoding="utf-8"))
@@ -548,11 +582,15 @@ class MainTests(unittest.TestCase):
self.assertTrue(data["lazy_load"])
def test_missing_positional_wav_dir_errors(self):
- with self.assertRaises(SystemExit) as ctx:
- self._run([str(self.folder / "nope"),
- "--output", str(self.output)],
+ missing = self.folder / "nope"
+ with self.assertRaises(SystemExit) as ctx, \
+ patch("sys.stderr") as mock_stderr:
+ self._run([str(missing), "--output", str(self.output)],
inputs=self._defaults())
self.assertEqual(ctx.exception.code, 2)
+ shown = "".join(call[0][0] for call in mock_stderr.write.call_args_list)
+ self.assertIn(f"WAV directory not found: {missing.resolve()}", shown)
+ self.assertIn("directory containing the .wav", shown)
class NonQwenFamilyMainTests(unittest.TestCase):
@@ -613,10 +651,10 @@ class NonQwenFamilyMainTests(unittest.TestCase):
self.fake_config.read_text(encoding="utf-8"))
def test_model_id_sync_declined_keeps_config(self):
- # sync declined, host, port, backend, lazy, wav dir skipped, confirm
- inputs = ["n", "", "", "", "", "", "y"]
+ # sync declined, host, port, backend, lazy, confirm
+ inputs = ["n", "", "", "", "", "y"]
exit_code = self._run(
- ["--output", str(self.output), "--family", "voxcpm2",
+ [str(self.folder), "--output", str(self.output), "--family", "voxcpm2",
"--model-id", "voxcpm2", "--model-path", "models/VoxCPM2-GGUF"],
inputs=inputs)
self.assertEqual(exit_code, 0)
@@ -628,13 +666,14 @@ class NonQwenFamilyMainTests(unittest.TestCase):
def test_no_voice_presets_warns(self):
buf = io.StringIO()
- # sync accepted, host, port, backend, lazy, wav dir skipped, confirm
+ # sync accepted, host, port, backend, lazy, confirm
with patch.object(sys, "argv",
["make_audiocpp_server_json.py",
+ str(self.folder),
"--output", str(self.output),
"--family", "index_tts2", "--model-id", "indextts2",
"--model-path", "models/IndexTTS2-GGUF"]), \
- patch("builtins.input", side_effect=["y", "", "", "", "", "", "y"]), \
+ patch("builtins.input", side_effect=["y", "", "", "", "", "y"]), \
patch.object(make_server, "transcribe_reference_audio"), \
patch.object(make_server, "whisper_backend_available",
return_value="faster_whisper"), \
@@ -649,7 +688,7 @@ class NonQwenFamilyMainTests(unittest.TestCase):
def test_models_flag_rejected_for_non_qwen_family(self):
with self.assertRaises(SystemExit) as ctx:
- self._run(["--output", str(self.output),
+ self._run([str(self.folder), "--output", str(self.output),
"--family", "higgs_audio_tts", "--models", "both"])
self.assertEqual(ctx.exception.code, 2)