~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to .pc/archive-tar-fix-links-and-pax.patch/src/pkg/archive/tar/writer_test.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-11-27 12:12:43 UTC
  • mfrom: (14.2.6 sid)
  • Revision ID: package-import@ubuntu.com-20131127121243-afpbjphmzzjpctnx
Tags: 2:1.1.2-3ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
4
 
 
5
package tar
 
6
 
 
7
import (
 
8
        "bytes"
 
9
        "fmt"
 
10
        "io"
 
11
        "io/ioutil"
 
12
        "os"
 
13
        "strings"
 
14
        "testing"
 
15
        "testing/iotest"
 
16
        "time"
 
17
)
 
18
 
 
19
type writerTestEntry struct {
 
20
        header   *Header
 
21
        contents string
 
22
}
 
23
 
 
24
type writerTest struct {
 
25
        file    string // filename of expected output
 
26
        entries []*writerTestEntry
 
27
}
 
28
 
 
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
 
34
        {
 
35
                file: "testdata/writer.tar",
 
36
                entries: []*writerTestEntry{
 
37
                        {
 
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",
 
48
                                },
 
49
                                contents: "Kilts",
 
50
                        },
 
51
                        {
 
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",
 
62
                                },
 
63
                                contents: "Google.com\n",
 
64
                        },
 
65
                        {
 
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",
 
77
                                },
 
78
                                // no contents
 
79
                        },
 
80
                },
 
81
        },
 
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
 
85
        {
 
86
                file: "testdata/writer-big.tar",
 
87
                entries: []*writerTestEntry{
 
88
                        {
 
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",
 
99
                                },
 
100
                                // fake contents
 
101
                                contents: strings.Repeat("\x00", 4<<10),
 
102
                        },
 
103
                },
 
104
        },
 
105
        // This file was produced using gnu tar 1.17
 
106
        // gnutar  -b 4 --format=ustar (longname/)*15 + file.txt
 
107
        {
 
108
                file: "testdata/ustar.tar",
 
109
                entries: []*writerTestEntry{
 
110
                        {
 
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",
 
121
                                },
 
122
                                contents: "hello\n",
 
123
                        },
 
124
                },
 
125
        },
 
126
}
 
127
 
 
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)
 
138
                }
 
139
        }
 
140
        return s
 
141
}
 
142
 
 
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)
 
151
                }
 
152
                if nb > len(b) {
 
153
                        nb = len(b)
 
154
                }
 
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)
 
159
                }
 
160
                a = a[na:]
 
161
                b = b[nb:]
 
162
        }
 
163
        return s
 
164
}
 
165
 
 
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
 
173
                }
 
174
 
 
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
 
183
                        }
 
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
 
187
                        }
 
188
                }
 
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
 
193
                }
 
194
 
 
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))
 
199
                }
 
200
                if testing.Short() { // The second test is expensive.
 
201
                        break
 
202
                }
 
203
        }
 
204
}
 
205
 
 
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)
 
211
        }
 
212
        hdr, err := FileInfoHeader(fileinfo, "")
 
213
        if err != nil {
 
214
                t.Fatalf("os.Stat: %v", err)
 
215
        }
 
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)
 
224
        }
 
225
        if _, err = writer.Write([]byte(contents)); err != nil {
 
226
                t.Fatal(err)
 
227
        }
 
228
        if err := writer.Close(); err != nil {
 
229
                t.Fatal(err)
 
230
        }
 
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.")
 
234
        }
 
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)
 
240
        }
 
241
        if hdr.Name != longName {
 
242
                t.Fatal("Couldn't recover long file name")
 
243
        }
 
244
}
 
245
 
 
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)}}
 
255
 
 
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)
 
260
                }
 
261
        }
 
262
}