Files
Maven/internal/stt/stt_test.go
kami d52f60c54e maven: fix test mocks for CalendarEvents interface (verification)
- Add CalendarEvents method to recordingAPI in auth_test.go
- Add CalendarEvents method to fakeCore in handlers_test.go

Co-Authored-By: opencode <opencode@anthropic.com>
2026-07-06 04:20:16 +04:00

126 lines
3.3 KiB
Go

package stt
import (
"context"
"testing"
"github.com/kami/maven/internal/audio"
"github.com/kami/maven/internal/worker"
)
// fakeTranscriber — a worker.Transcriber that records the call.
type fakeTranscriber struct {
got audio.Audio
}
func (f *fakeTranscriber) Transcribe(_ context.Context, req worker.TranscribeReq) (worker.TranscribeResp, error) {
f.got = req.Audio
return worker.TranscribeResp{Text: "hello world", Confidence: 0.7}, nil
}
func TestStubReturnsDeterministicPhrase(t *testing.T) {
t.Parallel()
s := NewStub()
a := audio.Audio{Format: audio.PCM16kMono, Bytes: []byte("utterance-A")}
text, conf, err := s.Transcribe(context.Background(), a)
if err != nil {
t.Fatalf("Stub.Transcribe: %v", err)
}
if conf != 1.0 {
t.Fatalf("Stub confidence should be 1.0, got %v", conf)
}
// same input ⇒ same output (deterministic; tests can rely on this).
text2, _, _ := s.Transcribe(context.Background(), a)
if text != text2 {
t.Fatalf("Stub should be deterministic: %q vs %q", text, text2)
}
// phrases come from the stubPhrases list.
found := false
for _, p := range stubPhrases {
if p == text {
found = true
break
}
}
if !found {
t.Fatalf("Stub phrase %q not in stubPhrases", text)
}
}
func TestStubEmptyAudioReturnsFirstPhrase(t *testing.T) {
t.Parallel()
s := NewStub()
text, _, err := s.Transcribe(context.Background(), audio.Audio{Format: audio.PCM16kMono})
if err != nil {
t.Fatalf("Stub.Transcribe: %v", err)
}
if text != stubPhrases[0] {
t.Fatalf("empty audio should return first phrase %q, got %q", stubPhrases[0], text)
}
}
func TestStubDifferentAudioMayPickDifferentPhrase(t *testing.T) {
t.Parallel()
s := NewStub()
// try enough variants to land at least two different phrases.
seen := map[string]struct{}{}
for i := 0; i < 200; i++ {
b := make([]byte, 64)
for j := range b {
b[j] = byte(i + j)
}
text, _, _ := s.Transcribe(context.Background(), audio.Audio{Format: audio.PCM16kMono, Bytes: b})
seen[text] = struct{}{}
if len(seen) >= 2 {
return
}
}
t.Fatalf("expected ≥2 distinct phrases across varied audio, got %d", len(seen))
}
func TestRemoteForwardsToClient(t *testing.T) {
t.Parallel()
// stand up a worker.Server with the fakeTranscriber behind it.
srv := worker.NewServer(t.TempDir()+"/stt.sock", &fakeTranscriber{})
if err := srv.Listen(); err != nil {
t.Fatalf("listen: %v", err)
}
defer srv.Close()
go srv.Serve()
c := worker.Dial(srv.Path())
defer c.Close()
r := NewRemote(c, "ru")
in := audio.Audio{Format: audio.PCM16kMono, Bytes: []byte("payload")}
text, conf, err := r.Transcribe(context.Background(), in)
if err != nil {
t.Fatalf("Remote.Transcribe: %v", err)
}
if text != "hello world" {
t.Fatalf("Text: %q, want %q", text, "hello world")
}
if conf != 0.7 {
t.Fatalf("Confidence: %v, want 0.7", conf)
}
}
func TestRemoteErrorWraps(t *testing.T) {
t.Parallel()
// a server with no transcriber ⇒ ErrUnknownMethod on Transcribe.
srv := worker.NewSynthesizerServer(t.TempDir()+"/stt.sock", nil)
if err := srv.Listen(); err != nil {
t.Fatalf("listen: %v", err)
}
defer srv.Close()
go srv.Serve()
c := worker.Dial(srv.Path())
defer c.Close()
r := NewRemote(c, "ru")
_, _, err := r.Transcribe(context.Background(), audio.Audio{Format: audio.PCM16kMono, Bytes: []byte("x")})
if err == nil {
t.Fatalf("want error, got nil")
}
}