2
2
mirror of https://github.com/octoleo/restic.git synced 2024-12-03 18:38:20 +00:00

backup: test that deviceID is only stored for hardlinks

This commit is contained in:
Michael Eischer 2024-03-28 19:11:56 +01:00
parent a9b3d86c4f
commit d705741571
2 changed files with 73 additions and 1 deletions

View File

@ -6,6 +6,12 @@ package archiver
import ( import (
"os" "os"
"syscall" "syscall"
"testing"
"github.com/restic/restic/internal/feature"
"github.com/restic/restic/internal/fs"
"github.com/restic/restic/internal/restic"
restictest "github.com/restic/restic/internal/test"
) )
type wrappedFileInfo struct { type wrappedFileInfo struct {
@ -39,3 +45,45 @@ func wrapFileInfo(fi os.FileInfo) os.FileInfo {
return res return res
} }
func statAndSnapshot(t *testing.T, repo restic.Repository, name string) (*restic.Node, *restic.Node) {
fi := lstat(t, name)
want, err := restic.NodeFromFileInfo(name, fi)
restictest.OK(t, err)
_, node := snapshot(t, repo, fs.Local{}, nil, name)
return want, node
}
func TestHardlinkMetadata(t *testing.T) {
defer feature.TestSetFlag(t, feature.Flag, feature.DeviceIDForHardlinks, true)()
files := TestDir{
"testfile": TestFile{
Content: "foo bar test file",
},
"linktarget": TestFile{
Content: "test file",
},
"testlink": TestHardlink{
Target: "./linktarget",
},
"testdir": TestDir{},
}
tempdir, repo := prepareTempdirRepoSrc(t, files)
back := restictest.Chdir(t, tempdir)
defer back()
want, node := statAndSnapshot(t, repo, "testlink")
restictest.Assert(t, node.DeviceID == want.DeviceID, "device id mismatch expected %v got %v", want.DeviceID, node.DeviceID)
restictest.Assert(t, node.Links == want.Links, "link count mismatch expected %v got %v", want.Links, node.Links)
restictest.Assert(t, node.Inode == want.Inode, "inode mismatch expected %v got %v", want.Inode, node.Inode)
_, node = statAndSnapshot(t, repo, "testfile")
restictest.Assert(t, node.DeviceID == 0, "device id mismatch for testfile expected %v got %v", 0, node.DeviceID)
_, node = statAndSnapshot(t, repo, "testdir")
restictest.Assert(t, node.DeviceID == 0, "device id mismatch for testdir expected %v got %v", 0, node.DeviceID)
}

View File

@ -6,6 +6,7 @@ import (
"path" "path"
"path/filepath" "path/filepath"
"runtime" "runtime"
"sort"
"strings" "strings"
"testing" "testing"
"time" "time"
@ -63,11 +64,29 @@ func (s TestSymlink) String() string {
return "<Symlink>" return "<Symlink>"
} }
// TestHardlink describes a hardlink created for a test.
type TestHardlink struct {
Target string
}
func (s TestHardlink) String() string {
return "<Hardlink>"
}
// TestCreateFiles creates a directory structure described by dir at target, // TestCreateFiles creates a directory structure described by dir at target,
// which must already exist. On Windows, symlinks aren't created. // which must already exist. On Windows, symlinks aren't created.
func TestCreateFiles(t testing.TB, target string, dir TestDir) { func TestCreateFiles(t testing.TB, target string, dir TestDir) {
t.Helper() t.Helper()
for name, item := range dir {
// ensure a stable order such that it can be guaranteed that a hardlink target already exists
var names []string
for name := range dir {
names = append(names, name)
}
sort.Strings(names)
for _, name := range names {
item := dir[name]
targetPath := filepath.Join(target, name) targetPath := filepath.Join(target, name)
switch it := item.(type) { switch it := item.(type) {
@ -81,6 +100,11 @@ func TestCreateFiles(t testing.TB, target string, dir TestDir) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
case TestHardlink:
err := fs.Link(filepath.Join(target, filepath.FromSlash(it.Target)), targetPath)
if err != nil {
t.Fatal(err)
}
case TestDir: case TestDir:
err := fs.Mkdir(targetPath, 0755) err := fs.Mkdir(targetPath, 0755)
if err != nil { if err != nil {