150 lines
4.3 KiB
Go
150 lines
4.3 KiB
Go
package transcriber
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestWhisperCppAdapter_ImplementsBatchAdapter(t *testing.T) {
|
|
// compile-time check that WhisperCppAdapter implements BatchAdapter
|
|
var _ BatchAdapter = (*WhisperCppAdapter)(nil)
|
|
}
|
|
|
|
func TestWhisperCppAdapter_EmptyAudio(t *testing.T) {
|
|
adapter := NewWhisperCppAdapter("/nonexistent/model.bin", "en", 4)
|
|
text, err := adapter.Transcribe(context.Background(), []byte{})
|
|
if err != nil {
|
|
t.Errorf("expected no error for empty audio, got: %v", err)
|
|
}
|
|
if text != "" {
|
|
t.Errorf("expected empty text for empty audio, got: %q", text)
|
|
}
|
|
}
|
|
|
|
func TestWhisperCppAdapter_MissingModel(t *testing.T) {
|
|
adapter := NewWhisperCppAdapter("/nonexistent/path/model.bin", "en", 4)
|
|
|
|
// create minimal valid PCM data (just zeros)
|
|
audioData := make([]byte, 32000) // 1 second at 16kHz 16-bit
|
|
|
|
_, err := adapter.Transcribe(context.Background(), audioData)
|
|
if err == nil {
|
|
t.Error("expected error for missing model file")
|
|
}
|
|
if err != nil && !contains(err.Error(), "model file not found") {
|
|
t.Errorf("expected 'model file not found' error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestWhisperCppAdapter_MissingCli(t *testing.T) {
|
|
if _, err := exec.LookPath("whisper-cli"); err == nil {
|
|
t.Skip("whisper-cli is installed")
|
|
}
|
|
|
|
tmpDir := t.TempDir()
|
|
modelPath := filepath.Join(tmpDir, "model.bin")
|
|
if err := os.WriteFile(modelPath, []byte("fake"), 0600); err != nil {
|
|
t.Fatalf("failed to create model: %v", err)
|
|
}
|
|
|
|
adapter := NewWhisperCppAdapter(modelPath, "en", 4)
|
|
audioData := make([]byte, 32000)
|
|
|
|
_, err := adapter.Transcribe(context.Background(), audioData)
|
|
if err == nil {
|
|
t.Error("expected error for missing whisper-cli")
|
|
}
|
|
if err != nil && !contains(err.Error(), "whisper-cli not found") {
|
|
t.Errorf("expected 'whisper-cli not found' error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestWhisperCppAdapter_LanguageConversion(t *testing.T) {
|
|
// verify adapter stores language for later conversion
|
|
adapter := NewWhisperCppAdapter("/fake/model.bin", "", 4)
|
|
if adapter.language != "" {
|
|
t.Errorf("expected empty language for auto, got: %q", adapter.language)
|
|
}
|
|
|
|
adapter = NewWhisperCppAdapter("/fake/model.bin", "en", 4)
|
|
if adapter.language != "en" {
|
|
t.Errorf("expected 'en' language, got: %q", adapter.language)
|
|
}
|
|
}
|
|
|
|
func TestWhisperCppAdapter_ThreadsConfig(t *testing.T) {
|
|
adapter := NewWhisperCppAdapter("/fake/model.bin", "en", 0)
|
|
if adapter.threads != 0 {
|
|
t.Errorf("expected threads=0 (auto), got: %d", adapter.threads)
|
|
}
|
|
|
|
adapter = NewWhisperCppAdapter("/fake/model.bin", "en", 8)
|
|
if adapter.threads != 8 {
|
|
t.Errorf("expected threads=8, got: %d", adapter.threads)
|
|
}
|
|
}
|
|
|
|
func TestWhisperCppAdapter_TempFileCleanup(t *testing.T) {
|
|
// this test requires whisper-cli and a model to be installed
|
|
// skip if not available
|
|
modelPath := os.Getenv("WHISPER_TEST_MODEL")
|
|
if modelPath == "" {
|
|
t.Skip("WHISPER_TEST_MODEL not set, skipping temp file cleanup test")
|
|
}
|
|
|
|
adapter := NewWhisperCppAdapter(modelPath, "en", 4)
|
|
|
|
// create minimal audio data
|
|
audioData := make([]byte, 32000)
|
|
|
|
// run transcription
|
|
_, _ = adapter.Transcribe(context.Background(), audioData)
|
|
|
|
// check that temp file was cleaned up
|
|
// (we can't easily verify this without modifying the adapter to expose temp path)
|
|
// this is more of a visual/log verification
|
|
}
|
|
|
|
func TestWhisperCppAdapter_ContextCancellation(t *testing.T) {
|
|
// skip if whisper-cli not installed
|
|
if _, err := os.Stat("/usr/local/bin/whisper-cli"); os.IsNotExist(err) {
|
|
t.Skip("whisper-cli not installed")
|
|
}
|
|
|
|
// create a fake model file for this test
|
|
tmpDir := t.TempDir()
|
|
fakeModel := filepath.Join(tmpDir, "fake.bin")
|
|
if err := os.WriteFile(fakeModel, []byte("fake"), 0600); err != nil {
|
|
t.Fatalf("failed to create fake model: %v", err)
|
|
}
|
|
|
|
adapter := NewWhisperCppAdapter(fakeModel, "en", 4)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel() // cancel immediately
|
|
|
|
// create minimal audio data
|
|
audioData := make([]byte, 32000)
|
|
|
|
_, err := adapter.Transcribe(ctx, audioData)
|
|
if err == nil {
|
|
t.Error("expected error for cancelled context")
|
|
}
|
|
}
|
|
|
|
func contains(s, substr string) bool {
|
|
return len(s) >= len(substr) && (s == substr || len(s) > 0 && containsHelper(s, substr))
|
|
}
|
|
|
|
func containsHelper(s, substr string) bool {
|
|
for i := 0; i <= len(s)-len(substr); i++ {
|
|
if s[i:i+len(substr)] == substr {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|