mirror of
https://github.com/vbatts/go-mtree.git
synced 2025-07-04 06:38:30 +00:00
compare: implement mtree.DirectoryHierarchy comparisons
This is part of a patchset that refactors all of the checking logic into comparison operations. Essentially, provide a Compare(...) function that allows for two different manifests to be compared. Extra and missing entries are supported in addition to the standard modified entry, and by implementing as a manifest comparison there is no double-scanning of the manifest source. The main annoyance is that we have to also include tar_time handling, which has not been abstracted inside keywords.go. This is a bit ugly right now, but works fine for the moment. Signed-off-by: Aleksa Sarai <asarai@suse.de>
This commit is contained in:
parent
36372dd3c8
commit
26ff922da6
3 changed files with 776 additions and 0 deletions
338
compare_test.go
Normal file
338
compare_test.go
Normal file
|
@ -0,0 +1,338 @@
|
|||
package mtree
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// simple walk of current directory, and imediately check it.
|
||||
// may not be parallelizable.
|
||||
func TestCompare(t *testing.T) {
|
||||
old, err := Walk(".", nil, append(DefaultKeywords, "sha1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
new, err := Walk(".", nil, append(DefaultKeywords, "sha1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diffs, err := Compare(old, new, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(diffs) > 0 {
|
||||
t.Errorf("%#v", diffs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareModified(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "test-compare-modified")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// Create a bunch of objects.
|
||||
tmpfile := filepath.Join(dir, "tmpfile")
|
||||
if err := ioutil.WriteFile(tmpfile, []byte("some content here"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tmpdir := filepath.Join(dir, "testdir")
|
||||
if err := os.Mkdir(tmpdir, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tmpsubfile := filepath.Join(tmpdir, "anotherfile")
|
||||
if err := ioutil.WriteFile(tmpsubfile, []byte("some different content"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Walk the current state.
|
||||
old, err := Walk(dir, nil, append(DefaultKeywords, "sha1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Overwrite the content in one of the files.
|
||||
if err := ioutil.WriteFile(tmpsubfile, []byte("modified content"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Walk the new state.
|
||||
new, err := Walk(dir, nil, append(DefaultKeywords, "sha1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Compare.
|
||||
diffs, err := Compare(old, new, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// 1 object
|
||||
if len(diffs) != 1 {
|
||||
t.Errorf("expected the diff length to be 1, got %d", len(diffs))
|
||||
for i, diff := range diffs {
|
||||
t.Logf("diff[%d] = %#v", i, diff)
|
||||
}
|
||||
}
|
||||
|
||||
// These cannot fail.
|
||||
tmpfile, _ = filepath.Rel(dir, tmpfile)
|
||||
tmpdir, _ = filepath.Rel(dir, tmpdir)
|
||||
tmpsubfile, _ = filepath.Rel(dir, tmpsubfile)
|
||||
|
||||
for _, diff := range diffs {
|
||||
switch diff.Path() {
|
||||
case tmpsubfile:
|
||||
if diff.Type() != Modified {
|
||||
t.Errorf("unexpected diff type for %s: %s", diff.Path(), diff.Type())
|
||||
}
|
||||
|
||||
if diff.Diff() == nil {
|
||||
t.Errorf("expect to not get nil for .Diff()")
|
||||
}
|
||||
|
||||
old := diff.Old()
|
||||
new := diff.New()
|
||||
if old == nil || new == nil {
|
||||
t.Errorf("expected to get (!nil, !nil) for (.Old, .New), got (%#v, %#v)", old, new)
|
||||
}
|
||||
default:
|
||||
t.Errorf("unexpected diff found: %#v", diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareMissing(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "test-compare-missing")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// Create a bunch of objects.
|
||||
tmpfile := filepath.Join(dir, "tmpfile")
|
||||
if err := ioutil.WriteFile(tmpfile, []byte("some content here"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tmpdir := filepath.Join(dir, "testdir")
|
||||
if err := os.Mkdir(tmpdir, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tmpsubfile := filepath.Join(tmpdir, "anotherfile")
|
||||
if err := ioutil.WriteFile(tmpsubfile, []byte("some different content"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Walk the current state.
|
||||
old, err := Walk(dir, nil, append(DefaultKeywords, "sha1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Delete the objects.
|
||||
if err := os.RemoveAll(tmpfile); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(tmpsubfile); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(tmpdir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Walk the new state.
|
||||
new, err := Walk(dir, nil, append(DefaultKeywords, "sha1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Compare.
|
||||
diffs, err := Compare(old, new, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// 3 objects + the changes to '.'
|
||||
if len(diffs) != 4 {
|
||||
t.Errorf("expected the diff length to be 4, got %d", len(diffs))
|
||||
for i, diff := range diffs {
|
||||
t.Logf("diff[%d] = %#v", i, diff)
|
||||
}
|
||||
}
|
||||
|
||||
// These cannot fail.
|
||||
tmpfile, _ = filepath.Rel(dir, tmpfile)
|
||||
tmpdir, _ = filepath.Rel(dir, tmpdir)
|
||||
tmpsubfile, _ = filepath.Rel(dir, tmpsubfile)
|
||||
|
||||
for _, diff := range diffs {
|
||||
switch diff.Path() {
|
||||
case ".":
|
||||
// ignore these changes
|
||||
case tmpfile, tmpdir, tmpsubfile:
|
||||
if diff.Type() != Missing {
|
||||
t.Errorf("unexpected diff type for %s: %s", diff.Path(), diff.Type())
|
||||
}
|
||||
|
||||
if diff.Diff() != nil {
|
||||
t.Errorf("expect to get nil for .Diff(), got %#v", diff.Diff())
|
||||
}
|
||||
|
||||
old := diff.Old()
|
||||
new := diff.New()
|
||||
if old == nil || new != nil {
|
||||
t.Errorf("expected to get (!nil, nil) for (.Old, .New), got (%#v, %#v)", old, new)
|
||||
}
|
||||
default:
|
||||
t.Errorf("unexpected diff found: %#v", diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareExtra(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "test-compare-extra")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// Walk the current state.
|
||||
old, err := Walk(dir, nil, append(DefaultKeywords, "sha1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Create a bunch of objects.
|
||||
tmpfile := filepath.Join(dir, "tmpfile")
|
||||
if err := ioutil.WriteFile(tmpfile, []byte("some content here"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tmpdir := filepath.Join(dir, "testdir")
|
||||
if err := os.Mkdir(tmpdir, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tmpsubfile := filepath.Join(tmpdir, "anotherfile")
|
||||
if err := ioutil.WriteFile(tmpsubfile, []byte("some different content"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Walk the new state.
|
||||
new, err := Walk(dir, nil, append(DefaultKeywords, "sha1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Compare.
|
||||
diffs, err := Compare(old, new, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// 3 objects + the changes to '.'
|
||||
if len(diffs) != 4 {
|
||||
t.Errorf("expected the diff length to be 4, got %d", len(diffs))
|
||||
for i, diff := range diffs {
|
||||
t.Logf("diff[%d] = %#v", i, diff)
|
||||
}
|
||||
}
|
||||
|
||||
// These cannot fail.
|
||||
tmpfile, _ = filepath.Rel(dir, tmpfile)
|
||||
tmpdir, _ = filepath.Rel(dir, tmpdir)
|
||||
tmpsubfile, _ = filepath.Rel(dir, tmpsubfile)
|
||||
|
||||
for _, diff := range diffs {
|
||||
switch diff.Path() {
|
||||
case ".":
|
||||
// ignore these changes
|
||||
case tmpfile, tmpdir, tmpsubfile:
|
||||
if diff.Type() != Extra {
|
||||
t.Errorf("unexpected diff type for %s: %s", diff.Path(), diff.Type())
|
||||
}
|
||||
|
||||
if diff.Diff() != nil {
|
||||
t.Errorf("expect to get nil for .Diff(), got %#v", diff.Diff())
|
||||
}
|
||||
|
||||
old := diff.Old()
|
||||
new := diff.New()
|
||||
if old != nil || new == nil {
|
||||
t.Errorf("expected to get (!nil, nil) for (.Old, .New), got (%#v, %#v)", old, new)
|
||||
}
|
||||
default:
|
||||
t.Errorf("unexpected diff found: %#v", diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareKeys(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "test-compare-keys")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// Create a bunch of objects.
|
||||
tmpfile := filepath.Join(dir, "tmpfile")
|
||||
if err := ioutil.WriteFile(tmpfile, []byte("some content here"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tmpdir := filepath.Join(dir, "testdir")
|
||||
if err := os.Mkdir(tmpdir, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tmpsubfile := filepath.Join(tmpdir, "anotherfile")
|
||||
if err := ioutil.WriteFile(tmpsubfile, []byte("aaa"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Walk the current state.
|
||||
old, err := Walk(dir, nil, append(DefaultKeywords, "sha1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Overwrite the content in one of the files, but without changing the size.
|
||||
if err := ioutil.WriteFile(tmpsubfile, []byte("bbb"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Walk the new state.
|
||||
new, err := Walk(dir, nil, append(DefaultKeywords, "sha1"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Compare.
|
||||
diffs, err := Compare(old, new, []string{"size"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// 0 objects
|
||||
if len(diffs) != 0 {
|
||||
t.Errorf("expected the diff length to be 0, got %d", len(diffs))
|
||||
for i, diff := range diffs {
|
||||
t.Logf("diff[%d] = %#v", i, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add test for Compare(...) between a tar and a regular dh (to make sure that tar_time is handled correctly).
|
Loading…
Add table
Add a link
Reference in a new issue