2
2
mirror of https://github.com/octoleo/restic.git synced 2024-12-01 17:23:57 +00:00

backup: test that vss backups work if underlying data was removed

This commit is contained in:
Michael Eischer 2024-10-18 20:05:32 +02:00
parent ca79cb92e3
commit 9f206601af
2 changed files with 52 additions and 0 deletions

View File

@ -97,6 +97,7 @@ type BackupOptions struct {
} }
var backupOptions BackupOptions var backupOptions BackupOptions
var backupFSTestHook func(fs fs.FS) fs.FS
// ErrInvalidSourceData is used to report an incomplete backup // ErrInvalidSourceData is used to report an incomplete backup
var ErrInvalidSourceData = errors.New("at least one source file could not be read") var ErrInvalidSourceData = errors.New("at least one source file could not be read")
@ -582,6 +583,10 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
targets = []string{filename} targets = []string{filename}
} }
if backupFSTestHook != nil {
targetFS = backupFSTestHook(targetFS)
}
// rejectFuncs collect functions that can reject items from the backup based on path and file info // rejectFuncs collect functions that can reject items from the backup based on path and file info
rejectFuncs, err := collectRejectFuncs(opts, targets, targetFS) rejectFuncs, err := collectRejectFuncs(opts, targets, targetFS)
if err != nil { if err != nil {

View File

@ -111,6 +111,53 @@ func TestBackupWithRelativePath(t *testing.T) {
rtest.Assert(t, latestSn.Parent != nil && latestSn.Parent.Equal(firstSnapshotID), "second snapshot selected unexpected parent %v instead of %v", latestSn.Parent, firstSnapshotID) rtest.Assert(t, latestSn.Parent != nil && latestSn.Parent.Equal(firstSnapshotID), "second snapshot selected unexpected parent %v instead of %v", latestSn.Parent, firstSnapshotID)
} }
type vssDeleteOriginalFS struct {
fs.FS
testdata string
hasRemoved bool
}
func (f *vssDeleteOriginalFS) Lstat(name string) (os.FileInfo, error) {
if !f.hasRemoved {
// call Lstat to trigger snapshot creation
_, _ = f.FS.Lstat(name)
// nuke testdata
if err := os.RemoveAll(f.testdata); err != nil {
return nil, err
}
f.hasRemoved = true
}
return f.FS.Lstat(name)
}
func TestBackupVSS(t *testing.T) {
if runtime.GOOS != "windows" || fs.HasSufficientPrivilegesForVSS() != nil {
t.Skip("vss fs test can only be run on windows with admin privileges")
}
env, cleanup := withTestEnvironment(t)
defer cleanup()
testSetupBackupData(t, env)
opts := BackupOptions{UseFsSnapshot: true}
var testFS *vssDeleteOriginalFS
backupFSTestHook = func(fs fs.FS) fs.FS {
testFS = &vssDeleteOriginalFS{
FS: fs,
testdata: env.testdata,
}
return testFS
}
defer func() {
backupFSTestHook = nil
}()
testRunBackup(t, filepath.Dir(env.testdata), []string{"testdata"}, opts, env.gopts)
testListSnapshots(t, env.gopts, 1)
rtest.Equals(t, true, testFS.hasRemoved, "testdata was not removed")
}
func TestBackupParentSelection(t *testing.T) { func TestBackupParentSelection(t *testing.T) {
env, cleanup := withTestEnvironment(t) env, cleanup := withTestEnvironment(t)
defer cleanup() defer cleanup()