Add storage backends and safety checks
This commit is contained in:
133
internal/storage/path_test.go
Normal file
133
internal/storage/path_test.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidatePath(t *testing.T) {
|
||||
valid := []string{
|
||||
"report.md",
|
||||
"daily/report.md",
|
||||
"a-b_1.2/report.html",
|
||||
}
|
||||
for _, path := range valid {
|
||||
t.Run("valid "+path, func(t *testing.T) {
|
||||
if err := ValidatePath(path); err != nil {
|
||||
t.Fatalf("ValidatePath(%q) error = %v", path, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
invalid := []string{
|
||||
"",
|
||||
"/absolute",
|
||||
"../outside",
|
||||
"nested/../outside",
|
||||
"nested/./file",
|
||||
"nested//file",
|
||||
`nested\file`,
|
||||
}
|
||||
for _, path := range invalid {
|
||||
t.Run("invalid "+path, func(t *testing.T) {
|
||||
err := ValidatePath(path)
|
||||
if !IsInvalidPath(err) {
|
||||
t.Fatalf("ValidatePath(%q) error = %v, want invalid path", path, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidatePrefixAllowsRoot(t *testing.T) {
|
||||
if err := ValidatePrefix(""); err != nil {
|
||||
t.Fatalf("ValidatePrefix(\"\") error = %v", err)
|
||||
}
|
||||
if err := ValidatePrefix("a/.."); !IsInvalidPath(err) {
|
||||
t.Fatalf("ValidatePrefix traversal error = %v, want invalid path", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListSortsEntries(t *testing.T) {
|
||||
backend := walkBackend{
|
||||
entries: []Entry{
|
||||
{Path: "z.txt", Type: EntryTypeFile},
|
||||
{Path: "a.txt", Type: EntryTypeFile},
|
||||
},
|
||||
}
|
||||
|
||||
entries, err := List(context.Background(), backend, "", WalkOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("List() error = %v", err)
|
||||
}
|
||||
if got, want := []string{entries[0].Path, entries[1].Path}, []string{"a.txt", "z.txt"}; got[0] != want[0] || got[1] != want[1] {
|
||||
t.Fatalf("paths = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTypedErrorPredicates(t *testing.T) {
|
||||
err := NewError(OpReadFile, "test", "missing", ErrNotFound, errors.New("missing"))
|
||||
if !IsNotFound(err) {
|
||||
t.Fatalf("IsNotFound(%v) = false, want true", err)
|
||||
}
|
||||
if IsInvalidPath(err) {
|
||||
t.Fatalf("IsInvalidPath(%v) = true, want false", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistry(t *testing.T) {
|
||||
registry := NewRegistry()
|
||||
if err := registry.Register("test", func(context.Context, OpenConfig) (Backend, error) {
|
||||
return walkBackend{}, nil
|
||||
}); err != nil {
|
||||
t.Fatalf("Register() error = %v", err)
|
||||
}
|
||||
if _, err := registry.Open(context.Background(), "test", nil); err != nil {
|
||||
t.Fatalf("Open() error = %v", err)
|
||||
}
|
||||
if _, err := registry.Open(context.Background(), "missing", nil); !IsUnsupported(err) {
|
||||
t.Fatalf("Open() error = %v, want unsupported", err)
|
||||
}
|
||||
}
|
||||
|
||||
type walkBackend struct {
|
||||
entries []Entry
|
||||
}
|
||||
|
||||
func (b walkBackend) ReadFile(context.Context, string) ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (b walkBackend) OpenReader(context.Context, string) (io.ReadCloser, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (b walkBackend) WriteFile(context.Context, string, []byte, WriteOptions) (Entry, error) {
|
||||
return Entry{}, nil
|
||||
}
|
||||
|
||||
func (b walkBackend) WriteFrom(context.Context, string, io.Reader, WriteOptions) (Entry, error) {
|
||||
return Entry{}, nil
|
||||
}
|
||||
|
||||
func (b walkBackend) Stat(context.Context, string) (Entry, error) {
|
||||
return Entry{}, nil
|
||||
}
|
||||
|
||||
func (b walkBackend) Walk(_ context.Context, _ string, _ WalkOptions, fn WalkFunc) error {
|
||||
for _, entry := range b.entries {
|
||||
if err := fn(entry); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b walkBackend) HasAny(context.Context, string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (b walkBackend) DeleteManagedBundle(context.Context, string, []string, DeleteOptions) error {
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user