package storage_test import ( "context" "errors" "io/fs" "os" "path/filepath" "strings" "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) } } // TestFileStorerPutMissingDestination checks that a write fails when the // destination directory has gone, even after earlier writes to it // succeeded, and that it does not create the directory again. func TestFileStorerPutMissingDestination(t *testing.T) { t.Parallel() ctx := context.Background() base := filepath.Join(t.TempDir(), "usbstick") err := os.Mkdir(base, 0o750) if err != nil { t.Fatalf("Mkdir: %v", err) } s, err := storage.NewFileStorer(base) if err != nil { t.Fatalf("NewFileStorer: %v", err) } err = s.Put(ctx, "blobs/aa/bb/first", strings.NewReader("first")) if err != nil { t.Fatalf("first Put: %v", err) } err = os.Rename(base, base+"-unplugged") if err != nil { t.Fatalf("Rename: %v", err) } err = s.Put(ctx, "blobs/aa/bb/second", strings.NewReader("second")) if !errors.Is(err, fs.ErrNotExist) { t.Errorf("Put = %v, want a not-exist error", err) } _, err = os.Stat(base) if !errors.Is(err, fs.ErrNotExist) { t.Errorf("Put created the destination directory again (Stat = %v)", err) } }