ci / api / api (push) Successful in 56s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m23s
ci / db / db (push) Successful in 1m8s
ci / recommender / recommender (push) Failing after 40s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m25s
ci / ts / ts (packages + web) (push) Successful in 7m20s
86 lines
3.5 KiB
Go
86 lines
3.5 KiB
Go
package library
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"pipu/api/internal/auth"
|
|
)
|
|
|
|
func TestNormalizeExcludedDirs(t *testing.T) {
|
|
dirs, err := normalizeExcludedDirs([]string{" Downloads_PumpEars/ ", `Artist\Samples`, "Downloads_PumpEars", "Artist/./Samples", "100%_loops"})
|
|
require.NoError(t, err)
|
|
require.Equal(t, []string{"Downloads_PumpEars", "Artist/Samples", "100%_loops"}, dirs)
|
|
for _, invalid := range []string{"", ".", "./", "/etc", "../outside", "album/../samples", `C:\Downloads`, `\\server\share`, "folder\nother", strings.Repeat("a", 1001)} {
|
|
t.Run(invalid, func(t *testing.T) {
|
|
_, err := normalizeExcludedDirs([]string{invalid})
|
|
require.Error(t, err)
|
|
})
|
|
}
|
|
_, err = normalizeExcludedDirs(make([]string, 101))
|
|
require.Error(t, err)
|
|
dirs, err = normalizeExcludedDirs(nil)
|
|
require.NoError(t, err)
|
|
require.Empty(t, dirs)
|
|
}
|
|
|
|
func TestWalkPrunesExcludedSubtrees(t *testing.T) {
|
|
root := t.TempDir()
|
|
for _, rel := range []string{"Downloads_PumpEars/sample.wav", "Downloads_PumpEars/nested/sample.wav", "Downloads_PumpEars-copy/song.flac", "Artist/Downloads_PumpEars/song.flac", "Artist/Samples/loop.wav", "Artist/Album/song.flac", "100%_loops/loop.wav", "100xxloops/song.flac"} {
|
|
p := filepath.Join(root, filepath.FromSlash(rel))
|
|
require.NoError(t, os.MkdirAll(filepath.Dir(p), 0o755))
|
|
require.NoError(t, os.WriteFile(p, []byte("audio"), 0o644))
|
|
}
|
|
dirs := []string{"Downloads_PumpEars", "Artist/Samples", "100%_loops"}
|
|
var visited []string
|
|
found, err := walk(root, dirs, func(string) bool { return false }, func(_, _ int, current string) { visited = append(visited, current) })
|
|
require.NoError(t, err)
|
|
require.ElementsMatch(t, []string{"Downloads_PumpEars-copy/song.flac", "Artist/Downloads_PumpEars/song.flac", "Artist/Album/song.flac", "100xxloops/song.flac"}, rels(found))
|
|
for _, dir := range visited {
|
|
require.False(t, pathExcluded(dir, dirs), "excluded directories must not be visited")
|
|
}
|
|
// A point scan must reject an excluded path before touching storage or the filesystem.
|
|
_, err = (&Scanner{}).ScanFile(context.Background(), Source{ExcludedDirs: dirs}, root, "Downloads_PumpEars/sample.wav")
|
|
require.ErrorContains(t, err, "excluded scan folder")
|
|
}
|
|
|
|
type exclusionsSourceStore struct {
|
|
SourceStore
|
|
source Source
|
|
}
|
|
|
|
func (s *exclusionsSourceStore) GetSource(context.Context, uuid.UUID) (Source, error) {
|
|
return s.source, nil
|
|
}
|
|
func (s *exclusionsSourceStore) SaveSource(_ context.Context, src Source) (Source, error) {
|
|
s.source = src
|
|
return src, nil
|
|
}
|
|
|
|
func TestExcludedDirsPatchPreservesOmittedAndAllowsClearing(t *testing.T) {
|
|
id := uuid.New()
|
|
store := &exclusionsSourceStore{source: Source{ID: id, Name: "Base", Type: SourceLocal, Status: "mounted", ExcludedDirs: []string{"Downloads"}}}
|
|
board := NewProgressBoard()
|
|
svc := &SourceService{store: store, board: board}
|
|
ctx := auth.WithPrincipal(context.Background(), auth.Principal{Role: auth.RoleAdmin})
|
|
_, err := svc.UpdateSource(ctx, id, SourceInput{})
|
|
require.NoError(t, err)
|
|
require.Equal(t, []string{"Downloads"}, store.source.ExcludedDirs)
|
|
empty := []string{}
|
|
_, err = svc.UpdateSource(ctx, id, SourceInput{ExcludedDirs: &empty})
|
|
require.NoError(t, err)
|
|
require.Empty(t, store.source.ExcludedDirs)
|
|
board.start(id, false, time.Now())
|
|
dirs := []string{"Downloads_PumpEars"}
|
|
_, err = svc.UpdateSource(ctx, id, SourceInput{ExcludedDirs: &dirs})
|
|
require.Error(t, err)
|
|
require.Empty(t, store.source.ExcludedDirs, "a running scan must not race with exclusions changes")
|
|
}
|