libgo: Update to Go 1.1.1.
[official-gcc.git] / libgo / go / archive / tar / writer_test.go
blob4cf7c72aff346ec04a77ed8d06244fa63f88820b
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package tar
7 import (
8 "bytes"
9 "fmt"
10 "io"
11 "io/ioutil"
12 "os"
13 "strings"
14 "testing"
15 "testing/iotest"
16 "time"
19 type writerTestEntry struct {
20 header *Header
21 contents string
24 type writerTest struct {
25 file string // filename of expected output
26 entries []*writerTestEntry
29 var writerTests = []*writerTest{
30 // The writer test file was produced with this command:
31 // tar (GNU tar) 1.26
32 // ln -s small.txt link.txt
33 // tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt
35 file: "testdata/writer.tar",
36 entries: []*writerTestEntry{
38 header: &Header{
39 Name: "small.txt",
40 Mode: 0640,
41 Uid: 73025,
42 Gid: 5000,
43 Size: 5,
44 ModTime: time.Unix(1246508266, 0),
45 Typeflag: '0',
46 Uname: "dsymonds",
47 Gname: "eng",
49 contents: "Kilts",
52 header: &Header{
53 Name: "small2.txt",
54 Mode: 0640,
55 Uid: 73025,
56 Gid: 5000,
57 Size: 11,
58 ModTime: time.Unix(1245217492, 0),
59 Typeflag: '0',
60 Uname: "dsymonds",
61 Gname: "eng",
63 contents: "Google.com\n",
66 header: &Header{
67 Name: "link.txt",
68 Mode: 0777,
69 Uid: 1000,
70 Gid: 1000,
71 Size: 0,
72 ModTime: time.Unix(1314603082, 0),
73 Typeflag: '2',
74 Linkname: "small.txt",
75 Uname: "strings",
76 Gname: "strings",
78 // no contents
82 // The truncated test file was produced using these commands:
83 // dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
84 // tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
86 file: "testdata/writer-big.tar",
87 entries: []*writerTestEntry{
89 header: &Header{
90 Name: "tmp/16gig.txt",
91 Mode: 0640,
92 Uid: 73025,
93 Gid: 5000,
94 Size: 16 << 30,
95 ModTime: time.Unix(1254699560, 0),
96 Typeflag: '0',
97 Uname: "dsymonds",
98 Gname: "eng",
100 // fake contents
101 contents: strings.Repeat("\x00", 4<<10),
105 // This file was produced using gnu tar 1.17
106 // gnutar -b 4 --format=ustar (longname/)*15 + file.txt
108 file: "testdata/ustar.tar",
109 entries: []*writerTestEntry{
111 header: &Header{
112 Name: strings.Repeat("longname/", 15) + "file.txt",
113 Mode: 0644,
114 Uid: 0765,
115 Gid: 024,
116 Size: 06,
117 ModTime: time.Unix(1360135598, 0),
118 Typeflag: '0',
119 Uname: "shane",
120 Gname: "staff",
122 contents: "hello\n",
128 // Render byte array in a two-character hexadecimal string, spaced for easy visual inspection.
129 func bytestr(offset int, b []byte) string {
130 const rowLen = 32
131 s := fmt.Sprintf("%04x ", offset)
132 for _, ch := range b {
133 switch {
134 case '0' <= ch && ch <= '9', 'A' <= ch && ch <= 'Z', 'a' <= ch && ch <= 'z':
135 s += fmt.Sprintf(" %c", ch)
136 default:
137 s += fmt.Sprintf(" %02x", ch)
140 return s
143 // Render a pseudo-diff between two blocks of bytes.
144 func bytediff(a []byte, b []byte) string {
145 const rowLen = 32
146 s := fmt.Sprintf("(%d bytes vs. %d bytes)\n", len(a), len(b))
147 for offset := 0; len(a)+len(b) > 0; offset += rowLen {
148 na, nb := rowLen, rowLen
149 if na > len(a) {
150 na = len(a)
152 if nb > len(b) {
153 nb = len(b)
155 sa := bytestr(offset, a[0:na])
156 sb := bytestr(offset, b[0:nb])
157 if sa != sb {
158 s += fmt.Sprintf("-%v\n+%v\n", sa, sb)
160 a = a[na:]
161 b = b[nb:]
163 return s
166 func TestWriter(t *testing.T) {
167 testLoop:
168 for i, test := range writerTests {
169 expected, err := ioutil.ReadFile(test.file)
170 if err != nil {
171 t.Errorf("test %d: Unexpected error: %v", i, err)
172 continue
175 buf := new(bytes.Buffer)
176 tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB
177 big := false
178 for j, entry := range test.entries {
179 big = big || entry.header.Size > 1<<10
180 if err := tw.WriteHeader(entry.header); err != nil {
181 t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err)
182 continue testLoop
184 if _, err := io.WriteString(tw, entry.contents); err != nil {
185 t.Errorf("test %d, entry %d: Failed writing contents: %v", i, j, err)
186 continue testLoop
189 // Only interested in Close failures for the small tests.
190 if err := tw.Close(); err != nil && !big {
191 t.Errorf("test %d: Failed closing archive: %v", i, err)
192 continue testLoop
195 actual := buf.Bytes()
196 if !bytes.Equal(expected, actual) {
197 t.Errorf("test %d: Incorrect result: (-=expected, +=actual)\n%v",
198 i, bytediff(expected, actual))
200 if testing.Short() { // The second test is expensive.
201 break
206 func TestPax(t *testing.T) {
207 // Create an archive with a large name
208 fileinfo, err := os.Stat("testdata/small.txt")
209 if err != nil {
210 t.Fatal(err)
212 hdr, err := FileInfoHeader(fileinfo, "")
213 if err != nil {
214 t.Fatalf("os.Stat: %v", err)
216 // Force a PAX long name to be written
217 longName := strings.Repeat("ab", 100)
218 contents := strings.Repeat(" ", int(hdr.Size))
219 hdr.Name = longName
220 var buf bytes.Buffer
221 writer := NewWriter(&buf)
222 if err := writer.WriteHeader(hdr); err != nil {
223 t.Fatal(err)
225 if _, err = writer.Write([]byte(contents)); err != nil {
226 t.Fatal(err)
228 if err := writer.Close(); err != nil {
229 t.Fatal(err)
231 // Simple test to make sure PAX extensions are in effect
232 if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
233 t.Fatal("Expected at least one PAX header to be written.")
235 // Test that we can get a long name back out of the archive.
236 reader := NewReader(&buf)
237 hdr, err = reader.Next()
238 if err != nil {
239 t.Fatal(err)
241 if hdr.Name != longName {
242 t.Fatal("Couldn't recover long file name")
246 func TestPAXHeader(t *testing.T) {
247 medName := strings.Repeat("CD", 50)
248 longName := strings.Repeat("AB", 100)
249 paxTests := [][2]string{
250 {"name=/etc/hosts", "19 name=/etc/hosts\n"},
251 {"a=b", "6 a=b\n"}, // Single digit length
252 {"a=names", "11 a=names\n"}, // Test case involving carries
253 {"name=" + longName, fmt.Sprintf("210 name=%s\n", longName)},
254 {"name=" + medName, fmt.Sprintf("110 name=%s\n", medName)}}
256 for _, test := range paxTests {
257 key, expected := test[0], test[1]
258 if result := paxHeader(key); result != expected {
259 t.Fatalf("paxHeader: got %s, expected %s", result, expected)