The file backend listed a destination directory that does not exist as an empty store. With the volume unplugged, snapshot list reported every local snapshot as missing from the store, snapshot remove said it had removed metadata it never reached, and prune dropped every local snapshot record. List and ListStream now fail when the destination directory is missing, so those commands take their existing path for a store that cannot be listed. A missing prefix under an existing directory is still an empty listing, and a first backup still creates the directory. Three tests listed a file:// destination nothing had created; they now create it. Model: opus-5-5
63 lines
1.4 KiB
Go
63 lines
1.4 KiB
Go
package storage_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io/fs"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"sneak.berlin/go/vaultik/internal/storage"
|
|
)
|
|
|
|
// newFileStorer builds a file:// backend rooted at a fresh temp directory.
|
|
//
|
|
//nolint:ireturn // conformance runs against the Storer interface by design
|
|
func newFileStorer(t *testing.T) storage.Storer {
|
|
t.Helper()
|
|
|
|
s, err := storage.NewFileStorer(t.TempDir())
|
|
if err != nil {
|
|
t.Fatalf("NewFileStorer: %v", err)
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
// TestFileStorer runs the shared Storer contract against the file:// backend.
|
|
func TestFileStorer(t *testing.T) {
|
|
t.Parallel()
|
|
runStorerConformance(t, newFileStorer)
|
|
}
|
|
|
|
// TestFileStorerListMissingDestination checks that List and ListStream
|
|
// fail when the destination directory does not exist, instead of
|
|
// reporting an empty store.
|
|
func TestFileStorerListMissingDestination(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
|
|
s, err := storage.NewFileStorer(filepath.Join(t.TempDir(), "unmounted"))
|
|
if err != nil {
|
|
t.Fatalf("NewFileStorer: %v", err)
|
|
}
|
|
|
|
keys, err := s.List(ctx, "metadata/")
|
|
if !errors.Is(err, fs.ErrNotExist) {
|
|
t.Errorf("List = %v, %v; want a not-exist error", keys, err)
|
|
}
|
|
|
|
var streamErr error
|
|
|
|
for object := range s.ListStream(ctx, "metadata/") {
|
|
if object.Err != nil {
|
|
streamErr = object.Err
|
|
}
|
|
}
|
|
|
|
if !errors.Is(streamErr, fs.ErrNotExist) {
|
|
t.Errorf("ListStream error = %v, want a not-exist error", streamErr)
|
|
}
|
|
}
|