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) i := 0 for job := range treeJobs { expectedPath := filepath.Join(strings.Split(walktreeTestItems[i], "/")...) if job.Path != expectedPath { t.Fatalf("expected path %q (%v), got %q", walktreeTestItems[i], i, job.Path) } i++ } if i != len(walktreeTestItems) { t.Fatalf("got %d items, expected %v", i, len(walktreeTestItems)) } }) }
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 { } } }) }
func TestWalkTree(t *testing.T) { repo := SetupRepo() defer TeardownRepo(repo) dirs, err := filepath.Glob(TestWalkerPath) OK(t, err) // archive a few files arch := restic.NewArchiver(repo) sn, _, err := arch.Snapshot(nil, dirs, nil) OK(t, err) // flush repo, write all packs OK(t, repo.Flush()) done := make(chan struct{}) // start tree walker treeJobs := make(chan restic.WalkTreeJob) go restic.WalkTree(repo, sn.Tree, done, treeJobs) // start filesystem walker fsJobs := make(chan pipe.Job) resCh := make(chan pipe.Result, 1) f := func(string, os.FileInfo) bool { return true } go pipe.Walk(dirs, f, done, fsJobs, resCh) for { // receive fs job fsJob, fsChOpen := <-fsJobs Assert(t, !fsChOpen || fsJob != nil, "received nil job from filesystem: %v %v", fsJob, fsChOpen) if fsJob != nil { OK(t, fsJob.Error()) } var path string fsEntries := 1 switch j := fsJob.(type) { case pipe.Dir: path = j.Path() fsEntries = len(j.Entries) case pipe.Entry: path = j.Path() } // receive tree job treeJob, treeChOpen := <-treeJobs treeEntries := 1 OK(t, treeJob.Error) if treeJob.Tree != nil { treeEntries = len(treeJob.Tree.Nodes) } Assert(t, fsChOpen == treeChOpen, "one channel closed too early: fsChOpen %v, treeChOpen %v", fsChOpen, treeChOpen) if !fsChOpen || !treeChOpen { break } Assert(t, filepath.Base(path) == filepath.Base(treeJob.Path), "paths do not match: %q != %q", filepath.Base(path), filepath.Base(treeJob.Path)) Assert(t, fsEntries == treeEntries, "wrong number of entries: %v != %v", fsEntries, treeEntries) } }