List the files under a path by path, not by string prefix (closes #223)
check / check (push) Successful in 12m16s
check / check (push) Successful in 12m16s
FileRepository.ListByPrefix matched with SQL LIKE: a plain string prefix that ignores ASCII case and treats _ and % as wildcards. Restoring /home/u/doc also restored doc2, DOC and doc.txt.bak, and a backup counted the files of a longer sibling path as deleted. It is now ListUnderPath, which returns the file at the path and every file whose path starts with the path plus a slash, compared exactly. A trailing slash is ignored, so "/" still lists every file. Three tests relied on string-prefix matching and now name a full path or call ListAll. ListIDsWithChunksNotInUploadedBlobs keeps its LIKE: it only adds file IDs the scan never looks up. Model: opus-5-5
This commit was merged in pull request #250.
This commit is contained in:
@@ -5,10 +5,12 @@ import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"os"
|
||||
"slices"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"sneak.berlin/go/vaultik/internal/database"
|
||||
"sneak.berlin/go/vaultik/internal/types"
|
||||
)
|
||||
|
||||
// errTestRollback is the sentinel returned from transaction bodies to
|
||||
@@ -134,6 +136,82 @@ func TestFileRepositoryListDelete(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileRepositoryListUnderPath(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db, cleanup := setupTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
ctx := context.Background()
|
||||
repo := database.NewFileRepository(db)
|
||||
|
||||
const (
|
||||
docDir = "/home/u/doc"
|
||||
docFile = "/home/u/doc/a.txt"
|
||||
)
|
||||
|
||||
// In path order, so the root case can expect all of them as listed.
|
||||
paths := []string{
|
||||
"/home/u/50%/x.txt",
|
||||
"/home/u/50percent/y.txt",
|
||||
"/home/u/DOC/c.txt",
|
||||
"/home/u/a_b/x.txt",
|
||||
"/home/u/axb/y.txt",
|
||||
docDir,
|
||||
"/home/u/doc.txt.bak",
|
||||
docFile,
|
||||
"/home/u/doc/sub/b.txt",
|
||||
"/home/u/doc2/b.txt",
|
||||
}
|
||||
|
||||
for _, path := range paths {
|
||||
err := repo.Create(ctx, nil, &database.File{
|
||||
Path: types.FilePath(path),
|
||||
MTime: time.Now().Truncate(time.Second),
|
||||
Mode: 0644,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create %s: %v", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
docTree := []string{docDir, docFile, "/home/u/doc/sub/b.txt"}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
path string
|
||||
want []string
|
||||
}{
|
||||
{"directory", docDir, docTree},
|
||||
{"directory with trailing slash", docDir + "/", docTree},
|
||||
{"directory differing only in case", "/home/u/DOC",
|
||||
[]string{"/home/u/DOC/c.txt"}},
|
||||
{"file", docFile, []string{docFile}},
|
||||
{"underscore is literal", "/home/u/a_b",
|
||||
[]string{"/home/u/a_b/x.txt"}},
|
||||
{"percent is literal", "/home/u/50%",
|
||||
[]string{"/home/u/50%/x.txt"}},
|
||||
{"root", "/", paths},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
files, err := repo.ListUnderPath(ctx, tt.path)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: failed to list files: %v", tt.name, err)
|
||||
}
|
||||
|
||||
got := make([]string, 0, len(files))
|
||||
for _, f := range files {
|
||||
got = append(got, f.Path.String())
|
||||
}
|
||||
|
||||
if !slices.Equal(got, tt.want) {
|
||||
t.Errorf("%s: listing %q got %q, want %q",
|
||||
tt.name, tt.path, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileRepositorySymlink(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user