data: move TestTreeMap to data package to allow reuse

This commit is contained in:
Michael Eischer
2025-11-22 22:13:54 +01:00
parent e1a5550a27
commit 17688c2313
3 changed files with 57 additions and 60 deletions

View File

@@ -12,7 +12,6 @@ import (
"github.com/restic/chunker" "github.com/restic/chunker"
"github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/test"
rtest "github.com/restic/restic/internal/test" rtest "github.com/restic/restic/internal/test"
) )
@@ -147,7 +146,7 @@ func TestCreateSnapshot(t testing.TB, repo restic.Repository, at time.Time, dept
} }
var treeID restic.ID var treeID restic.ID
test.OK(t, repo.WithBlobUploader(context.TODO(), func(ctx context.Context, uploader restic.BlobSaverWithAsync) error { rtest.OK(t, repo.WithBlobUploader(context.TODO(), func(ctx context.Context, uploader restic.BlobSaverWithAsync) error {
treeID = fs.saveTree(ctx, uploader, seed, depth) treeID = fs.saveTree(ctx, uploader, seed, depth)
return nil return nil
})) }))
@@ -199,3 +198,49 @@ func TestLoadAllSnapshots(ctx context.Context, repo restic.ListerLoaderUnpacked,
return snapshots, nil return snapshots, nil
} }
// TestTreeMap returns the trees from the map on LoadTree.
type TestTreeMap map[restic.ID][]byte
func (t TestTreeMap) LoadBlob(_ context.Context, tpe restic.BlobType, id restic.ID, _ []byte) ([]byte, error) {
if tpe != restic.TreeBlob {
return nil, fmt.Errorf("can only load trees")
}
tree, ok := t[id]
if !ok {
return nil, fmt.Errorf("tree not found")
}
return tree, nil
}
func (t TestTreeMap) Connections() uint {
return 2
}
// TestWritableTreeMap also support saving
type TestWritableTreeMap struct {
TestTreeMap
}
func (t TestWritableTreeMap) SaveBlob(_ context.Context, tpe restic.BlobType, buf []byte, id restic.ID, _ bool) (newID restic.ID, known bool, size int, err error) {
if tpe != restic.TreeBlob {
return restic.ID{}, false, 0, fmt.Errorf("can only save trees")
}
if id.IsNull() {
id = restic.Hash(buf)
}
_, ok := t.TestTreeMap[id]
if ok {
return id, false, 0, nil
}
t.TestTreeMap[id] = append([]byte{}, buf...)
return id, true, len(buf), nil
}
func (t TestWritableTreeMap) Dump(test testing.TB) {
for k, v := range t.TestTreeMap {
test.Logf("%v: %v", k, string(v))
}
}

View File

@@ -5,40 +5,11 @@ import (
"slices" "slices"
"testing" "testing"
"github.com/pkg/errors"
"github.com/restic/restic/internal/data" "github.com/restic/restic/internal/data"
"github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/test" "github.com/restic/restic/internal/test"
) )
// WritableTreeMap also support saving
type WritableTreeMap struct {
TreeMap
}
func (t WritableTreeMap) SaveBlob(_ context.Context, tpe restic.BlobType, buf []byte, id restic.ID, _ bool) (newID restic.ID, known bool, size int, err error) {
if tpe != restic.TreeBlob {
return restic.ID{}, false, 0, errors.New("can only save trees")
}
if id.IsNull() {
id = restic.Hash(buf)
}
_, ok := t.TreeMap[id]
if ok {
return id, false, 0, nil
}
t.TreeMap[id] = append([]byte{}, buf...)
return id, true, len(buf), nil
}
func (t WritableTreeMap) Dump(test testing.TB) {
for k, v := range t.TreeMap {
test.Logf("%v: %v", k, string(v))
}
}
type checkRewriteFunc func(t testing.TB) (rewriter *TreeRewriter, final func(testing.TB)) type checkRewriteFunc func(t testing.TB) (rewriter *TreeRewriter, final func(testing.TB))
// checkRewriteItemOrder ensures that the order of the 'path' arguments is the one passed in as 'want'. // checkRewriteItemOrder ensures that the order of the 'path' arguments is the one passed in as 'want'.
@@ -280,7 +251,7 @@ func TestRewriter(t *testing.T) {
test.newTree = test.tree test.newTree = test.tree
} }
expRepo, expRoot := BuildTreeMap(test.newTree) expRepo, expRoot := BuildTreeMap(test.newTree)
modrepo := WritableTreeMap{repo} modrepo := data.TestWritableTreeMap{TestTreeMap: repo}
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancel(context.TODO())
defer cancel() defer cancel()
@@ -298,7 +269,7 @@ func TestRewriter(t *testing.T) {
t.Log("Got") t.Log("Got")
modrepo.Dump(t) modrepo.Dump(t)
t.Log("Expected") t.Log("Expected")
WritableTreeMap{expRepo}.Dump(t) data.TestWritableTreeMap{TestTreeMap: expRepo}.Dump(t)
} }
}) })
} }
@@ -321,7 +292,7 @@ func TestSnapshotSizeQuery(t *testing.T) {
t.Run("", func(t *testing.T) { t.Run("", func(t *testing.T) {
repo, root := BuildTreeMap(tree) repo, root := BuildTreeMap(tree)
expRepo, expRoot := BuildTreeMap(newTree) expRepo, expRoot := BuildTreeMap(newTree)
modrepo := WritableTreeMap{repo} modrepo := data.TestWritableTreeMap{TestTreeMap: repo}
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancel(context.TODO())
defer cancel() defer cancel()
@@ -352,17 +323,17 @@ func TestSnapshotSizeQuery(t *testing.T) {
t.Log("Got") t.Log("Got")
modrepo.Dump(t) modrepo.Dump(t)
t.Log("Expected") t.Log("Expected")
WritableTreeMap{expRepo}.Dump(t) data.TestWritableTreeMap{TestTreeMap: expRepo}.Dump(t)
} }
}) })
} }
func TestRewriterFailOnUnknownFields(t *testing.T) { func TestRewriterFailOnUnknownFields(t *testing.T) {
tm := WritableTreeMap{TreeMap{}} tm := data.TestWritableTreeMap{TestTreeMap: data.TestTreeMap{}}
node := []byte(`{"nodes":[{"name":"subfile","type":"file","mtime":"0001-01-01T00:00:00Z","atime":"0001-01-01T00:00:00Z","ctime":"0001-01-01T00:00:00Z","uid":0,"gid":0,"content":null,"unknown_field":42}]}`) node := []byte(`{"nodes":[{"name":"subfile","type":"file","mtime":"0001-01-01T00:00:00Z","atime":"0001-01-01T00:00:00Z","ctime":"0001-01-01T00:00:00Z","uid":0,"gid":0,"content":null,"unknown_field":42}]}`)
id := restic.Hash(node) id := restic.Hash(node)
tm.TreeMap[id] = node tm.TestTreeMap[id] = node
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancel(context.TODO())
defer cancel() defer cancel()
@@ -393,7 +364,7 @@ func TestRewriterFailOnUnknownFields(t *testing.T) {
} }
func TestRewriterTreeLoadError(t *testing.T) { func TestRewriterTreeLoadError(t *testing.T) {
tm := WritableTreeMap{TreeMap{}} tm := data.TestWritableTreeMap{TestTreeMap: data.TestTreeMap{}}
id := restic.NewRandomID() id := restic.NewRandomID()
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancel(context.TODO())

View File

@@ -6,7 +6,6 @@ import (
"sort" "sort"
"testing" "testing"
"github.com/pkg/errors"
"github.com/restic/restic/internal/data" "github.com/restic/restic/internal/data"
"github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/restic"
rtest "github.com/restic/restic/internal/test" rtest "github.com/restic/restic/internal/test"
@@ -20,13 +19,13 @@ type TestFile struct {
Size uint64 Size uint64
} }
func BuildTreeMap(tree TestTree) (m TreeMap, root restic.ID) { func BuildTreeMap(tree TestTree) (m data.TestTreeMap, root restic.ID) {
m = TreeMap{} m = data.TestTreeMap{}
id := buildTreeMap(tree, m) id := buildTreeMap(tree, m)
return m, id return m, id
} }
func buildTreeMap(tree TestTree, m TreeMap) restic.ID { func buildTreeMap(tree TestTree, m data.TestTreeMap) restic.ID {
tb := data.NewTreeJSONBuilder() tb := data.NewTreeJSONBuilder()
var names []string var names []string
for name := range tree { for name := range tree {
@@ -75,24 +74,6 @@ func buildTreeMap(tree TestTree, m TreeMap) restic.ID {
return id return id
} }
// TreeMap returns the trees from the map on LoadTree.
type TreeMap map[restic.ID][]byte
func (t TreeMap) LoadBlob(_ context.Context, tpe restic.BlobType, id restic.ID, _ []byte) ([]byte, error) {
if tpe != restic.TreeBlob {
return nil, errors.New("can only load trees")
}
tree, ok := t[id]
if !ok {
return nil, errors.New("tree not found")
}
return tree, nil
}
func (t TreeMap) Connections() uint {
return 2
}
// checkFunc returns a function suitable for walking the tree to check // checkFunc returns a function suitable for walking the tree to check
// something, and a function which will check the final result. // something, and a function which will check the final result.
type checkFunc func(t testing.TB) (walker WalkFunc, leaveDir func(path string) error, final func(testing.TB, error)) type checkFunc func(t testing.TB) (walker WalkFunc, leaveDir func(path string) error, final func(testing.TB, error))