2015-03-02 13:48:47 +00:00
|
|
|
package restic_test
|
|
|
|
|
|
|
|
import (
|
2015-07-19 22:13:39 +00:00
|
|
|
"os"
|
2015-03-02 13:48:47 +00:00
|
|
|
"path/filepath"
|
|
|
|
"testing"
|
2015-10-26 19:55:22 +00:00
|
|
|
"time"
|
2015-03-02 13:48:47 +00:00
|
|
|
|
|
|
|
"github.com/restic/restic"
|
2015-10-26 19:55:22 +00:00
|
|
|
"github.com/restic/restic/backend"
|
|
|
|
"github.com/restic/restic/pack"
|
2015-03-02 13:48:47 +00:00
|
|
|
"github.com/restic/restic/pipe"
|
2015-10-26 19:55:22 +00:00
|
|
|
"github.com/restic/restic/repository"
|
2015-04-09 19:15:48 +00:00
|
|
|
. "github.com/restic/restic/test"
|
2015-03-02 13:48:47 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestWalkTree(t *testing.T) {
|
2015-06-26 20:12:04 +00:00
|
|
|
repo := SetupRepo()
|
|
|
|
defer TeardownRepo(repo)
|
|
|
|
|
2015-06-28 11:15:35 +00:00
|
|
|
dirs, err := filepath.Glob(TestWalkerPath)
|
2015-04-09 19:15:48 +00:00
|
|
|
OK(t, err)
|
2015-03-02 13:48:47 +00:00
|
|
|
|
|
|
|
// archive a few files
|
2015-05-09 11:32:52 +00:00
|
|
|
arch := restic.NewArchiver(repo)
|
2015-03-02 13:48:47 +00:00
|
|
|
sn, _, err := arch.Snapshot(nil, dirs, nil)
|
2015-04-09 19:15:48 +00:00
|
|
|
OK(t, err)
|
2015-03-02 13:48:47 +00:00
|
|
|
|
2015-05-09 11:32:52 +00:00
|
|
|
// flush repo, write all packs
|
|
|
|
OK(t, repo.Flush())
|
2015-04-26 15:44:38 +00:00
|
|
|
|
2015-03-02 13:48:47 +00:00
|
|
|
done := make(chan struct{})
|
|
|
|
|
|
|
|
// start tree walker
|
|
|
|
treeJobs := make(chan restic.WalkTreeJob)
|
2015-07-25 15:05:45 +00:00
|
|
|
go restic.WalkTree(repo, *sn.Tree, done, treeJobs)
|
2015-03-02 13:48:47 +00:00
|
|
|
|
|
|
|
// start filesystem walker
|
2015-03-07 10:53:32 +00:00
|
|
|
fsJobs := make(chan pipe.Job)
|
|
|
|
resCh := make(chan pipe.Result, 1)
|
2015-07-19 22:13:39 +00:00
|
|
|
|
|
|
|
f := func(string, os.FileInfo) bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
go pipe.Walk(dirs, f, done, fsJobs, resCh)
|
2015-03-02 13:48:47 +00:00
|
|
|
|
|
|
|
for {
|
|
|
|
// receive fs job
|
|
|
|
fsJob, fsChOpen := <-fsJobs
|
2015-04-09 19:15:48 +00:00
|
|
|
Assert(t, !fsChOpen || fsJob != nil,
|
2015-03-02 13:48:47 +00:00
|
|
|
"received nil job from filesystem: %v %v", fsJob, fsChOpen)
|
2015-04-26 15:44:38 +00:00
|
|
|
if fsJob != nil {
|
|
|
|
OK(t, fsJob.Error())
|
|
|
|
}
|
2015-03-02 13:48:47 +00:00
|
|
|
|
|
|
|
var path string
|
|
|
|
fsEntries := 1
|
|
|
|
switch j := fsJob.(type) {
|
|
|
|
case pipe.Dir:
|
2015-03-07 10:53:32 +00:00
|
|
|
path = j.Path()
|
2015-03-02 13:48:47 +00:00
|
|
|
fsEntries = len(j.Entries)
|
|
|
|
case pipe.Entry:
|
2015-03-07 10:53:32 +00:00
|
|
|
path = j.Path()
|
2015-03-02 13:48:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// receive tree job
|
|
|
|
treeJob, treeChOpen := <-treeJobs
|
|
|
|
treeEntries := 1
|
|
|
|
|
2015-04-26 15:44:38 +00:00
|
|
|
OK(t, treeJob.Error)
|
|
|
|
|
2015-03-02 13:48:47 +00:00
|
|
|
if treeJob.Tree != nil {
|
|
|
|
treeEntries = len(treeJob.Tree.Nodes)
|
|
|
|
}
|
|
|
|
|
2015-04-09 19:15:48 +00:00
|
|
|
Assert(t, fsChOpen == treeChOpen,
|
2015-03-02 13:48:47 +00:00
|
|
|
"one channel closed too early: fsChOpen %v, treeChOpen %v",
|
|
|
|
fsChOpen, treeChOpen)
|
|
|
|
|
|
|
|
if !fsChOpen || !treeChOpen {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2015-04-09 19:15:48 +00:00
|
|
|
Assert(t, filepath.Base(path) == filepath.Base(treeJob.Path),
|
2015-03-02 13:48:47 +00:00
|
|
|
"paths do not match: %q != %q", filepath.Base(path), filepath.Base(treeJob.Path))
|
|
|
|
|
2015-04-09 19:15:48 +00:00
|
|
|
Assert(t, fsEntries == treeEntries,
|
2015-03-02 13:48:47 +00:00
|
|
|
"wrong number of entries: %v != %v", fsEntries, treeEntries)
|
|
|
|
}
|
|
|
|
}
|
2015-10-26 19:55:22 +00:00
|
|
|
|
|
|
|
type delayRepo struct {
|
|
|
|
repo *repository.Repository
|
|
|
|
delay time.Duration
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d delayRepo) LoadJSONPack(t pack.BlobType, id backend.ID, dst interface{}) error {
|
|
|
|
time.Sleep(d.delay)
|
|
|
|
return d.repo.LoadJSONPack(t, id, dst)
|
|
|
|
}
|
|
|
|
|
|
|
|
var repoFixture = filepath.Join("testdata", "walktree-test-repo.tar.gz")
|
|
|
|
|
|
|
|
func TestDelayedWalkTree(t *testing.T) {
|
|
|
|
WithTestEnvironment(t, repoFixture, func(repodir string) {
|
|
|
|
repo := OpenLocalRepo(t, repodir)
|
|
|
|
OK(t, repo.LoadIndex())
|
|
|
|
|
|
|
|
root, err := backend.ParseID("937a2f64f736c64ee700c6ab06f840c68c94799c288146a0e81e07f4c94254da")
|
|
|
|
OK(t, err)
|
|
|
|
|
|
|
|
dr := delayRepo{repo, 100 * time.Millisecond}
|
|
|
|
|
|
|
|
// start tree walker
|
|
|
|
treeJobs := make(chan restic.WalkTreeJob)
|
|
|
|
go restic.WalkTree(dr, root, nil, treeJobs)
|
|
|
|
|
|
|
|
for range treeJobs {
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkDelayedWalkTree(t *testing.B) {
|
|
|
|
WithTestEnvironment(t, repoFixture, func(repodir string) {
|
|
|
|
repo := OpenLocalRepo(t, repodir)
|
|
|
|
OK(t, repo.LoadIndex())
|
|
|
|
|
|
|
|
root, err := backend.ParseID("937a2f64f736c64ee700c6ab06f840c68c94799c288146a0e81e07f4c94254da")
|
|
|
|
OK(t, err)
|
|
|
|
|
|
|
|
dr := delayRepo{repo, 10 * time.Millisecond}
|
|
|
|
|
|
|
|
t.ResetTimer()
|
|
|
|
|
|
|
|
for i := 0; i < t.N; i++ {
|
|
|
|
// start tree walker
|
|
|
|
treeJobs := make(chan restic.WalkTreeJob)
|
|
|
|
go restic.WalkTree(dr, root, nil, treeJobs)
|
|
|
|
|
|
|
|
for range treeJobs {
|
|
|
|
// fmt.Printf("job: %v\n", job)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|