88 lines
2.7 KiB
Go
88 lines
2.7 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
//go:build linux && cgo
|
|
|
|
package speech
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestNativeUSBUsesOptionalABIAndReleasesResources(t *testing.T) {
|
|
root := t.TempDir()
|
|
library := filepath.Join(root, "libusb-1.0.so.0")
|
|
if output, err := exec.Command("cc", "-shared", "-fPIC", "-Wall", "-Wextra", "-Werror", "-o", library, "testdata/usb_fixture.c").CombinedOutput(); err != nil {
|
|
t.Fatalf("build USB fixture: %v: %s", err, output)
|
|
}
|
|
for _, mode := range []string{"ok", "unconfigured", "missing", "multiple", "denied", "busy", "short", "timeout"} {
|
|
t.Run(mode, func(t *testing.T) {
|
|
log := filepath.Join(t.TempDir(), "usb.log")
|
|
cmd := exec.Command(os.Args[0], "-test.run=^TestNativeUSBFixtureProcess$")
|
|
cmd.Env = append(os.Environ(), "LD_LIBRARY_PATH="+root, "FENRIR_USB_FIXTURE=1", "USB_FIXTURE_MODE="+mode, "USB_FIXTURE_LOG="+log)
|
|
if output, err := cmd.CombinedOutput(); err != nil {
|
|
t.Fatalf("fixture process: %v: %s", err, output)
|
|
}
|
|
data, err := os.ReadFile(log)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
text := string(data)
|
|
if !strings.HasPrefix(text, "init\nlist\n") || !strings.Contains(text, "free-list\n") || !strings.HasSuffix(text, "exit\n") {
|
|
t.Fatal("USB cleanup", text)
|
|
}
|
|
opened := mode != "missing" && mode != "multiple" && mode != "denied"
|
|
if strings.Contains(text, "\nclose\n") != opened {
|
|
t.Fatal("handle cleanup", text)
|
|
}
|
|
claimed := opened && mode != "busy"
|
|
if strings.Contains(text, "\nrelease\n") != claimed {
|
|
t.Fatal("interface cleanup", text)
|
|
}
|
|
if mode == "ok" || mode == "unconfigured" {
|
|
for _, want := range []string{"write-02:" + hex.EncodeToString([]byte("[:timeout 1]")), "write-02:" + hex.EncodeToString([]byte("[:ra 180]")), "write-02:" + hex.EncodeToString([]byte("hello\x0b")), "write-04:06"} {
|
|
if !strings.Contains(text, want+"\n") {
|
|
t.Fatal("missing transfer", want, text)
|
|
}
|
|
}
|
|
}
|
|
if strings.Contains(text, "set-configuration\n") != (mode == "unconfigured") {
|
|
t.Fatal("unexpected USB configuration change", text)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNativeUSBFixtureProcess(t *testing.T) {
|
|
if os.Getenv("FENRIR_USB_FIXTURE") != "1" {
|
|
return
|
|
}
|
|
transport, err := Open_driver("dectalk-usb", Options{})
|
|
mode := os.Getenv("USB_FIXTURE_MODE")
|
|
if mode != "ok" && mode != "unconfigured" {
|
|
if err == nil {
|
|
transport.Close()
|
|
t.Fatal("USB failure accepted", mode)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer transport.Close()
|
|
if err := transport.Configure(Parameters{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := transport.Say("hello"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := transport.Cancel(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|