From bef5c4acb8e906f04a363762e884e125e8ddcb45 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Sun, 4 Sep 2016 12:52:43 +0200 Subject: [PATCH] Add mock.Repository, Rework SetupRepo --- src/restic/archiver/archiver_test.go | 26 ++--- src/restic/archiver/testing.go | 16 +++ src/restic/lock_test.go | 36 +++--- src/restic/mock/repository.go | 141 +++++++++++++++++++++++ src/restic/repository/repository_test.go | 33 +++--- src/restic/test/backend.go | 55 +++------ src/restic/tree_test.go | 4 +- src/restic/walk/walk_test.go | 4 +- 8 files changed, 228 insertions(+), 87 deletions(-) create mode 100644 src/restic/archiver/testing.go create mode 100644 src/restic/mock/repository.go diff --git a/src/restic/archiver/archiver_test.go b/src/restic/archiver/archiver_test.go index a1fa47683..67a9ff8f6 100644 --- a/src/restic/archiver/archiver_test.go +++ b/src/restic/archiver/archiver_test.go @@ -47,8 +47,8 @@ func benchmarkChunkEncrypt(b testing.TB, buf, buf2 []byte, rd Rdr, key *crypto.K } func BenchmarkChunkEncrypt(b *testing.B) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(b) + defer cleanup() data := Random(23, 10<<20) // 10MiB rd := bytes.NewReader(data) @@ -79,8 +79,8 @@ func benchmarkChunkEncryptP(b *testing.PB, buf []byte, rd Rdr, key *crypto.Key) } func BenchmarkChunkEncryptParallel(b *testing.B) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(b) + defer cleanup() data := Random(23, 10<<20) // 10MiB @@ -98,8 +98,8 @@ func BenchmarkChunkEncryptParallel(b *testing.B) { } func archiveDirectory(b testing.TB) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(b) + defer cleanup() arch := archiver.New(repo) @@ -136,8 +136,8 @@ func countPacks(repo restic.Repository, t restic.FileType) (n uint) { } func archiveWithDedup(t testing.TB) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() if BenchArchiveDirectory == "" { t.Skip("benchdir not set, skipping TestArchiverDedup") @@ -150,7 +150,7 @@ func archiveWithDedup(t testing.TB) { } // archive a few files - sn := SnapshotDir(t, repo, BenchArchiveDirectory, nil) + sn := archiver.TestSnapshot(t, repo, BenchArchiveDirectory, nil) t.Logf("archived snapshot %v", sn.ID().Str()) // get archive stats @@ -161,7 +161,7 @@ func archiveWithDedup(t testing.TB) { cnt.before.packs, cnt.before.dataBlobs, cnt.before.treeBlobs) // archive the same files again, without parent snapshot - sn2 := SnapshotDir(t, repo, BenchArchiveDirectory, nil) + sn2 := archiver.TestSnapshot(t, repo, BenchArchiveDirectory, nil) t.Logf("archived snapshot %v", sn2.ID().Str()) // get archive stats again @@ -178,7 +178,7 @@ func archiveWithDedup(t testing.TB) { } // archive the same files again, with a parent snapshot - sn3 := SnapshotDir(t, repo, BenchArchiveDirectory, sn2.ID()) + sn3 := archiver.TestSnapshot(t, repo, BenchArchiveDirectory, sn2.ID()) t.Logf("archived snapshot %v, parent %v", sn3.ID().Str(), sn2.ID().Str()) // get archive stats again @@ -208,8 +208,8 @@ func TestParallelSaveWithDuplication(t *testing.T) { } func testParallelSaveWithDuplication(t *testing.T, seed int) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() dataSizeMb := 128 duplication := 7 diff --git a/src/restic/archiver/testing.go b/src/restic/archiver/testing.go new file mode 100644 index 000000000..b73f09dcd --- /dev/null +++ b/src/restic/archiver/testing.go @@ -0,0 +1,16 @@ +package archiver + +import ( + "restic" + "testing" +) + +// TestSnapshot creates a new snapshot of path. +func TestSnapshot(t testing.TB, repo restic.Repository, path string, parent *restic.ID) *restic.Snapshot { + arch := New(repo) + sn, _, err := arch.Snapshot(nil, []string{path}, parent) + if err != nil { + t.Fatal(err) + } + return sn +} diff --git a/src/restic/lock_test.go b/src/restic/lock_test.go index b97bc97a8..b60b9ea8a 100644 --- a/src/restic/lock_test.go +++ b/src/restic/lock_test.go @@ -10,8 +10,8 @@ import ( ) func TestLock(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() lock, err := restic.NewLock(repo) OK(t, err) @@ -20,8 +20,8 @@ func TestLock(t *testing.T) { } func TestDoubleUnlock(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() lock, err := restic.NewLock(repo) OK(t, err) @@ -34,8 +34,8 @@ func TestDoubleUnlock(t *testing.T) { } func TestMultipleLock(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() lock1, err := restic.NewLock(repo) OK(t, err) @@ -48,8 +48,8 @@ func TestMultipleLock(t *testing.T) { } func TestLockExclusive(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() elock, err := restic.NewExclusiveLock(repo) OK(t, err) @@ -57,8 +57,8 @@ func TestLockExclusive(t *testing.T) { } func TestLockOnExclusiveLockedRepo(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() elock, err := restic.NewExclusiveLock(repo) OK(t, err) @@ -74,8 +74,8 @@ func TestLockOnExclusiveLockedRepo(t *testing.T) { } func TestExclusiveLockOnLockedRepo(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() elock, err := restic.NewLock(repo) OK(t, err) @@ -168,8 +168,8 @@ func lockExists(repo restic.Repository, t testing.TB, id restic.ID) bool { } func TestLockWithStaleLock(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() id1, err := createFakeLock(repo, time.Now().Add(-time.Hour), os.Getpid()) OK(t, err) @@ -193,8 +193,8 @@ func TestLockWithStaleLock(t *testing.T) { } func TestRemoveAllLocks(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() id1, err := createFakeLock(repo, time.Now().Add(-time.Hour), os.Getpid()) OK(t, err) @@ -216,8 +216,8 @@ func TestRemoveAllLocks(t *testing.T) { } func TestLockRefresh(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() lock, err := restic.NewLock(repo) OK(t, err) diff --git a/src/restic/mock/repository.go b/src/restic/mock/repository.go new file mode 100644 index 000000000..df109c5f3 --- /dev/null +++ b/src/restic/mock/repository.go @@ -0,0 +1,141 @@ +package mock + +import ( + "restic" + "restic/crypto" +) + +// Repository implements a mock Repository. +type Repository struct { + BackendFn func() Backend + + KeyFn func() *crypto.Key + + SetIndexFn func(restic.Index) + + IndexFn func() restic.Index + SaveFullIndexFn func() error + SaveIndexFn func() error + LoadIndexFn func() error + + ConfigFn func() restic.Config + + LookupBlobSizeFn func(restic.ID, restic.BlobType) (uint, error) + + ListFn func(restic.FileType, <-chan struct{}) <-chan restic.ID + ListPackFn func(restic.ID) ([]restic.Blob, int64, error) + + FlushFn func() error + + SaveUnpackedFn func(restic.FileType, []byte) (restic.ID, error) + SaveJSONUnpackedFn func(restic.FileType, interface{}) (restic.ID, error) + + LoadJSONUnpackedFn func(restic.FileType, restic.ID, interface{}) error + LoadAndDecryptFn func(restic.FileType, restic.ID) ([]byte, error) + + LoadBlobFn func(restic.BlobType, restic.ID, []byte) (int, error) + SaveBlobFn func(restic.BlobType, []byte, restic.ID) (restic.ID, error) + + LoadTreeFn func(restic.ID) (*restic.Tree, error) + SaveTreeFn func(t *restic.Tree) (restic.ID, error) +} + +// Backend is a stub method. +func (repo *Repository) Backend() Backend { + return repo.BackendFn() +} + +// Key is a stub method. +func (repo *Repository) Key() *crypto.Key { + return repo.KeyFn() +} + +// SetIndex is a stub method. +func (repo *Repository) SetIndex(idx restic.Index) { + repo.SetIndexFn(idx) +} + +// Index is a stub method. +func (repo *Repository) Index() restic.Index { + return repo.IndexFn() +} + +// SaveFullIndex is a stub method. +func (repo *Repository) SaveFullIndex() error { + return repo.SaveFullIndexFn() +} + +// SaveIndex is a stub method. +func (repo *Repository) SaveIndex() error { + return repo.SaveIndexFn() +} + +// LoadIndex is a stub method. +func (repo *Repository) LoadIndex() error { + return repo.LoadIndexFn() +} + +// Config is a stub method. +func (repo *Repository) Config() restic.Config { + return repo.ConfigFn() +} + +// LookupBlobSize is a stub method. +func (repo *Repository) LookupBlobSize(id restic.ID, t restic.BlobType) (uint, error) { + return repo.LookupBlobSizeFn(id, t) +} + +// List is a stub method. +func (repo *Repository) List(t restic.FileType, done <-chan struct{}) <-chan restic.ID { + return repo.ListFn(t, done) +} + +// ListPack is a stub method. +func (repo *Repository) ListPack(id restic.ID) ([]restic.Blob, int64, error) { + return repo.ListPackFn(id) +} + +// Flush is a stub method. +func (repo *Repository) Flush() error { + return repo.FlushFn() +} + +// SaveUnpacked is a stub method. +func (repo *Repository) SaveUnpacked(t restic.FileType, buf []byte) (restic.ID, error) { + return repo.SaveUnpackedFn(t, buf) +} + +// SaveJSONUnpacked is a stub method. +func (repo *Repository) SaveJSONUnpacked(t restic.FileType, item interface{}) (restic.ID, error) { + return repo.SaveJSONUnpackedFn(t, item) +} + +// LoadJSONUnpacked is a stub method. +func (repo *Repository) LoadJSONUnpacked(t restic.FileType, id restic.ID, item interface{}) error { + return repo.LoadJSONUnpackedFn(t, id, item) +} + +// LoadAndDecrypt is a stub method. +func (repo *Repository) LoadAndDecrypt(t restic.FileType, id restic.ID) ([]byte, error) { + return repo.LoadAndDecryptFn(t, id) +} + +// LoadBlob is a stub method. +func (repo *Repository) LoadBlob(t restic.BlobType, id restic.ID, buf []byte) (int, error) { + return repo.LoadBlobFn(t, id, buf) +} + +// SaveBlob is a stub method. +func (repo *Repository) SaveBlob(t restic.BlobType, buf []byte, id restic.ID) (restic.ID, error) { + return repo.SaveBlobFn(t, buf, id) +} + +// LoadTree is a stub method. +func (repo *Repository) LoadTree(id restic.ID) (*restic.Tree, error) { + return repo.LoadTreeFn(id) +} + +// SaveTree is a stub method. +func (repo *Repository) SaveTree(t *restic.Tree) (restic.ID, error) { + return repo.SaveTreeFn(t) +} diff --git a/src/restic/repository/repository_test.go b/src/restic/repository/repository_test.go index 3295ab5d9..2a2d54aaa 100644 --- a/src/restic/repository/repository_test.go +++ b/src/restic/repository/repository_test.go @@ -10,6 +10,7 @@ import ( "testing" "restic" + "restic/archiver" "restic/repository" . "restic/test" ) @@ -17,8 +18,8 @@ import ( var testSizes = []int{5, 23, 2<<18 + 23, 1 << 20} func TestSave(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() for _, size := range testSizes { data := make([]byte, size) @@ -53,8 +54,8 @@ func TestSave(t *testing.T) { } func TestSaveFrom(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() for _, size := range testSizes { data := make([]byte, size) @@ -87,8 +88,8 @@ func TestSaveFrom(t *testing.T) { } func BenchmarkSaveAndEncrypt(t *testing.B) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() size := 4 << 20 // 4MiB @@ -109,15 +110,15 @@ func BenchmarkSaveAndEncrypt(t *testing.B) { } func TestLoadTree(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() if BenchArchiveDirectory == "" { t.Skip("benchdir not set, skipping") } // archive a few files - sn := SnapshotDir(t, repo, BenchArchiveDirectory, nil) + sn := archiver.TestSnapshot(t, repo, BenchArchiveDirectory, nil) OK(t, repo.Flush()) _, err := repo.LoadTree(*sn.Tree) @@ -125,15 +126,15 @@ func TestLoadTree(t *testing.T) { } func BenchmarkLoadTree(t *testing.B) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() if BenchArchiveDirectory == "" { t.Skip("benchdir not set, skipping") } // archive a few files - sn := SnapshotDir(t, repo, BenchArchiveDirectory, nil) + sn := archiver.TestSnapshot(t, repo, BenchArchiveDirectory, nil) OK(t, repo.Flush()) t.ResetTimer() @@ -145,8 +146,8 @@ func BenchmarkLoadTree(t *testing.B) { } func TestLoadJSONUnpacked(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() if BenchArchiveDirectory == "" { t.Skip("benchdir not set, skipping") @@ -206,8 +207,8 @@ func saveRandomDataBlobs(t testing.TB, repo restic.Repository, num int, sizeMax } func TestRepositoryIncrementalIndex(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() repository.IndexFull = func(*repository.Index) bool { return true } diff --git a/src/restic/test/backend.go b/src/restic/test/backend.go index 66567ab79..055d7c10e 100644 --- a/src/restic/test/backend.go +++ b/src/restic/test/backend.go @@ -8,7 +8,6 @@ import ( "testing" "restic" - "restic/archiver" "restic/backend/local" "restic/repository" ) @@ -50,54 +49,38 @@ func getBoolVar(name string, defaultValue bool) bool { } // SetupRepo returns a repo setup in a temp dir. -func SetupRepo() restic.Repository { +func SetupRepo(t testing.TB) (repo restic.Repository, cleanup func()) { tempdir, err := ioutil.TempDir(TestTempDir, "restic-test-") if err != nil { - panic(err) + t.Fatal(err) } // create repository below temp dir b, err := local.Create(filepath.Join(tempdir, "repo")) if err != nil { - panic(err) + t.Fatal(err) } - repo := repository.New(b) - err = repo.Init(TestPassword) + r := repository.New(b) + err = r.Init(TestPassword) if err != nil { - panic(err) + t.Fatal(err) } + repo = r + cleanup = func() { + if !TestCleanupTempDirs { + l := repo.Backend().(*local.Local) + fmt.Printf("leaving local backend at %s\n", l.Location()) + return + } - return repo -} - -// TeardownRepo removes a repository created by SetupRepo. -func TeardownRepo(repo restic.Repository) { - if !TestCleanupTempDirs { - l := repo.Backend().(*local.Local) - fmt.Printf("leaving local backend at %s\n", l.Location()) - return - } - - if r, ok := repo.(restic.Deleter); ok { - err := r.Delete() - if err != nil { - panic(err) + if r, ok := repo.(restic.Deleter); ok { + err := r.Delete() + if err != nil { + t.Fatal(err) + } } } -} -// SnapshotDir creates a new snapshot of path. -func SnapshotDir(t testing.TB, repo restic.Repository, path string, parent *restic.ID) *restic.Snapshot { - arch := archiver.New(repo) - sn, _, err := arch.Snapshot(nil, []string{path}, parent) - OK(t, err) - return sn -} - -// WithRepo runs the function t with a repository that is removed after f returns. -func WithRepo(t testing.TB, f func(restic.Repository)) { - repo := SetupRepo() - f(repo) - TeardownRepo(repo) + return repo, cleanup } diff --git a/src/restic/tree_test.go b/src/restic/tree_test.go index 779842552..71c4441ed 100644 --- a/src/restic/tree_test.go +++ b/src/restic/tree_test.go @@ -92,8 +92,8 @@ func TestNodeComparison(t *testing.T) { } func TestLoadTree(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() // save tree tree := restic.NewTree() diff --git a/src/restic/walk/walk_test.go b/src/restic/walk/walk_test.go index 681c2f1e6..19874c3b0 100644 --- a/src/restic/walk/walk_test.go +++ b/src/restic/walk/walk_test.go @@ -15,8 +15,8 @@ import ( ) func TestWalkTree(t *testing.T) { - repo := SetupRepo() - defer TeardownRepo(repo) + repo, cleanup := SetupRepo(t) + defer cleanup() dirs, err := filepath.Glob(TestWalkerPath) OK(t, err)