2
2
mirror of https://github.com/octoleo/restic.git synced 2024-12-12 14:17:57 +00:00
restic/internal/backend/dryrun/dry_backend_test.go
2024-05-18 21:38:31 +02:00

120 lines
3.3 KiB
Go

package dryrun_test
import (
"context"
"fmt"
"io"
"sort"
"strings"
"testing"
"github.com/restic/restic/internal/backend"
"github.com/restic/restic/internal/backend/dryrun"
"github.com/restic/restic/internal/backend/mem"
)
// make sure that Backend implements backend.Backend
var _ backend.Backend = &dryrun.Backend{}
func newBackends() (*dryrun.Backend, backend.Backend) {
m := mem.New()
return dryrun.New(m), m
}
func TestDry(t *testing.T) {
ctx := context.TODO()
d, m := newBackends()
// Since the dry backend is a mostly write-only overlay, the standard backend test suite
// won't pass. Instead, perform a series of operations over the backend, testing the state
// at each step.
steps := []struct {
be backend.Backend
op string
fname string
content string
wantErr string
}{
{d, "delete", "", "", ""},
{d, "stat", "a", "", "not found"},
{d, "list", "", "", ""},
{m, "save", "a", "baz", ""}, // save a directly to the mem backend
{d, "save", "b", "foob", ""}, // b is not saved
{d, "save", "b", "xxx", ""}, // no error as b is not saved
{d, "stat", "a", "a 3", ""},
{d, "load", "a", "baz", ""},
{d, "load", "b", "", "not found"},
{d, "list", "", "a", ""},
{d, "remove", "c", "", ""},
{d, "stat", "b", "", "not found"},
{d, "list", "", "a", ""},
{d, "remove", "a", "", ""}, // a is in fact not removed
{d, "list", "", "a", ""},
{m, "remove", "a", "", ""}, // remove a from the mem backend
{d, "list", "", "", ""},
{d, "close", "", "", ""},
{d, "close", "", "", ""},
}
for i, step := range steps {
var err error
handle := backend.Handle{Type: backend.PackFile, Name: step.fname}
switch step.op {
case "save":
err = step.be.Save(ctx, handle, backend.NewByteReader([]byte(step.content), step.be.Hasher()))
case "list":
fileList := []string{}
err = step.be.List(ctx, backend.PackFile, func(fi backend.FileInfo) error {
fileList = append(fileList, fi.Name)
return nil
})
sort.Strings(fileList)
files := strings.Join(fileList, " ")
if files != step.content {
t.Errorf("%d. List = %q, want %q", i, files, step.content)
}
case "delete":
err = step.be.Delete(ctx)
case "remove":
err = step.be.Remove(ctx, handle)
case "stat":
var fi backend.FileInfo
fi, err = step.be.Stat(ctx, handle)
if err == nil {
fis := fmt.Sprintf("%s %d", fi.Name, fi.Size)
if fis != step.content {
t.Errorf("%d. Stat = %q, want %q", i, fis, step.content)
}
}
case "load":
data := ""
err = step.be.Load(ctx, handle, 0, 0, func(rd io.Reader) error {
buf, err := io.ReadAll(rd)
data = string(buf)
return err
})
if data != step.content {
t.Errorf("%d. Load = %q, want %q", i, data, step.content)
}
case "close":
err = step.be.Close()
default:
t.Fatalf("%d. unknown step operation %q", i, step.op)
}
if step.wantErr != "" {
if err == nil {
t.Errorf("%d. %s error = nil, want %q", i, step.op, step.wantErr)
} else if !strings.Contains(err.Error(), step.wantErr) {
t.Errorf("%d. %s error = %q, doesn't contain %q", i, step.op, err, step.wantErr)
} else if step.wantErr == "not found" && !step.be.IsNotExist(err) {
t.Errorf("%d. IsNotExist(%s error) = false, want true", i, step.op)
}
} else if err != nil {
t.Errorf("%d. %s error = %q, want nil", i, step.op, err)
}
}
}