func DoTestPatchRenameFileSameDir(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("baz", tg.B(42, 65537))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) assert.Equal(t, 1, len(patchPlan.Cmds)) rename, isRename := patchPlan.Cmds[0].(*Transfer) assert.T(t, isRename) assert.T(t, strings.HasSuffix(rename.From.Resolve(), filepath.Join("foo", "baz"))) assert.T(t, strings.HasSuffix(rename.To.Resolve(), filepath.Join("foo", "bar"))) }
func DoTestPatchDepConflict(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("gloo", tg.F("bloo", tg.B(99, 8192), tg.B(100, 10000)), tg.D("groo", tg.D("snoo", tg.F("bar", tg.B(42, 65537)))))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("gloo", tg.B(99, 10000))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) assertNoRelocs(t, dstpath) }
func TestPatchPreserveKeeps(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(6806, 65536)), tg.F("blop", tg.B(6806, 65536))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("baz", tg.B(6806, 65536)), tg.F("blop", tg.B(6806, 65536))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) info, err := os.Stat(filepath.Join(dstpath, "foo", "bar")) assert.T(t, err == nil && info != nil) info, err = os.Stat(filepath.Join(dstpath, "foo", "blop")) assert.T(t, err == nil && info != nil) }
func DoTestPatchAdd(t *testing.T, mkrepo repoMaker) { tg := treegen.New() files := []treegen.Generated{} for i := 0; i < 10; i++ { files = append(files, tg.F("", tg.B(int64(42*i), int64(500000*i)))) } treeSpec := tg.D("foo", tg.D("bar", files...)) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(filepath.Join(srcpath, "foo"), srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.D("bar"), tg.D("baz")) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(filepath.Join(dstpath, "foo"), dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) for _, cmd := range patchPlan.Cmds { _, isSfd := cmd.(*SrcFileDownload) assert.T(t, isSfd) } }
// Test the matcher on a case where the source file has the same // prefix as destination, but has been appended to. func TestMatchAppend(t *testing.T) { tg := treegen.New() treeSpec := tg.F("bar", tg.B(42, 65537), tg.B(43, 65537)) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) // Try indexing root dir as a file srcFile, err := fs.IndexFile(srcpath) assert.Tf(t, err != nil, "%v", err) // Ok, for real this time srcFile, err = fs.IndexFile(filepath.Join(srcpath, "bar")) assert.Tf(t, err == nil, "%v", err) assert.Equal(t, 17, len(srcFile.Blocks)) tg = treegen.New() treeSpec = tg.F("bar", tg.B(42, 65537)) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstFile, err := fs.IndexFile(filepath.Join(dstpath, "bar")) assert.Equal(t, 9, len(dstFile.Blocks)) match, err := MatchFile(srcFile, filepath.Join(dstpath, "bar")) assert.T(t, err == nil, "%v", err) assert.Equal(t, 8, len(match.BlockMatches)) notMatched := match.NotMatched() assert.Equal(t, 1, len(notMatched)) assert.Equal(t, int64(65536), notMatched[0].From) assert.Equal(t, int64(65537+65537), notMatched[0].To) }
func TestPatchRenameScope(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(6806, 65536)), tg.F("baz", tg.B(6806, 65536))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("baz", tg.B(6806, 65536)), tg.F("blop", tg.B(6806, 65536))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) srcDir, err := fs.IndexDir(srcpath) assert.T(t, err == nil) dstDir, err := fs.IndexDir(dstpath) assert.T(t, err == nil) assert.Equal(t, srcDir.Strong(), dstDir.Strong()) }
func DoTestPatchFileAppend(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537), tg.B(43, 65537))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("bar", tg.B(42, 65537))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) complete := false for i, cmd := range patchPlan.Cmds { switch { case i == 0: localTemp, isTemp := cmd.(*LocalTemp) assert.T(t, isTemp) assert.Equal(t, filepath.Join(dstpath, "foo", "bar"), localTemp.Path.Resolve()) case i >= 1 && i <= 8: ltc, isLtc := cmd.(*LocalTempCopy) assert.Tf(t, isLtc, "cmd %d", i) assert.Equal(t, ltc.LocalOffset, ltc.TempOffset) assert.Equal(t, int64(fs.BLOCKSIZE), ltc.Length) assert.Equal(t, int64(0), ltc.LocalOffset%int64(fs.BLOCKSIZE)) case i == 9: stc, isStc := cmd.(*SrcTempCopy) assert.T(t, isStc) assert.Equal(t, int64(65538), stc.Length) case i == 10: _, isRwt := cmd.(*ReplaceWithTemp) assert.T(t, isRwt) complete = true case i > 10: t.Fatalf("too many commands") } } assert.T(t, complete, "missing expected number of commands") failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) srcRoot, errors := fs.IndexDir(srcpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) dstRoot, errors := fs.IndexDir(dstpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) assert.Equal(t, srcRoot.Info().Strong, dstRoot.Info().Strong) }
func TestClean(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("bar", tg.D("aleph", tg.F("A", tg.B(42, 65537)), tg.F("a", tg.B(42, 65537))))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.D("bar", tg.D("aleph", tg.F("A", tg.B(42, 65537)), tg.F("a", tg.B(42, 65537))), tg.D("beth", tg.F("B", tg.B(43, 65537)), tg.F("b", tg.B(43, 65537))), tg.D("jimmy", tg.F("G", tg.B(44, 65537)), tg.F("g", tg.B(44, 65537)))), tg.D("baz", tg.D("uno", tg.F("1", tg.B(1, 65537)), tg.F("I", tg.B(1, 65537))), tg.D("dos", tg.F("2", tg.B(11, 65537)), tg.F("II", tg.B(11, 65537))), tg.D("tres", tg.F("3", tg.B(111, 65537)), tg.F("III", tg.B(111, 65537))))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) onePath := dstStore.Resolve(filepath.Join("foo", "baz", "uno", "1")) _, err = os.Stat(onePath) assert.Tf(t, err == nil, "%v", err) patchPlan := NewPatchPlan(srcStore, dstStore) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil, "%v", failedCmd) assert.Tf(t, err == nil, "%v", err) errors := make(chan error, 10) patchPlan.Clean(errors) close(errors) for err := range errors { assert.Tf(t, err == nil, "%v", err) } onePath = dstStore.Resolve(filepath.Join("foo", "baz", "uno", "1")) _, err = os.Stat(onePath) assert.Tf(t, err != nil, "%v", err) }
func DoTestSetModeNew(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("bar", tg.D("aleph", tg.F("A", tg.B(42, 65537)), tg.F("a", tg.B(42, 65537))))) srcpath := treegen.TestTree(t, treeSpec) os.Chmod(filepath.Join(srcpath, "foo", "bar", "aleph", "A"), 0765) os.Chmod(filepath.Join(srcpath, "foo", "bar"), 0711) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo") dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil, "%v", failedCmd) assert.Tf(t, err == nil, "%v", err) errors := make(chan os.Error) go func() { patchPlan.Clean(errors) close(errors) }() for err := range errors { assert.Tf(t, err == nil, "%v", err) } errors = make(chan os.Error) go func() { patchPlan.SetMode(errors) close(errors) }() for err := range errors { assert.Tf(t, err == nil, "%v", err) } fileinfo, err := os.Stat(filepath.Join(dstpath, "foo", "bar", "aleph", "A")) assert.T(t, fileinfo != nil) assert.Equal(t, uint32(0765), fileinfo.Permission()) fileinfo, err = os.Stat(filepath.Join(dstpath, "foo", "bar")) assert.T(t, fileinfo != nil) assert.Equal(t, uint32(0711), fileinfo.Permission()) }
func DoTestPatchRelocConflict(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("gloo", tg.F("bloo", tg.B(99, 99)), tg.D("groo", tg.D("snoo", tg.F("bar", tg.B(42, 65537)))))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("gloo", tg.B(99, 99))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) assert.Equal(t, 3, len(patchPlan.Cmds)) for i, cmd := range patchPlan.Cmds { switch i { case 0: conflict, is := cmd.(*Conflict) assert.T(t, is) assert.T(t, strings.HasSuffix(conflict.Path.RelPath, filepath.Join("foo", "gloo"))) case 1: copy, is := cmd.(*Transfer) assert.T(t, is) assert.T(t, strings.HasSuffix(copy.From.Resolve(), filepath.Join("foo", "gloo"))) assert.T(t, strings.HasSuffix(copy.To.Resolve(), filepath.Join("foo", "gloo", "bloo"))) case 2: copy, is := cmd.(*SrcFileDownload) assert.T(t, is) assert.Equal(t, "764b5f659f70e69d4a87fe6ed138af40be36c514", copy.SrcFile.Info().Strong) } } failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) assertNoRelocs(t, dstpath) }
func DoTestPatchRenameScope(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(6806, 65536)), tg.F("baz", tg.B(6806, 65536))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("baz", tg.B(6806, 65536)), tg.F("blop", tg.B(6806, 65536))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) // The actual content of dst after the patch depends on // which file the repo chooses when matching foo/bar // to baz or blop in dst. // // If blop matches, it will get renamed to bar and the trees will // become identical. However if baz matches, blop will be left in place. srcDir, errors := fs.IndexDir(srcpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) dstDir, errors := fs.IndexDir(dstpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) for _, path := range []string{"foo/bar", "foo/baz"} { srcNode, has := fs.Lookup(srcDir, path) assert.T(t, has) dstNode, has := fs.Lookup(dstDir, path) assert.T(t, has) assert.Equal(t, srcNode.(fs.File).Info().Strong, dstNode.(fs.File).Info().Strong) } }
// Test the patch planner on a case where the source file is a shorter, // truncated version of the destination. // Execute the patch plan and check both resulting trees are identical. func TestPatchFileTruncate(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("bar", tg.B(42, 65537), tg.B(43, 65537))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) complete := false for i, cmd := range patchPlan.Cmds { switch { case i == 0: localTemp, isTemp := cmd.(*LocalTemp) assert.T(t, isTemp) assert.Equal(t, filepath.Join(dstpath, "foo", "bar"), localTemp.Path.Resolve()) case i >= 1 && i <= 8: ltc, isLtc := cmd.(*LocalTempCopy) assert.Tf(t, isLtc, "cmd %d", i) assert.Equal(t, ltc.LocalOffset, ltc.TempOffset) assert.Equal(t, int64(fs.BLOCKSIZE), ltc.Length) assert.Equal(t, int64(0), ltc.LocalOffset%int64(fs.BLOCKSIZE)) case i == 9: stc, isStc := cmd.(*SrcTempCopy) assert.T(t, isStc) assert.Equal(t, int64(1), stc.Length) complete = true case i > 10: t.Fatalf("too many commands") } } assert.T(t, complete, "missing expected number of commands") failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) srcRoot, _ := fs.IndexDir(srcpath) dstRoot, _ := fs.IndexDir(dstpath) assert.Equal(t, srcRoot.Strong(), dstRoot.Strong()) }
func DoTestStoreRelPath(t *testing.T, repo fs.NodeRepo) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) store, err := fs.NewLocalStore(path, repo) assert.T(t, err == nil) relFoo := store.RelPath(filepath.Join(path, "foo")) assert.Equalf(t, "foo", relFoo, "'%v': not a foo", relFoo) // Relocate bar newBar, err := store.Relocate(filepath.Join(filepath.Join(path, "foo"), "bar")) assert.T(t, err == nil) // new bar's parent should still be foo newBarParent, _ := filepath.Split(newBar) newBarParent = strings.TrimRight(newBarParent, "/\\") // old bar should not exist _, err = os.Stat(filepath.Join(filepath.Join(path, "foo"), "bar")) assert.T(t, err != nil) foobar := filepath.Join("foo", "bar") assert.Equal(t, newBar, store.Resolve(foobar), "reloc path %s != resolve foo/bar %s", newBar, store.Resolve(foobar)) }
func DoTestDirDescent(t *testing.T, repo fs.NodeRepo) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("baobab", tg.B(91, 65537)), tg.D("bar", tg.D("aleph", tg.F("a", tg.B(42, 65537)))), tg.F("bar3003", tg.B(777, 65537))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) dir, errors := fs.IndexDir(path, repo) assert.Equalf(t, 0, len(errors), "%v", errors) for _, fpath := range []string{ filepath.Join("foo", "baobab"), filepath.Join("foo", "bar", "aleph", "a"), filepath.Join("foo", "bar3003")} { node, found := fs.Lookup(dir, fpath) assert.Tf(t, found, "not found: %s", fpath) _, isFile := node.(fs.File) assert.T(t, isFile) } node, found := fs.Lookup(dir, filepath.Join("foo", "bar")) assert.T(t, found) _, isDir := node.(fs.Dir) assert.T(t, isDir) }
func TestDirDescent(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("baobab", tg.B(91, 65537)), tg.D("bar", tg.D("aleph", tg.F("a", tg.B(42, 65537)))), tg.F("bar3003", tg.B(777, 65537))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) dir, err := IndexDir(path) assert.T(t, err == nil) for _, fpath := range []string{ filepath.Join("foo", "baobab"), filepath.Join("foo", "bar", "aleph", "a"), filepath.Join("foo", "bar3003")} { node, found := dir.Resolve(fpath) assert.Tf(t, found, "not found: %s", fpath) _, isFile := node.(*File) assert.T(t, isFile) } node, found := dir.Resolve(filepath.Join("foo", "bar")) assert.T(t, found) _, isDir := node.(*Dir) assert.T(t, isDir) }
func DoTestPatchIdentity(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) assert.Equal(t, "1b1979b8746948cedc81488e92d1ad715e38bbfc", srcStore.Repo().Root().(fs.Dir).Info().Strong) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) assert.Equal(t, "1b1979b8746948cedc81488e92d1ad715e38bbfc", dstStore.Repo().Root().(fs.Dir).Info().Strong) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) assert.T(t, len(patchPlan.Cmds) > 0) for i := 0; i < len(patchPlan.Cmds); i++ { keep := patchPlan.Cmds[0].(*Keep) assert.T(t, strings.HasPrefix(dstpath, keep.Path.Resolve())) } }
func TestPostOrder(t *testing.T) { tg := treegen.New() treeSpec := tg.D("F", tg.D("B", tg.F("A", tg.B(1, 100)), tg.D("D", tg.F("C", tg.B(2, 100)), tg.F("E", tg.B(3, 100)))), tg.D("G", tg.D("I", tg.F("H", tg.B(4, 100))))) root := treegen.TestTree(t, treeSpec) visitor := &postVisitor{order: []string{}} PostOrderWalk(root, visitor, nil) /* for _, s := range visitor.order { log.Printf("%v", s) } */ expect := []string{"/C", "/E", "/D", "/A", "/B", "/H", "/I", "/G", "/F"} for i := 0; i < len(expect); i++ { assert.Tf(t, strings.HasSuffix(visitor.order[i], expect[i]), "%v did not have expected suffix %s", visitor.order[i], expect[i]) } }
// Test patch planner on case where the source and // destination have a direct conflict in structure. // A path in the source is a directory, path in destination // already contains a file at that location. func TestPatchSimpleDirFileConflict(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("gloo", tg.F("bloo", tg.B(99, 99)), tg.D("groo", tg.D("snoo", tg.F("bar", tg.B(42, 65537)))))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("gloo", tg.B(99, 999))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) assert.Equal(t, 3, len(patchPlan.Cmds)) for i, cmd := range patchPlan.Cmds { switch i { case 0: conflict, is := cmd.(*Conflict) assert.T(t, is) assert.T(t, strings.HasSuffix(conflict.Path.RelPath, filepath.Join("foo", "gloo"))) case 1: copy, is := cmd.(*SrcFileDownload) assert.T(t, is) assert.Equal(t, "beced72da0cf22301e23bdccec61bf9763effd6f", copy.SrcFile.Strong()) case 2: copy, is := cmd.(*SrcFileDownload) assert.T(t, is) assert.Equal(t, "764b5f659f70e69d4a87fe6ed138af40be36c514", copy.SrcFile.Strong()) } } }
func DoTestPatchWeakCollision(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(6806, 65536))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("bar", tg.B(9869, 65536))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) // Src and dst blocks have same weak checksum assert.Equal(t, (srcStore.Repo().Root().(fs.Dir)).SubDirs()[0].Files()[0].Blocks()[0].Info().Weak, (dstStore.Repo().Root().(fs.Dir)).SubDirs()[0].Files()[0].Blocks()[0].Info().Weak) // Src and dst blocks have different strong checksum srcRoot := srcStore.Repo().Root().(fs.Dir) dstRoot := dstStore.Repo().Root().(fs.Dir) assert.Tf(t, srcRoot.Info().Strong != dstRoot.Info().Strong, "wtf: %v == %v", srcRoot.Info().Strong, dstRoot.Info().Strong) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) srcDir, errors := fs.IndexDir(srcpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) dstDir, errors := fs.IndexDir(dstpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) assert.Equal(t, srcDir.Info().Strong, dstDir.Info().Strong) }
func DoTestPatchRenameFileDifferentDir(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("gloo", tg.F("bloo", tg.B(99, 99)), tg.D("groo", tg.D("snoo", tg.F("bar", tg.B(42, 65537)))))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("pancake", tg.F("butter", tg.B(42, 65537)), tg.F("syrup", tg.B(99, 99))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) assert.Equal(t, 2, len(patchPlan.Cmds)) for i := 0; i < len(patchPlan.Cmds); i++ { _, isRename := patchPlan.Cmds[0].(*Transfer) assert.T(t, isRename) } // Now flip patchPlan = NewPatchPlan(dstStore, srcStore) assert.Equal(t, 2, len(patchPlan.Cmds)) for i := 0; i < len(patchPlan.Cmds); i++ { _, isRename := patchPlan.Cmds[0].(*Transfer) assert.T(t, isRename) } }
func DoTestParentRefs(t *testing.T, repo fs.NodeRepo) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("bar", tg.D("aleph", tg.F("A", tg.B(42, 65537)), tg.F("a", tg.B(42, 65537))), tg.D("beth", tg.F("B", tg.B(43, 65537)), tg.F("b", tg.B(43, 65537))), tg.D("jimmy", tg.F("G", tg.B(44, 65537)), tg.F("g", tg.B(44, 65537)))), tg.D("baz", tg.D("uno", tg.F("1", tg.B(1, 65537)), tg.F("I", tg.B(1, 65537))), tg.D("dos", tg.F("2", tg.B(11, 65537)), tg.F("II", tg.B(11, 65537))), tg.D("tres", tg.F("3", tg.B(111, 65537)), tg.F("III", tg.B(111, 65537))))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) foo, errors := fs.IndexDir(filepath.Join(path, "foo"), repo) assert.Equalf(t, 0, len(errors), "%v", errors) rootCount := 0 fs.Walk(foo, func(node fs.Node) bool { switch node.(type) { case fs.Dir: dir := node.(fs.Dir) if _, hasParent := dir.Parent(); !hasParent { rootCount++ } break case fs.File: file := node.(fs.File) _, hasParent := file.Parent() assert.Tf(t, hasParent, "%v is root?!", file.Info()) break case fs.Block: block := node.(fs.Block) _, hasParent := block.Parent() assert.Tf(t, hasParent, "%v is root?!", block.Info()) break } return true }) assert.Equal(t, 1, rootCount) }
func TestPatchWeakCollision(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(6806, 65536))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("bar", tg.B(9869, 65536))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) // Src and dst blocks have same weak checksum assert.Equal(t, srcStore.Root().SubDirs[0].Files[0].Blocks[0].Weak(), dstStore.Root().SubDirs[0].Files[0].Blocks[0].Weak()) // Src and dst blocks have different strong checksum assert.Tf(t, srcStore.Root().Strong() != dstStore.Root().Strong(), "wtf: %v == %v", srcStore.Root().Strong(), dstStore.Root().Strong()) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) srcDir, err := fs.IndexDir(srcpath) assert.T(t, err == nil) dstDir, err := fs.IndexDir(dstpath) assert.T(t, err == nil) assert.Equal(t, srcDir.Strong(), dstDir.Strong()) }
func TestRootWorks(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) dbrepo, err := NewDbRepo(":memory:") assert.T(t, err == nil) _, errors := fs.IndexDir(filepath.Join(path, "foo"), dbrepo) assert.Equalf(t, 0, len(errors), "%v", errors) }
func TestGobbable(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("bar", tg.D("aleph", tg.F("A", tg.B(42, 65537)), tg.F("a", tg.B(42, 65537))), tg.D("beth", tg.F("B", tg.B(43, 65537)), tg.F("b", tg.B(43, 65537))), tg.D("jimmy", tg.F("G", tg.B(44, 65537)), tg.F("g", tg.B(44, 65537)))), tg.D("baz", tg.D("uno", tg.F("1", tg.B(1, 65537)), tg.F("I", tg.B(1, 65537))), tg.D("dos", tg.F("2", tg.B(11, 65537)), tg.F("II", tg.B(11, 65537))), tg.D("tres", tg.F("3", tg.B(111, 65537)), tg.F("III", tg.B(111, 65537))))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) foo, err := IndexDir(filepath.Join(path, "foo")) assert.Tf(t, err == nil, "%v", err) node, found := foo.Resolve(filepath.Join("bar", "aleph", "A")) assert.Equal(t, filepath.Join("bar", "aleph", "A"), RelPath(node)) bufferEnc := bytes.NewBuffer([]byte{}) encoder := gob.NewEncoder(bufferEnc) err = encoder.Encode(foo) assert.Tf(t, err == nil, "%v", err) bufferDec := bytes.NewBuffer(bufferEnc.Bytes()) decoder := gob.NewDecoder(bufferDec) decFoo := &Dir{} err = decoder.Decode(decFoo) assert.Tf(t, err == nil, "%v", err) node, found = decFoo.Resolve(filepath.Join("bar", "aleph", "A")) assert.T(t, found) _, isFile := node.(*File) assert.T(t, isFile) assert.T(t, node.Parent() != nil) assert.Equal(t, filepath.Join("bar", "aleph", "A"), RelPath(node)) }
func TestDirResolve(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("bar", tg.D("aleph", tg.F("A", tg.B(42, 65537)), tg.F("a", tg.B(42, 65537))), tg.D("beth", tg.F("B", tg.B(43, 65537)), tg.F("b", tg.B(43, 65537))), tg.D("jimmy", tg.F("G", tg.B(44, 65537)), tg.F("g", tg.B(44, 65537)))), tg.D("baz", tg.D("uno", tg.F("1", tg.B(1, 65537)), tg.F("I", tg.B(1, 65537))), tg.D("dos", tg.F("2", tg.B(11, 65537)), tg.F("II", tg.B(11, 65537))), tg.D("tres", tg.F("3", tg.B(111, 65537)), tg.F("III", tg.B(111, 65537))))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) foo, err := IndexDir(filepath.Join(path, "foo")) assert.Tf(t, err == nil, "%v", err) var node FsNode var found bool bar, exists := foo.Item("bar") assert.T(t, exists) barDir, isDir := bar.(*Dir) assert.T(t, isDir, "barDir = %v", barDir) node, found = foo.Resolve("bar") assert.T(t, found) _, isDir = node.(*Dir) assert.T(t, isDir) node, found = foo.Resolve(filepath.Join("bar", "aleph")) assert.T(t, found) _, isDir = node.(*Dir) assert.T(t, isDir) node, found = foo.Resolve(filepath.Join("bar", "aleph", "A")) assert.T(t, found) _, isFile := node.(*File) assert.T(t, isFile) }
func DoTestDirResolve(t *testing.T, repo fs.NodeRepo) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("bar", tg.D("aleph", tg.F("A", tg.B(42, 65537)), tg.F("a", tg.B(42, 65537))), tg.D("beth", tg.F("B", tg.B(43, 65537)), tg.F("b", tg.B(43, 65537))), tg.D("jimmy", tg.F("G", tg.B(44, 65537)), tg.F("g", tg.B(44, 65537)))), tg.D("baz", tg.D("uno", tg.F("1", tg.B(1, 65537)), tg.F("I", tg.B(1, 65537))), tg.D("dos", tg.F("2", tg.B(11, 65537)), tg.F("II", tg.B(11, 65537))), tg.D("tres", tg.F("3", tg.B(111, 65537)), tg.F("III", tg.B(111, 65537))))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) foo, errors := fs.IndexDir(filepath.Join(path, "foo"), repo) assert.Equalf(t, 0, len(errors), "%v", errors) var node fs.FsNode var found bool node, found = fs.Lookup(foo, "bar") assert.T(t, found) _, isDir := node.(fs.Dir) assert.T(t, isDir) node, found = fs.Lookup(foo, filepath.Join("bar", "aleph")) assert.T(t, found) _, isDir = node.(fs.Dir) assert.T(t, isDir) node, found = fs.Lookup(foo, filepath.Join("bar", "aleph", "A")) assert.T(t, found) _, isFile := node.(fs.File) assert.T(t, isFile) }
func DoTestNodeRelPath(t *testing.T, repo fs.NodeRepo) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) dir, errors := fs.IndexDir(path, repo) assert.Equalf(t, 0, len(errors), "%v", errors) assert.Equal(t, "", fs.RelPath(dir)) assert.Equal(t, "foo", fs.RelPath(dir.SubDirs()[0])) assert.Equal(t, filepath.Join("foo", "bar"), fs.RelPath(dir.SubDirs()[0].Files()[0])) assert.Equal(t, filepath.Join("foo", "bar"), fs.RelPath(dir.SubDirs()[0].Files()[0])) }
func TestNodeRelPath(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) dir, err := IndexDir(path) assert.T(t, err == nil) assert.Equal(t, "", RelPath(dir)) assert.Equal(t, "foo", RelPath(dir.SubDirs[0])) assert.Equal(t, filepath.Join("foo", "bar"), RelPath(dir.SubDirs[0].Files[0])) assert.Equal(t, filepath.Join("foo", "bar"), RelPath(dir.SubDirs[0].Files[0])) }
func TestDbRepo(t *testing.T) { dbrepo, dbpath := createDbRepo(t) log.SetFlags(log.LstdFlags | log.Lshortfile) defer os.Remove(dbpath) defer dbrepo.Close() tg := treegen.New() treeSpec := tg.D("foo", tg.D("bar", tg.D("aleph", tg.F("A", tg.B(42, 65537)), tg.F("a", tg.B(42, 65537))), tg.D("beth", tg.F("B", tg.B(43, 65537)), tg.F("b", tg.B(43, 65537))), tg.D("jimmy", tg.F("G", tg.B(44, 65537)), tg.F("g", tg.B(44, 65537)))), tg.D("baz", tg.D("uno", tg.F("1", tg.B(1, 65537)), tg.F("I", tg.B(1, 65537))), tg.D("dos", tg.F("2", tg.B(11, 65537)), tg.F("II", tg.B(11, 65537))), tg.D("tres", tg.F("3", tg.B(111, 65537)), tg.F("III", tg.B(111, 65537))))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) foo, errors := fs.IndexDir(filepath.Join(path, "foo"), dbrepo) assert.Equalf(t, 0, len(errors), "%v", errors) dbmemrepo, err := NewDbRepo(":memory:") assert.T(t, err == nil) memfoo, errors := fs.IndexDir(filepath.Join(path, "foo"), dbmemrepo) assert.Equalf(t, 0, len(errors), "%v", errors) assert.Equal(t, foo.Info().Strong, memfoo.Info().Strong) }
// Test the patch planner on two identical directory structures. func TestPatchIdentity(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) assert.T(t, len(patchPlan.Cmds) > 0) for i := 0; i < len(patchPlan.Cmds); i++ { keep := patchPlan.Cmds[0].(*Keep) assert.T(t, strings.HasPrefix(dstpath, keep.Path.Resolve())) } }