move Backend interface to backend package

This commit is contained in:
Michael Eischer
2023-10-01 11:40:12 +02:00
parent ceb0774af1
commit 1b8a67fe76
105 changed files with 822 additions and 775 deletions
+7 -6
View File
@@ -6,22 +6,23 @@ import (
"io"
"testing"
"github.com/restic/restic/internal/backend"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/test"
)
func saveRandomFile(t testing.TB, be restic.Backend, length int) ([]byte, restic.Handle) {
func saveRandomFile(t testing.TB, be backend.Backend, length int) ([]byte, backend.Handle) {
data := test.Random(23, length)
id := restic.Hash(data)
handle := restic.Handle{Type: restic.PackFile, Name: id.String()}
err := be.Save(context.TODO(), handle, restic.NewByteReader(data, be.Hasher()))
handle := backend.Handle{Type: backend.PackFile, Name: id.String()}
err := be.Save(context.TODO(), handle, backend.NewByteReader(data, be.Hasher()))
if err != nil {
t.Fatalf("Save() error: %+v", err)
}
return data, handle
}
func remove(t testing.TB, be restic.Backend, h restic.Handle) {
func remove(t testing.TB, be backend.Backend, h backend.Handle) {
if err := be.Remove(context.TODO(), h); err != nil {
t.Fatalf("Remove() returned error: %v", err)
}
@@ -146,9 +147,9 @@ func (s *Suite[C]) BenchmarkSave(t *testing.B) {
length := 1<<24 + 2123
data := test.Random(23, length)
id := restic.Hash(data)
handle := restic.Handle{Type: restic.PackFile, Name: id.String()}
handle := backend.Handle{Type: backend.PackFile, Name: id.String()}
rd := restic.NewByteReader(data, be.Hasher())
rd := backend.NewByteReader(data, be.Hasher())
t.SetBytes(int64(length))
t.ResetTimer()
+1 -1
View File
@@ -17,7 +17,7 @@
//
// func newTestSuite(t testing.TB) *test.Suite {
// return &test.Suite{
// Create: func(cfg interface{}) (restic.Backend, error) {
// Create: func(cfg interface{}) (backend.Backend, error) {
// [...]
// },
// [...]
+6 -7
View File
@@ -11,7 +11,6 @@ import (
"github.com/restic/restic/internal/backend"
"github.com/restic/restic/internal/backend/location"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/test"
)
@@ -35,7 +34,7 @@ type Suite[C any] struct {
WaitForDelayedRemoval time.Duration
// ErrorHandler allows ignoring certain errors.
ErrorHandler func(testing.TB, restic.Backend, error) error
ErrorHandler func(testing.TB, backend.Backend, error) error
}
// RunTests executes all defined tests as subtests of t.
@@ -156,7 +155,7 @@ func (s *Suite[C]) RunBenchmarks(b *testing.B) {
s.cleanup(b)
}
func (s *Suite[C]) createOrError() (restic.Backend, error) {
func (s *Suite[C]) createOrError() (backend.Backend, error) {
tr, err := backend.Transport(backend.TransportOptions{})
if err != nil {
return nil, fmt.Errorf("cannot create transport for tests: %v", err)
@@ -167,7 +166,7 @@ func (s *Suite[C]) createOrError() (restic.Backend, error) {
return nil, err
}
_, err = be.Stat(context.TODO(), restic.Handle{Type: restic.ConfigFile})
_, err = be.Stat(context.TODO(), backend.Handle{Type: backend.ConfigFile})
if err != nil && !be.IsNotExist(err) {
return nil, err
}
@@ -179,7 +178,7 @@ func (s *Suite[C]) createOrError() (restic.Backend, error) {
return be, nil
}
func (s *Suite[C]) create(t testing.TB) restic.Backend {
func (s *Suite[C]) create(t testing.TB) backend.Backend {
be, err := s.createOrError()
if err != nil {
t.Fatal(err)
@@ -187,7 +186,7 @@ func (s *Suite[C]) create(t testing.TB) restic.Backend {
return be
}
func (s *Suite[C]) open(t testing.TB) restic.Backend {
func (s *Suite[C]) open(t testing.TB) backend.Backend {
tr, err := backend.Transport(backend.TransportOptions{})
if err != nil {
t.Fatalf("cannot create transport for tests: %v", err)
@@ -208,7 +207,7 @@ func (s *Suite[C]) cleanup(t testing.TB) {
s.close(t, be)
}
func (s *Suite[C]) close(t testing.TB, be restic.Backend) {
func (s *Suite[C]) close(t testing.TB, be backend.Backend) {
err := be.Close()
if err != nil {
t.Fatal(err)
+50 -50
View File
@@ -27,7 +27,7 @@ func seedRand(t testing.TB) {
t.Logf("rand initialized with seed %d", seed)
}
func beTest(ctx context.Context, be restic.Backend, h restic.Handle) (bool, error) {
func beTest(ctx context.Context, be backend.Backend, h backend.Handle) (bool, error) {
_, err := be.Stat(ctx, h)
if err != nil && be.IsNotExist(err) {
return false, nil
@@ -49,7 +49,7 @@ func (s *Suite[C]) TestCreateWithConfig(t *testing.T) {
defer s.close(t, b)
// remove a config if present
cfgHandle := restic.Handle{Type: restic.ConfigFile}
cfgHandle := backend.Handle{Type: backend.ConfigFile}
cfgPresent, err := beTest(context.TODO(), b, cfgHandle)
if err != nil {
t.Fatalf("unable to test for config: %+v", err)
@@ -60,7 +60,7 @@ func (s *Suite[C]) TestCreateWithConfig(t *testing.T) {
}
// save a config
store(t, b, restic.ConfigFile, []byte("test config"))
store(t, b, backend.ConfigFile, []byte("test config"))
// now create the backend again, this must fail
_, err = s.createOrError()
@@ -69,7 +69,7 @@ func (s *Suite[C]) TestCreateWithConfig(t *testing.T) {
}
// remove config
err = b.Remove(context.TODO(), restic.Handle{Type: restic.ConfigFile, Name: ""})
err = b.Remove(context.TODO(), backend.Handle{Type: backend.ConfigFile, Name: ""})
if err != nil {
t.Fatalf("unexpected error removing config: %+v", err)
}
@@ -94,13 +94,13 @@ func (s *Suite[C]) TestConfig(t *testing.T) {
var testString = "Config"
// create config and read it back
_, err := backend.LoadAll(context.TODO(), nil, b, restic.Handle{Type: restic.ConfigFile})
_, err := backend.LoadAll(context.TODO(), nil, b, backend.Handle{Type: backend.ConfigFile})
if err == nil {
t.Fatalf("did not get expected error for non-existing config")
}
test.Assert(t, b.IsNotExist(err), "IsNotExist() did not recognize error from LoadAll(): %v", err)
err = b.Save(context.TODO(), restic.Handle{Type: restic.ConfigFile}, restic.NewByteReader([]byte(testString), b.Hasher()))
err = b.Save(context.TODO(), backend.Handle{Type: backend.ConfigFile}, backend.NewByteReader([]byte(testString), b.Hasher()))
if err != nil {
t.Fatalf("Save() error: %+v", err)
}
@@ -108,7 +108,7 @@ func (s *Suite[C]) TestConfig(t *testing.T) {
// try accessing the config with different names, should all return the
// same config
for _, name := range []string{"", "foo", "bar", "0000000000000000000000000000000000000000000000000000000000000000"} {
h := restic.Handle{Type: restic.ConfigFile, Name: name}
h := backend.Handle{Type: backend.ConfigFile, Name: name}
buf, err := backend.LoadAll(context.TODO(), nil, b, h)
if err != nil {
t.Fatalf("unable to read config with name %q: %+v", name, err)
@@ -120,7 +120,7 @@ func (s *Suite[C]) TestConfig(t *testing.T) {
}
// remove the config
remove(t, b, restic.Handle{Type: restic.ConfigFile})
remove(t, b, backend.Handle{Type: backend.ConfigFile})
}
// TestLoad tests the backend's Load function.
@@ -130,7 +130,7 @@ func (s *Suite[C]) TestLoad(t *testing.T) {
b := s.open(t)
defer s.close(t, b)
err := testLoad(b, restic.Handle{Type: restic.PackFile, Name: "foobar"})
err := testLoad(b, backend.Handle{Type: backend.PackFile, Name: "foobar"})
if err == nil {
t.Fatalf("Load() did not return an error for non-existing blob")
}
@@ -141,8 +141,8 @@ func (s *Suite[C]) TestLoad(t *testing.T) {
data := test.Random(23, length)
id := restic.Hash(data)
handle := restic.Handle{Type: restic.PackFile, Name: id.String()}
err = b.Save(context.TODO(), handle, restic.NewByteReader(data, b.Hasher()))
handle := backend.Handle{Type: backend.PackFile, Name: id.String()}
err = b.Save(context.TODO(), handle, backend.NewByteReader(data, b.Hasher()))
if err != nil {
t.Fatalf("Save() error: %+v", err)
}
@@ -243,7 +243,7 @@ func (s *Suite[C]) TestList(t *testing.T) {
// Check that the backend is empty to start with
var found []string
err := b.List(context.TODO(), restic.PackFile, func(fi restic.FileInfo) error {
err := b.List(context.TODO(), backend.PackFile, func(fi backend.FileInfo) error {
found = append(found, fi.Name)
return nil
})
@@ -259,8 +259,8 @@ func (s *Suite[C]) TestList(t *testing.T) {
for i := 0; i < numTestFiles; i++ {
data := test.Random(rand.Int(), rand.Intn(100)+55)
id := restic.Hash(data)
h := restic.Handle{Type: restic.PackFile, Name: id.String()}
err := b.Save(context.TODO(), h, restic.NewByteReader(data, b.Hasher()))
h := backend.Handle{Type: backend.PackFile, Name: id.String()}
err := b.Save(context.TODO(), h, backend.NewByteReader(data, b.Hasher()))
if err != nil {
t.Fatal(err)
}
@@ -284,7 +284,7 @@ func (s *Suite[C]) TestList(t *testing.T) {
s.SetListMaxItems(test.maxItems)
}
err := b.List(context.TODO(), restic.PackFile, func(fi restic.FileInfo) error {
err := b.List(context.TODO(), backend.PackFile, func(fi backend.FileInfo) error {
id, err := restic.ParseID(fi.Name)
if err != nil {
t.Fatal(err)
@@ -320,9 +320,9 @@ func (s *Suite[C]) TestList(t *testing.T) {
}
t.Logf("remove %d files", numTestFiles)
handles := make([]restic.Handle, 0, len(list1))
handles := make([]backend.Handle, 0, len(list1))
for id := range list1 {
handles = append(handles, restic.Handle{Type: restic.PackFile, Name: id.String()})
handles = append(handles, backend.Handle{Type: backend.PackFile, Name: id.String()})
}
err = s.delayedRemove(t, b, handles...)
@@ -340,13 +340,13 @@ func (s *Suite[C]) TestListCancel(t *testing.T) {
b := s.open(t)
defer s.close(t, b)
testFiles := make([]restic.Handle, 0, numTestFiles)
testFiles := make([]backend.Handle, 0, numTestFiles)
for i := 0; i < numTestFiles; i++ {
data := []byte(fmt.Sprintf("random test blob %v", i))
id := restic.Hash(data)
h := restic.Handle{Type: restic.PackFile, Name: id.String()}
err := b.Save(context.TODO(), h, restic.NewByteReader(data, b.Hasher()))
h := backend.Handle{Type: backend.PackFile, Name: id.String()}
err := b.Save(context.TODO(), h, backend.NewByteReader(data, b.Hasher()))
if err != nil {
t.Fatal(err)
}
@@ -358,7 +358,7 @@ func (s *Suite[C]) TestListCancel(t *testing.T) {
cancel()
// pass in a cancelled context
err := b.List(ctx, restic.PackFile, func(fi restic.FileInfo) error {
err := b.List(ctx, backend.PackFile, func(fi backend.FileInfo) error {
t.Errorf("got FileInfo %v for cancelled context", fi)
return nil
})
@@ -373,7 +373,7 @@ func (s *Suite[C]) TestListCancel(t *testing.T) {
defer cancel()
i := 0
err := b.List(ctx, restic.PackFile, func(fi restic.FileInfo) error {
err := b.List(ctx, backend.PackFile, func(fi backend.FileInfo) error {
i++
// cancel the context on the first file
if i == 1 {
@@ -396,7 +396,7 @@ func (s *Suite[C]) TestListCancel(t *testing.T) {
defer cancel()
i := 0
err := b.List(ctx, restic.PackFile, func(fi restic.FileInfo) error {
err := b.List(ctx, backend.PackFile, func(fi backend.FileInfo) error {
// cancel the context at the last file
i++
if i == numTestFiles {
@@ -423,7 +423,7 @@ func (s *Suite[C]) TestListCancel(t *testing.T) {
i := 0
// pass in a context with a timeout
err := b.List(ctxTimeout, restic.PackFile, func(fi restic.FileInfo) error {
err := b.List(ctxTimeout, backend.PackFile, func(fi backend.FileInfo) error {
i++
// wait until the context is cancelled
@@ -494,11 +494,11 @@ func (s *Suite[C]) TestSave(t *testing.T) {
data := test.Random(23, length)
id = sha256.Sum256(data)
h := restic.Handle{
Type: restic.PackFile,
h := backend.Handle{
Type: backend.PackFile,
Name: id.String(),
}
err := b.Save(context.TODO(), h, restic.NewByteReader(data, b.Hasher()))
err := b.Save(context.TODO(), h, backend.NewByteReader(data, b.Hasher()))
test.OK(t, err)
buf, err := backend.LoadAll(context.TODO(), nil, b, h)
@@ -546,7 +546,7 @@ func (s *Suite[C]) TestSave(t *testing.T) {
t.Fatal(err)
}
h := restic.Handle{Type: restic.PackFile, Name: id.String()}
h := backend.Handle{Type: backend.PackFile, Name: id.String()}
// wrap the tempfile in an errorCloser, so we can detect if the backend
// closes the reader
@@ -585,7 +585,7 @@ func (s *Suite[C]) TestSave(t *testing.T) {
}
type incompleteByteReader struct {
restic.ByteReader
backend.ByteReader
}
func (r *incompleteByteReader) Length() int64 {
@@ -609,8 +609,8 @@ func (s *Suite[C]) TestSaveError(t *testing.T) {
copy(id[:], data)
// test that incomplete uploads fail
h := restic.Handle{Type: restic.PackFile, Name: id.String()}
err := b.Save(context.TODO(), h, &incompleteByteReader{ByteReader: *restic.NewByteReader(data, b.Hasher())})
h := backend.Handle{Type: backend.PackFile, Name: id.String()}
err := b.Save(context.TODO(), h, &incompleteByteReader{ByteReader: *backend.NewByteReader(data, b.Hasher())})
// try to delete possible leftovers
_ = s.delayedRemove(t, b, h)
if err == nil {
@@ -619,7 +619,7 @@ func (s *Suite[C]) TestSaveError(t *testing.T) {
}
type wrongByteReader struct {
restic.ByteReader
backend.ByteReader
}
func (b *wrongByteReader) Hash() []byte {
@@ -648,8 +648,8 @@ func (s *Suite[C]) TestSaveWrongHash(t *testing.T) {
copy(id[:], data)
// test that upload with hash mismatch fails
h := restic.Handle{Type: restic.PackFile, Name: id.String()}
err := b.Save(context.TODO(), h, &wrongByteReader{ByteReader: *restic.NewByteReader(data, b.Hasher())})
h := backend.Handle{Type: backend.PackFile, Name: id.String()}
err := b.Save(context.TODO(), h, &wrongByteReader{ByteReader: *backend.NewByteReader(data, b.Hasher())})
exists, err2 := beTest(context.TODO(), b, h)
if err2 != nil {
t.Fatal(err2)
@@ -674,23 +674,23 @@ var testStrings = []struct {
{"4e54d2c721cbdb730f01b10b62dec622962b36966ec685880effa63d71c808f2", "foo/../../baz"},
}
func store(t testing.TB, b restic.Backend, tpe restic.FileType, data []byte) restic.Handle {
func store(t testing.TB, b backend.Backend, tpe backend.FileType, data []byte) backend.Handle {
id := restic.Hash(data)
h := restic.Handle{Name: id.String(), Type: tpe}
err := b.Save(context.TODO(), h, restic.NewByteReader([]byte(data), b.Hasher()))
h := backend.Handle{Name: id.String(), Type: tpe}
err := b.Save(context.TODO(), h, backend.NewByteReader([]byte(data), b.Hasher()))
test.OK(t, err)
return h
}
// testLoad loads a blob (but discards its contents).
func testLoad(b restic.Backend, h restic.Handle) error {
func testLoad(b backend.Backend, h backend.Handle) error {
return b.Load(context.TODO(), h, 0, 0, func(rd io.Reader) (ierr error) {
_, ierr = io.Copy(io.Discard, rd)
return ierr
})
}
func (s *Suite[C]) delayedRemove(t testing.TB, be restic.Backend, handles ...restic.Handle) error {
func (s *Suite[C]) delayedRemove(t testing.TB, be backend.Backend, handles ...backend.Handle) error {
// Some backend (swift, I'm looking at you) may implement delayed
// removal of data. Let's wait a bit if this happens.
@@ -734,11 +734,11 @@ func (s *Suite[C]) delayedRemove(t testing.TB, be restic.Backend, handles ...res
return nil
}
func delayedList(t testing.TB, b restic.Backend, tpe restic.FileType, max int, maxwait time.Duration) restic.IDs {
func delayedList(t testing.TB, b backend.Backend, tpe backend.FileType, max int, maxwait time.Duration) restic.IDs {
list := restic.NewIDSet()
start := time.Now()
for i := 0; i < max; i++ {
err := b.List(context.TODO(), tpe, func(fi restic.FileInfo) error {
err := b.List(context.TODO(), tpe, func(fi backend.FileInfo) error {
id := restic.TestParseID(fi.Name)
list.Insert(id)
return nil
@@ -763,9 +763,9 @@ func (s *Suite[C]) TestBackend(t *testing.T) {
test.Assert(t, !b.IsNotExist(nil), "IsNotExist() recognized nil error")
for _, tpe := range []restic.FileType{
restic.PackFile, restic.KeyFile, restic.LockFile,
restic.SnapshotFile, restic.IndexFile,
for _, tpe := range []backend.FileType{
backend.PackFile, backend.KeyFile, backend.LockFile,
backend.SnapshotFile, backend.IndexFile,
} {
// detect non-existing files
for _, ts := range testStrings {
@@ -773,7 +773,7 @@ func (s *Suite[C]) TestBackend(t *testing.T) {
test.OK(t, err)
// test if blob is already in repository
h := restic.Handle{Type: tpe, Name: id.String()}
h := backend.Handle{Type: tpe, Name: id.String()}
ret, err := beTest(context.TODO(), b, h)
test.OK(t, err)
test.Assert(t, !ret, "blob was found to exist before creating")
@@ -799,7 +799,7 @@ func (s *Suite[C]) TestBackend(t *testing.T) {
store(t, b, tpe, []byte(ts.data))
// test Load()
h := restic.Handle{Type: tpe, Name: ts.id}
h := backend.Handle{Type: tpe, Name: ts.id}
buf, err := backend.LoadAll(context.TODO(), nil, b, h)
test.OK(t, err)
test.Equals(t, ts.data, string(buf))
@@ -823,7 +823,7 @@ func (s *Suite[C]) TestBackend(t *testing.T) {
// test adding the first file again
ts := testStrings[0]
h := restic.Handle{Type: tpe, Name: ts.id}
h := backend.Handle{Type: tpe, Name: ts.id}
// remove and recreate
err := s.delayedRemove(t, b, h)
@@ -835,7 +835,7 @@ func (s *Suite[C]) TestBackend(t *testing.T) {
test.Assert(t, !ok, "removed blob still present")
// create blob
err = b.Save(context.TODO(), h, restic.NewByteReader([]byte(ts.data), b.Hasher()))
err = b.Save(context.TODO(), h, backend.NewByteReader([]byte(ts.data), b.Hasher()))
test.OK(t, err)
// list items
@@ -859,12 +859,12 @@ func (s *Suite[C]) TestBackend(t *testing.T) {
t.Fatalf("lists aren't equal, want:\n %v\n got:\n%v\n", IDs, list)
}
var handles []restic.Handle
var handles []backend.Handle
for _, ts := range testStrings {
id, err := restic.ParseID(ts.id)
test.OK(t, err)
h := restic.Handle{Type: tpe, Name: id.String()}
h := backend.Handle{Type: tpe, Name: id.String()}
found, err := beTest(context.TODO(), b, h)
test.OK(t, err)