2
2
mirror of https://github.com/octoleo/restic.git synced 2024-12-23 11:28:54 +00:00
restic/internal/backend/dryrun/dry_backend_test.go
Michael Eischer 9aa2eff384 Add plumbing to calculate backend specific file hash for upload
This enables the backends to request the calculation of a
backend-specific hash. For the currently supported backends this will
always be MD5. The hash calculation happens as early as possible, for
pack files this is during assembly of the pack file. That way the hash
would even capture corruptions of the temporary pack file on disk.
2021-08-04 22:17:46 +02:00

138 lines
3.8 KiB
Go

package dryrun_test
import (
"context"
"fmt"
"io"
"io/ioutil"
"sort"
"strings"
"testing"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/backend/dryrun"
"github.com/restic/restic/internal/backend/mem"
)
// make sure that Backend implements backend.Backend
var _ restic.Backend = &dryrun.Backend{}
func newBackends() (*dryrun.Backend, restic.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 restic.Backend
op string
fname string
content string
wantErr string
}{
{d, "loc", "", "DRY:RAM", ""},
{d, "delete", "", "", ""},
{d, "stat", "a", "", "not found"},
{d, "list", "", "", ""},
{d, "save", "", "", "invalid"},
{d, "test", "a", "", ""},
{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, "test", "a", "1", ""},
{d, "test", "b", "", ""},
{d, "stat", "", "", "invalid"},
{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
var boolRes bool
handle := restic.Handle{Type: restic.PackFile, Name: step.fname}
switch step.op {
case "save":
err = step.be.Save(ctx, handle, restic.NewByteReader([]byte(step.content), step.be.Hasher()))
case "test":
boolRes, err = step.be.Test(ctx, handle)
if boolRes != (step.content != "") {
t.Errorf("%d. Test(%q) = %v, want %v", i, step.fname, boolRes, step.content != "")
}
case "list":
fileList := []string{}
err = step.be.List(ctx, restic.PackFile, func(fi restic.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 "loc":
loc := step.be.Location()
if loc != step.content {
t.Errorf("%d. Location = %q, want %q", i, loc, step.content)
}
case "delete":
err = step.be.Delete(ctx)
case "remove":
err = step.be.Remove(ctx, handle)
case "stat":
var fi restic.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, 100, 0, func(rd io.Reader) error {
buf, err := ioutil.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)
}
}
}