import io import json import struct import sys import wave import httpx import pytest from fastapi.testclient import TestClient from knaster.audio import rtf, wav_duration from knaster.bench import bench_tts from knaster.canary import CanaryProber from knaster.llm import OpenAIChatClient from knaster.tts_server import CommandBackend, create_tts_app def make_wav(seconds: float, rate: int = 22050) -> bytes: buf = io.BytesIO() with wave.open(buf, "wb") as w: w.setnchannels(1) w.setsampwidth(2) w.setframerate(rate) w.writeframes(struct.pack(" httpx.Response: assert request.url.path == "/v1/audio/speech" body = json.loads(request.content) if fail or body["model"] == "kaputt": return httpx.Response(503, text="down") return httpx.Response(200, content=make_wav(seconds), headers={"content-type": "audio/wav"}) return httpx.Client(transport=httpx.MockTransport(handler)) def test_bench_tts(): client = OpenAIChatClient("http://x", client=tts_transport(2.0)) result = bench_tts("http://x", "tts-de", runs=2, client=client) assert len(result["runs"]) == 2 and result["errors"] == [] assert result["runs"][0]["audio_seconds"] == 2.0 and result["rtf_median"] is not None bad = bench_tts("http://x", "kaputt", runs=1, client=client) assert bad["runs"] == [] and bad["errors"] def test_canary_probes_tts_slots(registry): from prometheus_client import CollectorRegistry from knaster.registry import Registry from knaster.store import Store from .conftest import REGISTRY data = {"slots": {**REGISTRY["slots"], "tts-de": { "tier": 1, "device": "cpu", "engine": "piper", "litellm_model": "tts-de", "base_model": "piper", "max_context": 5000, "kind": "tts"}}} reg = Registry.from_dict(data, Store("sqlite://")) chat = OpenAIChatClient("http://x", client=tts_transport(0.8)) prober = CanaryProber(reg, chat, metrics_registry=CollectorRegistry()) tts = next(prober.probe(s) for s in reg.slots() if s.name == "tts-de") assert tts.up and tts.ok silent = OpenAIChatClient("http://x", client=tts_transport(0.05)) assert not CanaryProber(reg, silent, metrics_registry=CollectorRegistry()).probe(reg.slot("tts-de")).ok down = OpenAIChatClient("http://x", client=tts_transport(fail=True)) assert not CanaryProber(reg, down, metrics_registry=CollectorRegistry()).probe(reg.slot("tts-de")).up