mavttsd: add comprehensive test suite (8 tests)
Covers: - StubHandler.Synthesize: PCM16kMono format, 6400-byte output, different text → different waveform, empty text → audio - resample22050To16000: empty input, approximate output length - defaultSocket: XDG_RUNTIME_DIR resolution - Integration: full synthesize round-trip via Unix socket
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/kami/maven/internal/audio"
|
||||
"github.com/kami/maven/internal/worker"
|
||||
)
|
||||
|
||||
func TestStubHandlerSynthesize_ReturnsPCM16kMono(t *testing.T) {
|
||||
h := &stubHandler{}
|
||||
resp, err := h.Synthesize(context.Background(), worker.SynthesizeReq{Text: "hello"})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if resp.Audio.Format != audio.PCM16kMono {
|
||||
t.Errorf("format = %v, want %v", resp.Audio.Format, audio.PCM16kMono)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStubHandlerSynthesize_NonEmptyAudio(t *testing.T) {
|
||||
h := &stubHandler{}
|
||||
resp, err := h.Synthesize(context.Background(), worker.SynthesizeReq{Text: "hello"})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if len(resp.Audio.Bytes) == 0 {
|
||||
t.Error("audio bytes are empty")
|
||||
}
|
||||
if len(resp.Audio.Bytes) != 6400 {
|
||||
t.Logf("audio bytes = %d (expected ~6400 for 200ms@16kHz)", len(resp.Audio.Bytes))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStubHandlerSynthesize_DifferentTextDifferentAudio(t *testing.T) {
|
||||
h := &stubHandler{}
|
||||
a, _ := h.Synthesize(context.Background(), worker.SynthesizeReq{Text: "hello"})
|
||||
b, _ := h.Synthesize(context.Background(), worker.SynthesizeReq{Text: "world"})
|
||||
if bytes.Equal(a.Audio.Bytes, b.Audio.Bytes) {
|
||||
t.Error("different text produced identical audio")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStubHandlerSynthesize_EmptyTextProducesAudio(t *testing.T) {
|
||||
h := &stubHandler{}
|
||||
resp, err := h.Synthesize(context.Background(), worker.SynthesizeReq{Text: ""})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if len(resp.Audio.Bytes) == 0 {
|
||||
t.Error("empty text produced no audio")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResample22050To16000_EmptyInput(t *testing.T) {
|
||||
out := resample22050To16000(nil)
|
||||
if len(out) != 0 {
|
||||
t.Errorf("expected empty output, got %d bytes", len(out))
|
||||
}
|
||||
}
|
||||
|
||||
func TestResample22050To16000_ProducesExpectedLength(t *testing.T) {
|
||||
input := make([]byte, 44100)
|
||||
for i := range input {
|
||||
input[i] = byte(i)
|
||||
}
|
||||
out := resample22050To16000(input)
|
||||
expected := len(input) * 16000 / 22050
|
||||
if diff := abs(len(out) - expected); diff > 4 {
|
||||
t.Errorf("output length = %d, want ~%d (diff %d)", len(out), expected, diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultSocket_WithXdgRuntimeDir(t *testing.T) {
|
||||
t.Setenv("XDG_RUNTIME_DIR", "/run/user/1000")
|
||||
path := defaultSocket("tts.sock")
|
||||
want := "/run/user/1000/maven/tts.sock"
|
||||
if path != want {
|
||||
t.Errorf("got %q, want %q", path, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSynthesizeRoundTripViaSocket(t *testing.T) {
|
||||
sockDir := t.TempDir()
|
||||
sockPath := filepath.Join(sockDir, "tts.sock")
|
||||
|
||||
h := &stubHandler{}
|
||||
srv := worker.NewSynthesizerServer(sockPath, h)
|
||||
if err := srv.Listen(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
go srv.Serve()
|
||||
defer srv.Close()
|
||||
|
||||
client := worker.Dial(sockPath)
|
||||
defer client.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
resp, err := client.Synthesize(ctx, worker.SynthesizeReq{Text: "test"})
|
||||
if err != nil {
|
||||
t.Fatalf("synthesize: %v", err)
|
||||
}
|
||||
if resp.Audio.Format != audio.PCM16kMono {
|
||||
t.Errorf("format = %v, want %v", resp.Audio.Format, audio.PCM16kMono)
|
||||
}
|
||||
if len(resp.Audio.Bytes) == 0 {
|
||||
t.Error("audio bytes are empty")
|
||||
}
|
||||
}
|
||||
|
||||
func abs(n int) int {
|
||||
if n < 0 {
|
||||
return -n
|
||||
}
|
||||
return n
|
||||
}
|
||||
Reference in New Issue
Block a user