cf53912a33
Issue: #9 Backend: - GET /api/list-wavs?dir=<path> — lists .wav files in a directory - GET /wavs/<file> — static file serving from ./output/wavs Web UI: - WAV Browser section with path input + Browse button - AudioContext-based playback (zero deps) — progress bar, time display - WAV file grid with Play buttons, active item highlighting Tests: - 3 new tests for handleListWavs (wav files, empty dir, nonexistent dir) - Fix TestFindAkaiutil: add t.Chdir(tmp) so relative path lookups don't accidentally find the repo's third_party/akaiutil/akaiutil binary
205 lines
4.8 KiB
Go
205 lines
4.8 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestSanitiseISOName(t *testing.T) {
|
|
cases := []struct {
|
|
input string
|
|
expected string
|
|
}{
|
|
{"ZERO-G - Deepest India", "ZERO-G_-_Deepest_India"},
|
|
{"SYNTH PAD COLLECTION.iso", "SYNTH_PAD_COLLECTION"},
|
|
{"vocal.loops", "vocal"},
|
|
{"DRUM KIT #1", "DRUM_KIT_1"},
|
|
{"simple", "simple"},
|
|
{"no-extension", "no-extension"},
|
|
{"multiple spaces", "multiple_spaces"},
|
|
{"UPPERCASE", "UPPERCASE"},
|
|
{"MiXeD CaSe", "MiXeD_CaSe"},
|
|
{"with-dash", "with-dash"},
|
|
{"with_underscore", "with_underscore"},
|
|
{"with.dots.in.name", "with.dots.in"},
|
|
{".hidden", ""},
|
|
{"trailing_", "trailing"},
|
|
{"__leading__", "leading"},
|
|
{"spaces everywhere", "spaces_everywhere"},
|
|
{"", ""},
|
|
{" ", ""},
|
|
{".iso", ""},
|
|
{"a", "a"},
|
|
}
|
|
for _, c := range cases {
|
|
got := sanitiseISOName(c.input)
|
|
if got != c.expected {
|
|
t.Errorf("sanitiseISOName(%q) = %q, want %q", c.input, got, c.expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTruncate(t *testing.T) {
|
|
cases := []struct {
|
|
s string
|
|
n int
|
|
expect string
|
|
}{
|
|
{"hello", 10, "hello"},
|
|
{"hello", 5, "hello"},
|
|
{"hello", 4, "h..."},
|
|
{"hello", 3, "..."},
|
|
{"hello", 2, "he"},
|
|
{"hello", 1, "h"},
|
|
{"hello", 0, ""},
|
|
{"", 5, ""},
|
|
{"abcdef", 4, "a..."},
|
|
{"ab", 4, "ab"},
|
|
{"abc", 3, "abc"},
|
|
{"abcd", 2, "ab"},
|
|
}
|
|
for _, c := range cases {
|
|
got := truncate(c.s, c.n)
|
|
if got != c.expect {
|
|
t.Errorf("truncate(%q, %d) = %q, want %q", c.s, c.n, got, c.expect)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHumanSize(t *testing.T) {
|
|
cases := []struct {
|
|
bytes int64
|
|
expect string
|
|
}{
|
|
{0, "0B"},
|
|
{500, "500B"},
|
|
{1024, "1.0 KB"},
|
|
{1536, "1.5 KB"},
|
|
{10240, "10.0 KB"},
|
|
{1048576, "1.0 MB"},
|
|
{1572864, "1.5 MB"},
|
|
{1073741824, "1.0 GB"},
|
|
{2147483648, "2.0 GB"},
|
|
}
|
|
for _, c := range cases {
|
|
got := humanSize(c.bytes)
|
|
if got != c.expect {
|
|
t.Errorf("humanSize(%d) = %q, want %q", c.bytes, got, c.expect)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFindAkaiutil(t *testing.T) {
|
|
origEnv := os.Getenv("AKAIUTIL")
|
|
origArg0 := os.Args[0]
|
|
defer func() {
|
|
_ = os.Setenv("AKAIUTIL", origEnv)
|
|
os.Args[0] = origArg0
|
|
}()
|
|
|
|
t.Run("env var set to missing file", func(t *testing.T) {
|
|
tmp := t.TempDir()
|
|
t.Chdir(tmp)
|
|
_ = os.Setenv("AKAIUTIL", "/nonexistent/akaiutil")
|
|
os.Args[0] = "/some/binary"
|
|
_, err := findAkaiutil()
|
|
if err == nil {
|
|
t.Fatal("expected error for missing env var path")
|
|
}
|
|
})
|
|
|
|
t.Run("env var set to existing file", func(t *testing.T) {
|
|
tmp := t.TempDir()
|
|
t.Chdir(tmp)
|
|
f := tmp + "/myutil"
|
|
fd, _ := os.Create(f)
|
|
defer func() { _ = fd.Close() }()
|
|
_ = os.Setenv("AKAIUTIL", f)
|
|
got, err := findAkaiutil()
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got %v", err)
|
|
}
|
|
if got != f {
|
|
t.Errorf("got %q, want %q", got, f)
|
|
}
|
|
})
|
|
|
|
t.Run("finds binary next to argv[0]", func(t *testing.T) {
|
|
tmp := t.TempDir()
|
|
t.Chdir(tmp)
|
|
exe := tmp + "/mybinary"
|
|
fd, _ := os.Create(exe)
|
|
defer func() { _ = fd.Close() }()
|
|
sideBySide := tmp + "/akaiutil"
|
|
fd2, _ := os.Create(sideBySide)
|
|
defer func() { _ = fd2.Close() }()
|
|
_ = os.Setenv("AKAIUTIL", "")
|
|
os.Args[0] = exe
|
|
got, err := findAkaiutil()
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got %v", err)
|
|
}
|
|
if got != sideBySide {
|
|
t.Errorf("got %q, want %q", got, sideBySide)
|
|
}
|
|
})
|
|
|
|
t.Run("finds binary in third_party relative to argv[0]", func(t *testing.T) {
|
|
tmp := t.TempDir()
|
|
t.Chdir(tmp)
|
|
exe := tmp + "/somebin"
|
|
fd, _ := os.Create(exe)
|
|
defer func() { _ = fd.Close() }()
|
|
thirdParty := filepath.Join(tmp, "third_party", "akaiutil")
|
|
if err := os.MkdirAll(thirdParty, 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
akaiutilInThirdParty := filepath.Join(thirdParty, "akaiutil")
|
|
fd2, _ := os.Create(akaiutilInThirdParty)
|
|
defer func() { _ = fd2.Close() }()
|
|
_ = os.Setenv("AKAIUTIL", "")
|
|
os.Args[0] = exe
|
|
got, err := findAkaiutil()
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got %v", err)
|
|
}
|
|
if got != akaiutilInThirdParty {
|
|
t.Errorf("got %q, want %q", got, akaiutilInThirdParty)
|
|
}
|
|
})
|
|
|
|
t.Run("env var takes priority over path candidates", func(t *testing.T) {
|
|
tmp := t.TempDir()
|
|
t.Chdir(tmp)
|
|
envFile := tmp + "/envutil"
|
|
pathFile := tmp + "/pathutil"
|
|
fd1, _ := os.Create(envFile)
|
|
defer func() { _ = fd1.Close() }()
|
|
fd2, _ := os.Create(pathFile)
|
|
defer func() { _ = fd2.Close() }()
|
|
_ = os.Setenv("AKAIUTIL", envFile)
|
|
os.Args[0] = pathFile
|
|
got, err := findAkaiutil()
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got %v", err)
|
|
}
|
|
if got != envFile {
|
|
t.Errorf("got %q, want env var path %q", got, envFile)
|
|
}
|
|
})
|
|
|
|
t.Run("no akaiutil found returns error", func(t *testing.T) {
|
|
tmp := t.TempDir()
|
|
t.Chdir(tmp)
|
|
exe := tmp + "/nobinaryhere"
|
|
fd, _ := os.Create(exe)
|
|
defer func() { _ = fd.Close() }()
|
|
_ = os.Setenv("AKAIUTIL", "")
|
|
os.Args[0] = exe
|
|
_, err := findAkaiutil()
|
|
if err == nil {
|
|
t.Fatal("expected error when no akaiutil found")
|
|
}
|
|
})
|
|
} |