#!/usr/bin/env python3 """Smoke tests for hermes_voice_gateway helper code. These tests avoid live Hermes/STT/TTS calls. They verify the pieces that are safe to exercise locally: content-type mapping, response MIME mapping, header sanitization, fallback ACK WAV generation, and ffmpeg WAV normalization when ffmpeg is available. """ from __future__ import annotations import shutil import tempfile import wave from pathlib import Path from api_server_endpoint import ( audio_extension_for_content_type, audio_response_mime, convert_audio_to_esp32_wav, make_ack_wav, safe_audio_header, ) def _assert_wav_16k_mono_s16(path: Path) -> None: with wave.open(str(path), "rb") as wav: assert wav.getnchannels() == 1, wav.getnchannels() assert wav.getsampwidth() == 2, wav.getsampwidth() assert wav.getframerate() == 16000, wav.getframerate() assert wav.getnframes() > 0, wav.getnframes() def main() -> None: assert audio_extension_for_content_type("audio/wav") == ".wav" assert audio_extension_for_content_type("audio/wav; charset=binary") == ".wav" assert audio_extension_for_content_type("audio/webm") == ".webm" assert audio_extension_for_content_type("application/unknown") == ".wav" assert audio_response_mime("reply.wav") == "audio/wav" assert audio_response_mime("reply.mp3") == "audio/mpeg" assert audio_response_mime("reply.bin") == "application/octet-stream" assert safe_audio_header("hello\nworld\r\x00!", 100) == "hello world !" assert safe_audio_header("abcdef", 3) == "abc" with tempfile.TemporaryDirectory() as tmp: tmpdir = Path(tmp) ack = make_ack_wav(tmpdir / "ack.wav") _assert_wav_16k_mono_s16(ack) if shutil.which("ffmpeg"): converted = convert_audio_to_esp32_wav(str(ack), output_dir=tmpdir, device_id="kitchen/button") _assert_wav_16k_mono_s16(converted) assert "kitchen_button" in converted.name else: print("ffmpeg not found; skipped conversion path") print("hermes_voice_gateway smoke tests passed") if __name__ == "__main__": main()