Add test that repo.List is only called once

This commit is contained in:
Alexander Weiss 2020-10-17 21:55:46 +02:00 committed by Alexander Neumann
parent fd33030556
commit d2e53730d6
2 changed files with 61 additions and 2 deletions

View file

@ -3,8 +3,11 @@ Enhancement: Improve pruning performance and make pruning more customizable
The `prune` command is now much faster. This is especially the case for remote The `prune` command is now much faster. This is especially the case for remote
repositories or repositories with not much data to remove. repositories or repositories with not much data to remove.
Also the memory usage of the `prune` command is now reduced. Also the memory usage of the `prune` command is now reduced.
Restic used to rebuild the index from scratch after pruning. This is now Restic used to rebuild the index from scratch after pruning. This could lead
changed and the index rebuilding uses the information already known by `prune`. to missing packs in the index in some cases for eventually consistent
backends, like e.g. AWS S3.
This behavior is now changed and the index rebuilding uses the information
already known by `prune`.
By default, the `prune` command no longer removes all unused data. This By default, the `prune` command no longer removes all unused data. This
behavior can be fine-tuned by new options, like the acceptable amount of unused space or behavior can be fine-tuned by new options, like the acceptable amount of unused space or

View file

@ -1559,6 +1559,62 @@ func testEdgeCaseRepo(t *testing.T, tarfile string, optionsCheck CheckOptions, o
} }
} }
// a listOnceBackend only allows listing once per filetype
// listing filetypes more than once may cause problems with eventually consistent
// backends (like e.g. AWS S3) as the second listing may be inconsistent to what
// is expected by the first listing + some operations.
type listOnceBackend struct {
restic.Backend
listedFileType map[restic.FileType]bool
}
func newListOnceBackend(be restic.Backend) *listOnceBackend {
return &listOnceBackend{
Backend: be,
listedFileType: make(map[restic.FileType]bool),
}
}
func (be *listOnceBackend) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error {
if t != restic.LockFile && be.listedFileType[t] {
return errors.Errorf("tried listing type %v the second time", t)
}
be.listedFileType[t] = true
return be.Backend.List(ctx, t, fn)
}
func TestPruneListOnce(t *testing.T) {
env, cleanup := withTestEnvironment(t)
defer cleanup()
env.gopts.backendTestHook = func(r restic.Backend) (restic.Backend, error) {
return newListOnceBackend(r), nil
}
pruneOpts := PruneOptions{MaxUnused: "0"}
checkOpts := CheckOptions{ReadData: true, CheckUnused: true}
testSetupBackupData(t, env)
opts := BackupOptions{}
testRunBackup(t, "", []string{filepath.Join(env.testdata, "0", "0", "9")}, opts, env.gopts)
firstSnapshot := testRunList(t, "snapshots", env.gopts)
rtest.Assert(t, len(firstSnapshot) == 1,
"expected one snapshot, got %v", firstSnapshot)
testRunBackup(t, "", []string{filepath.Join(env.testdata, "0", "0", "9", "2")}, opts, env.gopts)
testRunBackup(t, "", []string{filepath.Join(env.testdata, "0", "0", "9", "3")}, opts, env.gopts)
snapshotIDs := testRunList(t, "snapshots", env.gopts)
rtest.Assert(t, len(snapshotIDs) == 3,
"expected 3 snapshot, got %v", snapshotIDs)
testRunForgetJSON(t, env.gopts)
testRunForget(t, env.gopts, firstSnapshot[0].String())
testRunPrune(t, env.gopts, pruneOpts)
rtest.OK(t, runCheck(checkOpts, env.gopts, nil))
}
func TestHardLink(t *testing.T) { func TestHardLink(t *testing.T) {
// this test assumes a test set with a single directory containing hard linked files // this test assumes a test set with a single directory containing hard linked files
env, cleanup := withTestEnvironment(t) env, cleanup := withTestEnvironment(t)