Files
MusicServer/internal/backend/characters_test.go
Sansan c62b65d7cd
CI / integration (push) Successful in 21s
CI / test (push) Successful in 23s
CI / publish (push) Skipped
CI / docker (push) Successful in 48s
Add GET /api/v1/character/details with each image's change time
Returns every character image with when it was last changed, in Unix seconds,
so clients can cache the images and download only the ones that changed.
2026-10-07 21:57:26 +02:00

86 lines
2.4 KiB
Go

package backend
import (
"io"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func newCharacterService(t *testing.T) *CharacterService {
t.Helper()
base := t.TempDir()
writeFile(t, filepath.Join(base, "secret.png"), "outside")
dir := filepath.Join(base, "characters")
writeFile(t, filepath.Join(dir, "Adol.png"), "adol")
writeFile(t, filepath.Join(dir, "Aloy.JPG"), "aloy")
writeFile(t, filepath.Join(dir, "notes.txt"), "text")
writeFile(t, filepath.Join(dir, "sub", "Hidden.png"), "hidden")
c, err := NewCharacterService(dir)
require.NoError(t, err)
t.Cleanup(func() { c.Close() })
return c
}
func TestCharacterList(t *testing.T) {
characters, err := newCharacterService(t).List()
require.NoError(t, err)
assert.Equal(t, []string{"Adol.png", "Aloy.JPG"}, characters)
}
func TestCharacterListDetails(t *testing.T) {
c := newCharacterService(t)
changed := time.Date(2026, 10, 7, 12, 0, 0, 0, time.UTC)
require.NoError(t, c.root.Chtimes("Adol.png", changed, changed))
characters, err := c.ListDetails()
require.NoError(t, err)
require.Len(t, characters, 2)
assert.Equal(t, CharacterDetails{Name: "Adol.png", Modified: changed.Unix()}, characters[0])
assert.Equal(t, "Aloy.JPG", characters[1].Name)
}
func TestCharacterListDetailsSeesChangedImage(t *testing.T) {
c := newCharacterService(t)
before, err := c.ListDetails()
require.NoError(t, err)
later := time.Unix(before[0].Modified, 0).Add(time.Hour)
require.NoError(t, c.root.Chtimes("Adol.png", later, later))
after, err := c.ListDetails()
require.NoError(t, err)
assert.Greater(t, after[0].Modified, before[0].Modified)
assert.Equal(t, before[1], after[1], "unchanged images keep their time")
}
func TestCharacterOpen(t *testing.T) {
c := newCharacterService(t)
f, err := c.Open("Adol.png")
require.NoError(t, err)
content, _ := io.ReadAll(f)
f.Close()
assert.Equal(t, "adol", string(content))
_, err = c.Open("Missing.png")
assert.ErrorIs(t, err, ErrNotFound)
}
func TestCharacterOpenRejectsPathTraversal(t *testing.T) {
c := newCharacterService(t)
for _, name := range []string{"", "../secret.png", "sub/Hidden.png", "/etc/passwd", "..", "notes.txt"} {
_, err := c.Open(name)
assert.ErrorIs(t, err, ErrInvalidName, name)
}
}
func TestNewCharacterServiceMissingDir(t *testing.T) {
_, err := NewCharacterService(filepath.Join(t.TempDir(), "missing"))
assert.Error(t, err)
}