Speech-dispatcher handling improved.

This commit is contained in:
Storm Dragon committed 2026-10-28 11:34:57 -04:00
1 parent 60abcc37d9
commit ec32c6e4c4
11 files changed
+638 -222

No files matched your search

+124
View File
@@ -0,0 +1,124 @@
// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package speech
import (
"net"
"os"
"path/filepath"
"strings"
"testing"
)
func TestResolveServerAddressPrecedence(t *testing.T) {
t.Setenv("SUDO_UID", "")
runtimeDirectory := t.TempDir()
cacheDirectory := t.TempDir()
t.Setenv("XDG_RUNTIME_DIR", runtimeDirectory)
t.Setenv("XDG_CACHE_HOME", cacheDirectory)
t.Setenv("SPEECHD_SOCKET", "/tmp/legacy-speech.sock")
t.Setenv("SPEECHD_ADDRESS", "unix_socket:/tmp/address-speech.sock")
for _, test := range []struct {
name, override, speechAddress, legacySocket, runtimeDir, want string
}{
{"explicit", "/tmp/explicit-speech.sock", "unix_socket:/tmp/address-speech.sock", "/tmp/legacy-speech.sock", runtimeDirectory, "/tmp/explicit-speech.sock"},
{"address", "", "unix_socket:/tmp/address-speech.sock", "/tmp/legacy-speech.sock", runtimeDirectory, "/tmp/address-speech.sock"},
{"legacy", "", "", "/tmp/legacy-speech.sock", runtimeDirectory, "/tmp/legacy-speech.sock"},
{"runtime", "", "", "", runtimeDirectory, filepath.Join(runtimeDirectory, "speech-dispatcher", "speechd.sock")},
{"cache", "", "", "", "", filepath.Join(cacheDirectory, "speech-dispatcher", "speechd.sock")},
} {
t.Run(test.name, func(t *testing.T) {
t.Setenv("SPEECHD_ADDRESS", test.speechAddress)
t.Setenv("SPEECHD_SOCKET", test.legacySocket)
t.Setenv("XDG_RUNTIME_DIR", test.runtimeDir)
got, err := resolve_server_address(test.override)
if err != nil || got.network != "unix" || got.address != test.want {
t.Fatalf("address = %+v, error = %v; want %q", got, err, test.want)
}
})
}
}
func TestParseServerAddress(t *testing.T) {
for _, test := range []struct {
input, network, address string
}{
{"unix_socket:/tmp/speech.sock", "unix", "/tmp/speech.sock"},
{"inet_socket", "tcp4", "127.0.0.1:6560"},
{"inet_socket:localhost:6561", "tcp4", "localhost:6561"},
{"inet_socket::6561", "tcp4", "127.0.0.1:6561"},
} {
got, err := parse_server_address(test.input)
if err != nil || got.network != test.network || got.address != test.address {
t.Fatalf("parse %q = %+v, %v", test.input, got, err)
}
}
for _, address := range []string{"invalid:/tmp/speech.sock", "unix_socket:relative.sock", "inet_socket:localhost:0", "inet_socket:localhost:bad"} {
if _, err := parse_server_address(address); err == nil {
t.Fatalf("accepted invalid address %q", address)
}
}
}
func TestSpeechAddressUsedByClientAndDiscovery(t *testing.T) {
for _, network := range []string{"unix", "tcp4"} {
t.Run(network, func(t *testing.T) {
var server *fakeServer
if network == "unix" {
server = new_fake_server(t, false)
} else {
listener, err := net.Listen("tcp4", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
server = new_fake_server_listener(t, false, listener)
}
address := "unix_socket:" + server.path
if network == "tcp4" {
address = "inet_socket:" + server.path
}
t.Setenv("SPEECHD_ADDRESS", address)
t.Setenv("SPEECHD_SOCKET", "/absent.sock")
t.Setenv("SPEECHD_CMD", "/nonexistent/speech-dispatcher")
client, err := Prepare("speech-dispatcher", Options{Module: "fixture", Voice: "Base Voice"})
if err != nil {
t.Fatal(err)
}
defer client.Close()
if _, err := Discover(Options{}); err != nil {
t.Fatal(err)
}
if err := client.Say("connection fixture"); err != nil {
t.Fatal(err)
}
wait_event(t, server.events, "say:connection fixture")
if err := client.Cancel(); err != nil {
t.Fatal(err)
}
wait_event(t, server.events, "CANCEL 41")
})
}
}
func TestInvalidAddressDoesNotFallBack(t *testing.T) {
server := new_fake_server(t, false)
t.Setenv("SPEECHD_ADDRESS", "unsupported:address")
t.Setenv("SPEECHD_SOCKET", server.path)
if _, err := Open(Options{}); err == nil || !strings.Contains(err.Error(), "unsupported") {
t.Fatalf("error = %v", err)
}
}
func TestDefaultSocketWithoutRuntimeOrCacheEnvironment(t *testing.T) {
t.Setenv("SUDO_UID", "")
t.Setenv("XDG_RUNTIME_DIR", "")
t.Setenv("XDG_CACHE_HOME", "")
t.Setenv("HOME", t.TempDir())
want := filepath.Join(os.Getenv("HOME"), ".cache", "speech-dispatcher", "speechd.sock")
if got := default_socket_path(); got != want {
t.Fatalf("socket %q, want %q", got, want)
}
}