package backend import ( "io" "path/filepath" "testing" "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 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) }