2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-26 14:56:29 +00:00

Add mock.Repository, Rework SetupRepo

This commit is contained in:
Alexander Neumann 2016-09-04 12:52:43 +02:00
parent b5b3c0eaf8
commit bef5c4acb8
8 changed files with 228 additions and 87 deletions

View File

@ -47,8 +47,8 @@ func benchmarkChunkEncrypt(b testing.TB, buf, buf2 []byte, rd Rdr, key *crypto.K
} }
func BenchmarkChunkEncrypt(b *testing.B) { func BenchmarkChunkEncrypt(b *testing.B) {
repo := SetupRepo() repo, cleanup := SetupRepo(b)
defer TeardownRepo(repo) defer cleanup()
data := Random(23, 10<<20) // 10MiB data := Random(23, 10<<20) // 10MiB
rd := bytes.NewReader(data) 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) { func BenchmarkChunkEncryptParallel(b *testing.B) {
repo := SetupRepo() repo, cleanup := SetupRepo(b)
defer TeardownRepo(repo) defer cleanup()
data := Random(23, 10<<20) // 10MiB data := Random(23, 10<<20) // 10MiB
@ -98,8 +98,8 @@ func BenchmarkChunkEncryptParallel(b *testing.B) {
} }
func archiveDirectory(b testing.TB) { func archiveDirectory(b testing.TB) {
repo := SetupRepo() repo, cleanup := SetupRepo(b)
defer TeardownRepo(repo) defer cleanup()
arch := archiver.New(repo) arch := archiver.New(repo)
@ -136,8 +136,8 @@ func countPacks(repo restic.Repository, t restic.FileType) (n uint) {
} }
func archiveWithDedup(t testing.TB) { func archiveWithDedup(t testing.TB) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
if BenchArchiveDirectory == "" { if BenchArchiveDirectory == "" {
t.Skip("benchdir not set, skipping TestArchiverDedup") t.Skip("benchdir not set, skipping TestArchiverDedup")
@ -150,7 +150,7 @@ func archiveWithDedup(t testing.TB) {
} }
// archive a few files // 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()) t.Logf("archived snapshot %v", sn.ID().Str())
// get archive stats // get archive stats
@ -161,7 +161,7 @@ func archiveWithDedup(t testing.TB) {
cnt.before.packs, cnt.before.dataBlobs, cnt.before.treeBlobs) cnt.before.packs, cnt.before.dataBlobs, cnt.before.treeBlobs)
// archive the same files again, without parent snapshot // 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()) t.Logf("archived snapshot %v", sn2.ID().Str())
// get archive stats again // get archive stats again
@ -178,7 +178,7 @@ func archiveWithDedup(t testing.TB) {
} }
// archive the same files again, with a parent snapshot // 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()) t.Logf("archived snapshot %v, parent %v", sn3.ID().Str(), sn2.ID().Str())
// get archive stats again // get archive stats again
@ -208,8 +208,8 @@ func TestParallelSaveWithDuplication(t *testing.T) {
} }
func testParallelSaveWithDuplication(t *testing.T, seed int) { func testParallelSaveWithDuplication(t *testing.T, seed int) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
dataSizeMb := 128 dataSizeMb := 128
duplication := 7 duplication := 7

View File

@ -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
}

View File

@ -10,8 +10,8 @@ import (
) )
func TestLock(t *testing.T) { func TestLock(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
lock, err := restic.NewLock(repo) lock, err := restic.NewLock(repo)
OK(t, err) OK(t, err)
@ -20,8 +20,8 @@ func TestLock(t *testing.T) {
} }
func TestDoubleUnlock(t *testing.T) { func TestDoubleUnlock(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
lock, err := restic.NewLock(repo) lock, err := restic.NewLock(repo)
OK(t, err) OK(t, err)
@ -34,8 +34,8 @@ func TestDoubleUnlock(t *testing.T) {
} }
func TestMultipleLock(t *testing.T) { func TestMultipleLock(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
lock1, err := restic.NewLock(repo) lock1, err := restic.NewLock(repo)
OK(t, err) OK(t, err)
@ -48,8 +48,8 @@ func TestMultipleLock(t *testing.T) {
} }
func TestLockExclusive(t *testing.T) { func TestLockExclusive(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
elock, err := restic.NewExclusiveLock(repo) elock, err := restic.NewExclusiveLock(repo)
OK(t, err) OK(t, err)
@ -57,8 +57,8 @@ func TestLockExclusive(t *testing.T) {
} }
func TestLockOnExclusiveLockedRepo(t *testing.T) { func TestLockOnExclusiveLockedRepo(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
elock, err := restic.NewExclusiveLock(repo) elock, err := restic.NewExclusiveLock(repo)
OK(t, err) OK(t, err)
@ -74,8 +74,8 @@ func TestLockOnExclusiveLockedRepo(t *testing.T) {
} }
func TestExclusiveLockOnLockedRepo(t *testing.T) { func TestExclusiveLockOnLockedRepo(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
elock, err := restic.NewLock(repo) elock, err := restic.NewLock(repo)
OK(t, err) OK(t, err)
@ -168,8 +168,8 @@ func lockExists(repo restic.Repository, t testing.TB, id restic.ID) bool {
} }
func TestLockWithStaleLock(t *testing.T) { func TestLockWithStaleLock(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
id1, err := createFakeLock(repo, time.Now().Add(-time.Hour), os.Getpid()) id1, err := createFakeLock(repo, time.Now().Add(-time.Hour), os.Getpid())
OK(t, err) OK(t, err)
@ -193,8 +193,8 @@ func TestLockWithStaleLock(t *testing.T) {
} }
func TestRemoveAllLocks(t *testing.T) { func TestRemoveAllLocks(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
id1, err := createFakeLock(repo, time.Now().Add(-time.Hour), os.Getpid()) id1, err := createFakeLock(repo, time.Now().Add(-time.Hour), os.Getpid())
OK(t, err) OK(t, err)
@ -216,8 +216,8 @@ func TestRemoveAllLocks(t *testing.T) {
} }
func TestLockRefresh(t *testing.T) { func TestLockRefresh(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
lock, err := restic.NewLock(repo) lock, err := restic.NewLock(repo)
OK(t, err) OK(t, err)

View File

@ -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)
}

View File

@ -10,6 +10,7 @@ import (
"testing" "testing"
"restic" "restic"
"restic/archiver"
"restic/repository" "restic/repository"
. "restic/test" . "restic/test"
) )
@ -17,8 +18,8 @@ import (
var testSizes = []int{5, 23, 2<<18 + 23, 1 << 20} var testSizes = []int{5, 23, 2<<18 + 23, 1 << 20}
func TestSave(t *testing.T) { func TestSave(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
for _, size := range testSizes { for _, size := range testSizes {
data := make([]byte, size) data := make([]byte, size)
@ -53,8 +54,8 @@ func TestSave(t *testing.T) {
} }
func TestSaveFrom(t *testing.T) { func TestSaveFrom(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
for _, size := range testSizes { for _, size := range testSizes {
data := make([]byte, size) data := make([]byte, size)
@ -87,8 +88,8 @@ func TestSaveFrom(t *testing.T) {
} }
func BenchmarkSaveAndEncrypt(t *testing.B) { func BenchmarkSaveAndEncrypt(t *testing.B) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
size := 4 << 20 // 4MiB size := 4 << 20 // 4MiB
@ -109,15 +110,15 @@ func BenchmarkSaveAndEncrypt(t *testing.B) {
} }
func TestLoadTree(t *testing.T) { func TestLoadTree(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
if BenchArchiveDirectory == "" { if BenchArchiveDirectory == "" {
t.Skip("benchdir not set, skipping") t.Skip("benchdir not set, skipping")
} }
// archive a few files // archive a few files
sn := SnapshotDir(t, repo, BenchArchiveDirectory, nil) sn := archiver.TestSnapshot(t, repo, BenchArchiveDirectory, nil)
OK(t, repo.Flush()) OK(t, repo.Flush())
_, err := repo.LoadTree(*sn.Tree) _, err := repo.LoadTree(*sn.Tree)
@ -125,15 +126,15 @@ func TestLoadTree(t *testing.T) {
} }
func BenchmarkLoadTree(t *testing.B) { func BenchmarkLoadTree(t *testing.B) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
if BenchArchiveDirectory == "" { if BenchArchiveDirectory == "" {
t.Skip("benchdir not set, skipping") t.Skip("benchdir not set, skipping")
} }
// archive a few files // archive a few files
sn := SnapshotDir(t, repo, BenchArchiveDirectory, nil) sn := archiver.TestSnapshot(t, repo, BenchArchiveDirectory, nil)
OK(t, repo.Flush()) OK(t, repo.Flush())
t.ResetTimer() t.ResetTimer()
@ -145,8 +146,8 @@ func BenchmarkLoadTree(t *testing.B) {
} }
func TestLoadJSONUnpacked(t *testing.T) { func TestLoadJSONUnpacked(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
if BenchArchiveDirectory == "" { if BenchArchiveDirectory == "" {
t.Skip("benchdir not set, skipping") 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) { func TestRepositoryIncrementalIndex(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
repository.IndexFull = func(*repository.Index) bool { return true } repository.IndexFull = func(*repository.Index) bool { return true }

View File

@ -8,7 +8,6 @@ import (
"testing" "testing"
"restic" "restic"
"restic/archiver"
"restic/backend/local" "restic/backend/local"
"restic/repository" "restic/repository"
) )
@ -50,29 +49,25 @@ func getBoolVar(name string, defaultValue bool) bool {
} }
// SetupRepo returns a repo setup in a temp dir. // 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-") tempdir, err := ioutil.TempDir(TestTempDir, "restic-test-")
if err != nil { if err != nil {
panic(err) t.Fatal(err)
} }
// create repository below temp dir // create repository below temp dir
b, err := local.Create(filepath.Join(tempdir, "repo")) b, err := local.Create(filepath.Join(tempdir, "repo"))
if err != nil { if err != nil {
panic(err) t.Fatal(err)
} }
repo := repository.New(b) r := repository.New(b)
err = repo.Init(TestPassword) err = r.Init(TestPassword)
if err != nil { if err != nil {
panic(err) t.Fatal(err)
} }
repo = r
return repo cleanup = func() {
}
// TeardownRepo removes a repository created by SetupRepo.
func TeardownRepo(repo restic.Repository) {
if !TestCleanupTempDirs { if !TestCleanupTempDirs {
l := repo.Backend().(*local.Local) l := repo.Backend().(*local.Local)
fmt.Printf("leaving local backend at %s\n", l.Location()) fmt.Printf("leaving local backend at %s\n", l.Location())
@ -82,22 +77,10 @@ func TeardownRepo(repo restic.Repository) {
if r, ok := repo.(restic.Deleter); ok { if r, ok := repo.(restic.Deleter); ok {
err := r.Delete() err := r.Delete()
if err != nil { if err != nil {
panic(err) t.Fatal(err)
}
} }
} }
}
// SnapshotDir creates a new snapshot of path. return repo, cleanup
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)
} }

View File

@ -92,8 +92,8 @@ func TestNodeComparison(t *testing.T) {
} }
func TestLoadTree(t *testing.T) { func TestLoadTree(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
// save tree // save tree
tree := restic.NewTree() tree := restic.NewTree()

View File

@ -15,8 +15,8 @@ import (
) )
func TestWalkTree(t *testing.T) { func TestWalkTree(t *testing.T) {
repo := SetupRepo() repo, cleanup := SetupRepo(t)
defer TeardownRepo(repo) defer cleanup()
dirs, err := filepath.Glob(TestWalkerPath) dirs, err := filepath.Glob(TestWalkerPath)
OK(t, err) OK(t, err)