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 a7b13bd603
commit 1f5791222a
2 changed files with 52 additions and 0 deletions

View file

@ -95,6 +95,7 @@ type BackupOptions struct {
}
var backupOptions BackupOptions
var backupFSTestHook func(fs fs.FS) fs.FS
// ErrInvalidSourceData is used to report an incomplete backup
var ErrInvalidSourceData = errors.New("at least one source file could not be read")
@ -598,6 +599,10 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter
targets = []string{filename}
}
if backupFSTestHook != nil {
targetFS = backupFSTestHook(targetFS)
}
wg, wgCtx := errgroup.WithContext(ctx)
cancelCtx, cancel := context.WithCancel(wgCtx)
defer cancel()

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)
}
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) {
env, cleanup := withTestEnvironment(t)
defer cleanup()