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.
19
type writerTestEntry struct {
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:
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{
44
ModTime: time.Unix(1246508266, 0),
58
ModTime: time.Unix(1245217492, 0),
63
contents: "Google.com\n",
72
ModTime: time.Unix(1314603082, 0),
74
Linkname: "small.txt",
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{
90
Name: "tmp/16gig.txt",
95
ModTime: time.Unix(1254699560, 0),
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{
112
Name: strings.Repeat("longname/", 15) + "file.txt",
117
ModTime: time.Unix(1360135598, 0),
128
// Render byte array in a two-character hexadecimal string, spaced for easy visual inspection.
129
func bytestr(offset int, b []byte) string {
131
s := fmt.Sprintf("%04x ", offset)
132
for _, ch := range b {
134
case '0' <= ch && ch <= '9', 'A' <= ch && ch <= 'Z', 'a' <= ch && ch <= 'z':
135
s += fmt.Sprintf(" %c", ch)
137
s += fmt.Sprintf(" %02x", ch)
143
// Render a pseudo-diff between two blocks of bytes.
144
func bytediff(a []byte, b []byte) string {
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
155
sa := bytestr(offset, a[0:na])
156
sb := bytestr(offset, b[0:nb])
158
s += fmt.Sprintf("-%v\n+%v\n", sa, sb)
166
func TestWriter(t *testing.T) {
168
for i, test := range writerTests {
169
expected, err := ioutil.ReadFile(test.file)
171
t.Errorf("test %d: Unexpected error: %v", i, err)
175
buf := new(bytes.Buffer)
176
tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB
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)
184
if _, err := io.WriteString(tw, entry.contents); err != nil {
185
t.Errorf("test %d, entry %d: Failed writing contents: %v", i, j, err)
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)
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.
206
func TestPax(t *testing.T) {
207
// Create an archive with a large name
208
fileinfo, err := os.Stat("testdata/small.txt")
212
hdr, err := FileInfoHeader(fileinfo, "")
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))
221
writer := NewWriter(&buf)
222
if err := writer.WriteHeader(hdr); err != nil {
225
if _, err = writer.Write([]byte(contents)); err != nil {
228
if err := writer.Close(); err != nil {
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()
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)