restic/internal/archiver/tree_test.go

467 lines
12 KiB
Go
Raw Normal View History

2018-03-30 20:43:18 +00:00
package archiver
import (
"fmt"
2018-03-30 20:43:18 +00:00
"path/filepath"
"runtime"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/restic/restic/internal/fs"
rtest "github.com/restic/restic/internal/test"
2018-03-30 20:43:18 +00:00
)
// debug.Log requires Tree.String.
2024-08-27 09:26:52 +00:00
var _ fmt.Stringer = tree{}
2018-03-30 20:43:18 +00:00
func TestPathComponents(t *testing.T) {
var tests = []struct {
p string
c []string
virtual bool
rel bool
win bool
}{
{
p: "/foo/bar/baz",
c: []string{"foo", "bar", "baz"},
},
{
p: "/foo/bar/baz",
c: []string{"foo", "bar", "baz"},
rel: true,
},
{
p: "foo/bar/baz",
c: []string{"foo", "bar", "baz"},
},
{
p: "foo/bar/baz",
c: []string{"foo", "bar", "baz"},
rel: true,
},
{
p: "../foo/bar/baz",
c: []string{"foo", "bar", "baz"},
},
{
p: "../foo/bar/baz",
c: []string{"..", "foo", "bar", "baz"},
rel: true,
},
{
p: "c:/foo/bar/baz",
c: []string{"c", "foo", "bar", "baz"},
virtual: true,
rel: true,
win: true,
},
{
p: "c:/foo/../bar/baz",
c: []string{"c", "bar", "baz"},
virtual: true,
win: true,
},
{
p: `c:\foo\..\bar\baz`,
c: []string{"c", "bar", "baz"},
virtual: true,
win: true,
},
{
p: "c:/foo/../bar/baz",
c: []string{"c", "bar", "baz"},
virtual: true,
rel: true,
win: true,
},
{
p: `c:\foo\..\bar\baz`,
c: []string{"c", "bar", "baz"},
virtual: true,
rel: true,
win: true,
},
}
for _, test := range tests {
t.Run("", func(t *testing.T) {
if test.win && runtime.GOOS != "windows" {
t.Skip("skip test on unix")
}
c, v := pathComponents(fs.Local{}, filepath.FromSlash(test.p), test.rel)
if !cmp.Equal(test.c, c) {
t.Error(test.c, c)
}
if v != test.virtual {
t.Errorf("unexpected virtual prefix count returned, want %v, got %v", test.virtual, v)
}
})
}
}
func TestRootDirectory(t *testing.T) {
var tests = []struct {
target string
root string
unix bool
win bool
}{
{target: ".", root: "."},
{target: "foo/bar/baz", root: "."},
{target: "../foo/bar/baz", root: ".."},
{target: "..", root: ".."},
{target: "../../..", root: "../../.."},
{target: "/home/foo", root: "/", unix: true},
{target: "c:/home/foo", root: "c:/", win: true},
{target: `c:\home\foo`, root: `c:\`, win: true},
{target: "//host/share/foo", root: "//host/share/", win: true},
}
for _, test := range tests {
t.Run("", func(t *testing.T) {
if test.unix && runtime.GOOS == "windows" {
t.Skip("skip test on windows")
}
if test.win && runtime.GOOS != "windows" {
t.Skip("skip test on unix")
}
root := rootDirectory(fs.Local{}, filepath.FromSlash(test.target))
want := filepath.FromSlash(test.root)
if root != want {
t.Fatalf("wrong root directory, want %v, got %v", want, root)
}
})
}
}
func TestTree(t *testing.T) {
var tests = []struct {
targets []string
2018-06-20 20:54:47 +00:00
src TestDir
2024-08-27 09:26:52 +00:00
want tree
2018-03-30 20:43:18 +00:00
unix bool
win bool
mustError bool
}{
{
targets: []string{"foo"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Path: "foo", Root: "."},
2018-03-30 20:43:18 +00:00
}},
},
{
targets: []string{"foo", "bar", "baz"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Path: "foo", Root: "."},
"bar": {Path: "bar", Root: "."},
"baz": {Path: "baz", Root: "."},
2018-03-30 20:43:18 +00:00
}},
},
{
targets: []string{"foo/user1", "foo/user2", "foo/other"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Root: ".", FileInfoPath: "foo", Nodes: map[string]tree{
"user1": {Path: filepath.FromSlash("foo/user1")},
"user2": {Path: filepath.FromSlash("foo/user2")},
"other": {Path: filepath.FromSlash("foo/other")},
2018-03-30 20:43:18 +00:00
}},
}},
},
{
targets: []string{"foo/work/user1", "foo/work/user2"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Root: ".", FileInfoPath: "foo", Nodes: map[string]tree{
"work": {FileInfoPath: filepath.FromSlash("foo/work"), Nodes: map[string]tree{
"user1": {Path: filepath.FromSlash("foo/work/user1")},
"user2": {Path: filepath.FromSlash("foo/work/user2")},
2018-03-30 20:43:18 +00:00
}},
}},
}},
},
{
targets: []string{"foo/user1", "bar/user1", "foo/other"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Root: ".", FileInfoPath: "foo", Nodes: map[string]tree{
"user1": {Path: filepath.FromSlash("foo/user1")},
"other": {Path: filepath.FromSlash("foo/other")},
2018-03-30 20:43:18 +00:00
}},
2024-08-27 09:26:52 +00:00
"bar": {Root: ".", FileInfoPath: "bar", Nodes: map[string]tree{
"user1": {Path: filepath.FromSlash("bar/user1")},
2018-03-30 20:43:18 +00:00
}},
}},
},
{
targets: []string{"../work"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"work": {Root: "..", Path: filepath.FromSlash("../work")},
2018-03-30 20:43:18 +00:00
}},
},
{
targets: []string{"../work/other"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"work": {Root: "..", FileInfoPath: filepath.FromSlash("../work"), Nodes: map[string]tree{
"other": {Path: filepath.FromSlash("../work/other")},
2018-03-30 20:43:18 +00:00
}},
}},
},
{
targets: []string{"foo/user1", "../work/other", "foo/user2"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Root: ".", FileInfoPath: "foo", Nodes: map[string]tree{
"user1": {Path: filepath.FromSlash("foo/user1")},
"user2": {Path: filepath.FromSlash("foo/user2")},
2018-03-30 20:43:18 +00:00
}},
2024-08-27 09:26:52 +00:00
"work": {Root: "..", FileInfoPath: filepath.FromSlash("../work"), Nodes: map[string]tree{
"other": {Path: filepath.FromSlash("../work/other")},
2018-03-30 20:43:18 +00:00
}},
}},
},
{
targets: []string{"foo/user1", "../foo/other", "foo/user2"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Root: ".", FileInfoPath: "foo", Nodes: map[string]tree{
"user1": {Path: filepath.FromSlash("foo/user1")},
"user2": {Path: filepath.FromSlash("foo/user2")},
2018-03-30 20:43:18 +00:00
}},
2024-08-27 09:26:52 +00:00
"foo-1": {Root: "..", FileInfoPath: filepath.FromSlash("../foo"), Nodes: map[string]tree{
"other": {Path: filepath.FromSlash("../foo/other")},
2018-03-30 20:43:18 +00:00
}},
}},
},
{
2018-06-20 20:54:47 +00:00
src: TestDir{
"foo": TestDir{
"file": TestFile{Content: "file content"},
"work": TestFile{Content: "work file content"},
},
},
targets: []string{"foo", "foo/work"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {
2018-06-20 20:54:47 +00:00
Root: ".",
FileInfoPath: "foo",
2024-08-27 09:26:52 +00:00
Nodes: map[string]tree{
"file": {Path: filepath.FromSlash("foo/file")},
"work": {Path: filepath.FromSlash("foo/work")},
2018-06-20 20:54:47 +00:00
},
},
}},
},
{
src: TestDir{
"foo": TestDir{
"file": TestFile{Content: "file content"},
"work": TestDir{
"other": TestFile{Content: "other file content"},
},
},
},
targets: []string{"foo/work", "foo"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {
2018-06-20 20:54:47 +00:00
Root: ".",
FileInfoPath: "foo",
2024-08-27 09:26:52 +00:00
Nodes: map[string]tree{
"file": {Path: filepath.FromSlash("foo/file")},
"work": {Path: filepath.FromSlash("foo/work")},
2018-06-20 20:54:47 +00:00
},
},
}},
},
{
src: TestDir{
"foo": TestDir{
"work": TestDir{
"user1": TestFile{Content: "file content"},
"user2": TestFile{Content: "other file content"},
},
},
},
2018-03-30 20:43:18 +00:00
targets: []string{"foo/work", "foo/work/user2"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Root: ".", FileInfoPath: "foo", Nodes: map[string]tree{
"work": {
2018-06-20 20:54:47 +00:00
FileInfoPath: filepath.FromSlash("foo/work"),
2024-08-27 09:26:52 +00:00
Nodes: map[string]tree{
"user1": {Path: filepath.FromSlash("foo/work/user1")},
"user2": {Path: filepath.FromSlash("foo/work/user2")},
2018-06-20 20:54:47 +00:00
},
2018-03-30 20:43:18 +00:00
},
}},
}},
},
{
2018-06-20 20:54:47 +00:00
src: TestDir{
"foo": TestDir{
"work": TestDir{
"user1": TestFile{Content: "file content"},
"user2": TestFile{Content: "other file content"},
},
},
},
2018-03-30 20:43:18 +00:00
targets: []string{"foo/work/user2", "foo/work"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Root: ".", FileInfoPath: "foo", Nodes: map[string]tree{
"work": {FileInfoPath: filepath.FromSlash("foo/work"),
2024-08-27 09:26:52 +00:00
Nodes: map[string]tree{
"user1": {Path: filepath.FromSlash("foo/work/user1")},
"user2": {Path: filepath.FromSlash("foo/work/user2")},
2018-06-20 20:54:47 +00:00
},
2018-03-30 20:43:18 +00:00
},
}},
}},
},
{
2018-06-20 20:54:47 +00:00
src: TestDir{
"foo": TestDir{
"other": TestFile{Content: "file content"},
"work": TestDir{
"user2": TestDir{
"data": TestDir{
"secret": TestFile{Content: "secret file content"},
},
},
"user3": TestDir{
"important.txt": TestFile{Content: "important work"},
},
},
},
},
2018-03-30 20:43:18 +00:00
targets: []string{"foo/work/user2/data/secret", "foo"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Root: ".", FileInfoPath: "foo", Nodes: map[string]tree{
"other": {Path: filepath.FromSlash("foo/other")},
2024-08-27 09:26:52 +00:00
"work": {FileInfoPath: filepath.FromSlash("foo/work"), Nodes: map[string]tree{
"user2": {FileInfoPath: filepath.FromSlash("foo/work/user2"), Nodes: map[string]tree{
"data": {FileInfoPath: filepath.FromSlash("foo/work/user2/data"), Nodes: map[string]tree{
"secret": {
2018-06-20 20:54:47 +00:00
Path: filepath.FromSlash("foo/work/user2/data/secret"),
},
}},
}},
"user3": {Path: filepath.FromSlash("foo/work/user3")},
2018-06-20 20:54:47 +00:00
}},
}},
2018-03-30 20:43:18 +00:00
}},
},
{
2018-06-20 20:54:47 +00:00
src: TestDir{
"mnt": TestDir{
"driveA": TestDir{
"work": TestDir{
"driveB": TestDir{
"secret": TestFile{Content: "secret file content"},
},
"test1": TestDir{
"important.txt": TestFile{Content: "important work"},
},
},
"test2": TestDir{
"important.txt": TestFile{Content: "other important work"},
},
},
},
},
2018-03-30 20:43:18 +00:00
unix: true,
2018-06-20 20:54:47 +00:00
targets: []string{"mnt/driveA", "mnt/driveA/work/driveB"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"mnt": {Root: ".", FileInfoPath: filepath.FromSlash("mnt"), Nodes: map[string]tree{
"driveA": {FileInfoPath: filepath.FromSlash("mnt/driveA"), Nodes: map[string]tree{
"work": {FileInfoPath: filepath.FromSlash("mnt/driveA/work"), Nodes: map[string]tree{
"driveB": {
2018-06-20 20:54:47 +00:00
Path: filepath.FromSlash("mnt/driveA/work/driveB"),
},
"test1": {Path: filepath.FromSlash("mnt/driveA/work/test1")},
2018-06-20 20:54:47 +00:00
}},
"test2": {Path: filepath.FromSlash("mnt/driveA/test2")},
2018-06-20 20:54:47 +00:00
}},
2018-03-30 20:43:18 +00:00
}},
}},
},
{
targets: []string{"foo/work/user", "foo/work/user"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Root: ".", FileInfoPath: "foo", Nodes: map[string]tree{
"work": {FileInfoPath: filepath.FromSlash("foo/work"), Nodes: map[string]tree{
"user": {Path: filepath.FromSlash("foo/work/user")},
2018-03-30 20:43:18 +00:00
}},
}},
}},
},
{
targets: []string{"./foo/work/user", "foo/work/user"},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"foo": {Root: ".", FileInfoPath: "foo", Nodes: map[string]tree{
"work": {FileInfoPath: filepath.FromSlash("foo/work"), Nodes: map[string]tree{
"user": {Path: filepath.FromSlash("foo/work/user")},
2018-03-30 20:43:18 +00:00
}},
}},
}},
},
{
win: true,
targets: []string{`c:\users\foobar\temp`},
2024-08-27 09:26:52 +00:00
want: tree{Nodes: map[string]tree{
"c": {Root: `c:\`, FileInfoPath: `c:\`, Nodes: map[string]tree{
"users": {FileInfoPath: `c:\users`, Nodes: map[string]tree{
"foobar": {FileInfoPath: `c:\users\foobar`, Nodes: map[string]tree{
"temp": {Path: `c:\users\foobar\temp`},
2018-03-30 20:43:18 +00:00
}},
}},
}},
}},
},
{
targets: []string{"."},
mustError: true,
},
{
targets: []string{".."},
mustError: true,
},
{
targets: []string{"../.."},
mustError: true,
},
}
for _, test := range tests {
t.Run("", func(t *testing.T) {
if test.unix && runtime.GOOS == "windows" {
t.Skip("skip test on windows")
}
if test.win && runtime.GOOS != "windows" {
t.Skip("skip test on unix")
}
tempdir := rtest.TempDir(t)
2018-06-20 20:54:47 +00:00
TestCreateFiles(t, tempdir, test.src)
back := rtest.Chdir(t, tempdir)
2018-06-20 20:54:47 +00:00
defer back()
2024-08-27 09:26:52 +00:00
tree, err := newTree(fs.Local{}, test.targets)
2018-03-30 20:43:18 +00:00
if test.mustError {
if err == nil {
t.Fatal("expected error, got nil")
}
t.Logf("found expected error: %v", err)
return
}
if err != nil {
t.Fatal(err)
}
if !cmp.Equal(&test.want, tree) {
t.Error(cmp.Diff(&test.want, tree))
}
})
}
}