Пример #1
0
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)
}
Пример #2
0
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())
}
Пример #3
0
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)
	}
}
Пример #4
0
// 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())
}
Пример #5
0
func DoTestVisitBlocks(t *testing.T, repo fs.NodeRepo) {
	dir, errors := fs.IndexDir("../../testroot/", repo)
	assert.T(t, dir != nil)
	assert.Equalf(t, 0, len(errors), "%v", errors)

	collect := []fs.Block{}

	fs.Walk(dir, func(node fs.Node) bool {
		b, ok := node.(fs.Block)
		if ok {
			collect = append(collect, b)
		}

		return true
	})

	matched := false
	for _, block := range collect {
		if block.Info().Strong == "d1f11a93449fa4d3f320234743204ce157bbf1f3" {
			matched = true
		}
	}

	assert.Tf(t, matched, "Failed to find expected block")
}
Пример #6
0
func DoTestVisitDirsOnly(t *testing.T, repo fs.NodeRepo) {
	dir, errors := fs.IndexDir("../../testroot/", repo)
	assert.T(t, dir != nil)
	assert.Equalf(t, 0, len(errors), "%v", errors)

	collect := []fs.Dir{}
	visited := []fs.Node{}

	fs.Walk(dir, func(node fs.Node) bool {
		visited = append(visited, node)

		d, ok := node.(fs.Dir)
		if ok {
			collect = append(collect, d)
			return true
		}

		_, ok = node.(fs.File)
		if ok {
			return false
		}

		t.Errorf("Unexpected type during visit: %v", node)
		return true
	})

	assert.Equalf(t, 3, len(collect), "Unexpected dirs in testroot/: %v", collect)

	for _, node := range visited {
		_, ok := node.(fs.Block)
		if ok {
			t.Fatalf("Should not have gotten a block, we told visitor to stop at file level.")
		}
	}
}
Пример #7
0
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)
}
Пример #8
0
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)
}
Пример #9
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)
}
Пример #10
0
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)
}
Пример #11
0
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())
}
Пример #12
0
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)
}
Пример #13
0
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)
}
Пример #14
0
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]))
}
Пример #15
0
func DoTestDirIndex(t *testing.T, repo fs.NodeRepo) {
	dir, errors := fs.IndexDir("../../testroot", repo)
	assert.T(t, dir != nil)
	assert.Equalf(t, 0, len(errors), "%v", errors)

	assert.Equal(t, 2, len(dir.SubDirs()))
	assert.Equal(t, 4, len(dir.Files()))

	assert.Equal(t, "feab33f9685531a1c1c9c22d5d8af98267ca9426", dir.Info().Strong)

	var myMusic fs.Dir = dir.SubDirs()[0]
	assert.Equal(t, "My Music", myMusic.Name())

	for i := 0; i < 2; i++ {
		var mp4file fs.FsNode = myMusic.Files()[i]
		assert.Tf(t, strings.HasPrefix(mp4file.Name(), "0 10k 30"),
			"Unexpected d -> d -> f name: %s", mp4file.Name())
	}
}