Browse code

pkg/archive: test that confirms hardlink ordering

This test was written against
master(abdfb21e3a761efdd70614de42905ff7911c5372) as a failing test, but
works with this patch set.

Signed-off-by: Vincent Batts <vbatts@redhat.com>

Vincent Batts authored on 2015/02/06 22:00:13
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,127 @@
0
+package archive
1
+
2
+import (
3
+	"archive/tar"
4
+	"fmt"
5
+	"io"
6
+	"io/ioutil"
7
+	"os"
8
+	"path"
9
+	"sort"
10
+	"testing"
11
+)
12
+
13
+func TestHardLinkOrder(t *testing.T) {
14
+	names := []string{"file1.txt", "file2.txt", "file3.txt"}
15
+	msg := []byte("Hey y'all")
16
+
17
+	// Create dir
18
+	src, err := ioutil.TempDir("", "docker-hardlink-test-src-")
19
+	if err != nil {
20
+		t.Fatal(err)
21
+	}
22
+	//defer os.RemoveAll(src)
23
+	for _, name := range names {
24
+		func() {
25
+			fh, err := os.Create(path.Join(src, name))
26
+			if err != nil {
27
+				t.Fatal(err)
28
+			}
29
+			defer fh.Close()
30
+			if _, err = fh.Write(msg); err != nil {
31
+				t.Fatal(err)
32
+			}
33
+		}()
34
+	}
35
+	// Create dest, with changes that includes hardlinks
36
+	dest, err := ioutil.TempDir("", "docker-hardlink-test-dest-")
37
+	if err != nil {
38
+		t.Fatal(err)
39
+	}
40
+	os.RemoveAll(dest) // we just want the name, at first
41
+	if err := copyDir(src, dest); err != nil {
42
+		t.Fatal(err)
43
+	}
44
+	defer os.RemoveAll(dest)
45
+	for _, name := range names {
46
+		for i := 0; i < 5; i++ {
47
+			if err := os.Link(path.Join(dest, name), path.Join(dest, fmt.Sprintf("%s.link%d", name, i))); err != nil {
48
+				t.Fatal(err)
49
+			}
50
+		}
51
+	}
52
+
53
+	// get changes
54
+	changes, err := ChangesDirs(dest, src)
55
+	if err != nil {
56
+		t.Fatal(err)
57
+	}
58
+
59
+	// sort
60
+	sort.Sort(changesByPath(changes))
61
+
62
+	// ExportChanges
63
+	ar, err := ExportChanges(dest, changes)
64
+	if err != nil {
65
+		t.Fatal(err)
66
+	}
67
+	hdrs, err := walkHeaders(ar)
68
+	if err != nil {
69
+		t.Fatal(err)
70
+	}
71
+
72
+	// reverse sort
73
+	sort.Sort(sort.Reverse(changesByPath(changes)))
74
+	// ExportChanges
75
+	arRev, err := ExportChanges(dest, changes)
76
+	if err != nil {
77
+		t.Fatal(err)
78
+	}
79
+	hdrsRev, err := walkHeaders(arRev)
80
+	if err != nil {
81
+		t.Fatal(err)
82
+	}
83
+
84
+	// line up the two sets
85
+	sort.Sort(tarHeaders(hdrs))
86
+	sort.Sort(tarHeaders(hdrsRev))
87
+
88
+	// compare Size and LinkName
89
+	for i := range hdrs {
90
+		if hdrs[i].Name != hdrsRev[i].Name {
91
+			t.Errorf("headers - expected name %q; but got %q", hdrs[i].Name, hdrsRev[i].Name)
92
+		}
93
+		if hdrs[i].Size != hdrsRev[i].Size {
94
+			t.Errorf("headers - %q expected size %d; but got %d", hdrs[i].Name, hdrs[i].Size, hdrsRev[i].Size)
95
+		}
96
+		if hdrs[i].Typeflag != hdrsRev[i].Typeflag {
97
+			t.Errorf("headers - %q expected type %d; but got %d", hdrs[i].Name, hdrs[i].Typeflag, hdrsRev[i].Typeflag)
98
+		}
99
+		if hdrs[i].Linkname != hdrsRev[i].Linkname {
100
+			t.Errorf("headers - %q expected linkname %q; but got %q", hdrs[i].Name, hdrs[i].Linkname, hdrsRev[i].Linkname)
101
+		}
102
+	}
103
+
104
+}
105
+
106
+type tarHeaders []tar.Header
107
+
108
+func (th tarHeaders) Len() int           { return len(th) }
109
+func (th tarHeaders) Swap(i, j int)      { th[j], th[i] = th[i], th[j] }
110
+func (th tarHeaders) Less(i, j int) bool { return th[i].Name < th[j].Name }
111
+
112
+func walkHeaders(r io.Reader) ([]tar.Header, error) {
113
+	t := tar.NewReader(r)
114
+	headers := []tar.Header{}
115
+	for {
116
+		hdr, err := t.Next()
117
+		if err != nil {
118
+			if err == io.EOF {
119
+				break
120
+			}
121
+			return headers, err
122
+		}
123
+		headers = append(headers, *hdr)
124
+	}
125
+	return headers, nil
126
+}