OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package tar | 5 package tar |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes"; | 8 "bytes"; |
| 9 "crypto/md5"; |
| 10 "fmt"; |
9 "io"; | 11 "io"; |
10 "os"; | 12 "os"; |
11 "reflect"; | 13 "reflect"; |
12 "strings"; | 14 "strings"; |
13 "testing"; | 15 "testing"; |
14 ) | 16 ) |
15 | 17 |
16 type untarTest struct { | 18 type untarTest struct { |
17 file string; | 19 file string; |
18 headers []*Header; | 20 headers []*Header; |
| 21 cksums []string; |
| 22 } |
| 23 |
| 24 var gnuTarTest = &untarTest{ |
| 25 file: "testdata/gnu.tar", |
| 26 headers: []*Header{ |
| 27 &Header{ |
| 28 Name: "small.txt", |
| 29 Mode: 0640, |
| 30 Uid: 73025, |
| 31 Gid: 5000, |
| 32 Size: 5, |
| 33 Mtime: 1244428340, |
| 34 Typeflag: '0', |
| 35 Uname: "dsymonds", |
| 36 Gname: "eng", |
| 37 }, |
| 38 &Header{ |
| 39 Name: "small2.txt", |
| 40 Mode: 0640, |
| 41 Uid: 73025, |
| 42 Gid: 5000, |
| 43 Size: 11, |
| 44 Mtime: 1244436044, |
| 45 Typeflag: '0', |
| 46 Uname: "dsymonds", |
| 47 Gname: "eng", |
| 48 }, |
| 49 }, |
| 50 cksums: []string{ |
| 51 "e38b27eaccb4391bdec553a7f3ae6b2f", |
| 52 "c65bd2e50a56a2138bf1716f2fd56fe9", |
| 53 }, |
19 } | 54 } |
20 | 55 |
21 var untarTests = []*untarTest{ | 56 var untarTests = []*untarTest{ |
22 » &untarTest{ | 57 » gnuTarTest, |
23 » » file: "testdata/gnu.tar", | |
24 » » headers: []*Header{ | |
25 » » » &Header{ | |
26 » » » » Name: "small.txt", | |
27 » » » » Mode: 0640, | |
28 » » » » Uid: 73025, | |
29 » » » » Gid: 5000, | |
30 » » » » Size: 5, | |
31 » » » » Mtime: 1244428340, | |
32 » » » » Typeflag: '0', | |
33 » » » » Uname: "dsymonds", | |
34 » » » » Gname: "eng", | |
35 » » » }, | |
36 » » » &Header{ | |
37 » » » » Name: "small2.txt", | |
38 » » » » Mode: 0640, | |
39 » » » » Uid: 73025, | |
40 » » » » Gid: 5000, | |
41 » » » » Size: 11, | |
42 » » » » Mtime: 1244436044, | |
43 » » » » Typeflag: '0', | |
44 » » » » Uname: "dsymonds", | |
45 » » » » Gname: "eng", | |
46 » » » }, | |
47 » » }, | |
48 » }, | |
49 &untarTest{ | 58 &untarTest{ |
50 file: "testdata/star.tar", | 59 file: "testdata/star.tar", |
51 headers: []*Header{ | 60 headers: []*Header{ |
52 &Header{ | 61 &Header{ |
53 Name: "small.txt", | 62 Name: "small.txt", |
54 Mode: 0640, | 63 Mode: 0640, |
55 Uid: 73025, | 64 Uid: 73025, |
56 Gid: 5000, | 65 Gid: 5000, |
57 Size: 5, | 66 Size: 5, |
58 Mtime: 1244592783, | 67 Mtime: 1244592783, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 t.Errorf("test %d, entry %d: Didn't get entry: %
v", i, j, err); | 126 t.Errorf("test %d, entry %d: Didn't get entry: %
v", i, j, err); |
118 f.Close(); | 127 f.Close(); |
119 continue testLoop; | 128 continue testLoop; |
120 } | 129 } |
121 if !reflect.DeepEqual(hdr, header) { | 130 if !reflect.DeepEqual(hdr, header) { |
122 t.Errorf("test %d, entry %d: Incorrect header:\n
have %+v\nwant %+v", | 131 t.Errorf("test %d, entry %d: Incorrect header:\n
have %+v\nwant %+v", |
123 i, j, *hdr, *header) | 132 i, j, *hdr, *header) |
124 } | 133 } |
125 } | 134 } |
126 hdr, err := tr.Next(); | 135 hdr, err := tr.Next(); |
| 136 if err == os.EOF { |
| 137 break |
| 138 } |
127 if hdr != nil || err != nil { | 139 if hdr != nil || err != nil { |
128 t.Errorf("test %d: Unexpected entry or error: hdr=%v err
=%v", i, err) | 140 t.Errorf("test %d: Unexpected entry or error: hdr=%v err
=%v", i, err) |
129 } | 141 } |
130 f.Close(); | 142 f.Close(); |
131 } | 143 } |
132 } | 144 } |
133 | 145 |
134 func TestPartialRead(t *testing.T) { | 146 func TestPartialRead(t *testing.T) { |
135 f, err := os.Open("testdata/gnu.tar", os.O_RDONLY, 0444); | 147 f, err := os.Open("testdata/gnu.tar", os.O_RDONLY, 0444); |
136 if err != nil { | 148 if err != nil { |
(...skipping 22 matching lines...) Expand all Loading... |
159 t.Fatalf("Didn't get second file: %v", err) | 171 t.Fatalf("Didn't get second file: %v", err) |
160 } | 172 } |
161 buf = make([]byte, 6); | 173 buf = make([]byte, 6); |
162 if _, err := io.ReadFull(tr, buf); err != nil { | 174 if _, err := io.ReadFull(tr, buf); err != nil { |
163 t.Fatalf("Unexpected error: %v", err) | 175 t.Fatalf("Unexpected error: %v", err) |
164 } | 176 } |
165 if expected := strings.Bytes("Google"); !bytes.Equal(buf, expected) { | 177 if expected := strings.Bytes("Google"); !bytes.Equal(buf, expected) { |
166 t.Errorf("Contents = %v, want %v", buf, expected) | 178 t.Errorf("Contents = %v, want %v", buf, expected) |
167 } | 179 } |
168 } | 180 } |
| 181 |
| 182 |
| 183 func TestIncrementalRead(t *testing.T) { |
| 184 test := gnuTarTest; |
| 185 f, err := os.Open(test.file, os.O_RDONLY, 0444); |
| 186 if err != nil { |
| 187 t.Fatalf("Unexpected error: %v", err) |
| 188 } |
| 189 defer f.Close(); |
| 190 |
| 191 tr := NewReader(f); |
| 192 |
| 193 headers := test.headers; |
| 194 cksums := test.cksums; |
| 195 nread := 0; |
| 196 |
| 197 // loop over all files |
| 198 for ; ; nread++ { |
| 199 hdr, err := tr.Next(); |
| 200 if hdr == nil || err == os.EOF { |
| 201 break |
| 202 } |
| 203 |
| 204 // check the header |
| 205 if !reflect.DeepEqual(hdr, headers[nread]) { |
| 206 t.Errorf("Incorrect header:\nhave %+v\nwant %+v", |
| 207 *hdr, headers[nread]) |
| 208 } |
| 209 |
| 210 // read file contents in little chunks EOF, |
| 211 // checksumming all the way |
| 212 h := md5.New(); |
| 213 rdbuf := make([]uint8, 8); |
| 214 for { |
| 215 nr, err := tr.Read(rdbuf); |
| 216 if err == os.EOF { |
| 217 break |
| 218 } |
| 219 if err != nil { |
| 220 t.Errorf("Read: unexpected error %v\n", err); |
| 221 break; |
| 222 } |
| 223 h.Write(rdbuf[0:nr]); |
| 224 } |
| 225 // verify checksum |
| 226 have := fmt.Sprintf("%x", h.Sum()); |
| 227 want := cksums[nread]; |
| 228 if want != have { |
| 229 t.Errorf("Bad checksum on file %s:\nhave %+v\nwant %+v",
hdr.Name, have, want) |
| 230 } |
| 231 } |
| 232 if nread != len(headers) { |
| 233 t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n
", len(headers), nread) |
| 234 } |
| 235 } |
| 236 |
| 237 func TestNonSeekable(t *testing.T) { |
| 238 test := gnuTarTest; |
| 239 f, err := os.Open(test.file, os.O_RDONLY, 0444); |
| 240 if err != nil { |
| 241 t.Fatalf("Unexpected error: %v", err) |
| 242 } |
| 243 defer f.Close(); |
| 244 |
| 245 // pipe the data in |
| 246 r, w, err := os.Pipe(); |
| 247 if err != nil { |
| 248 t.Fatalf("Unexpected error %s", err) |
| 249 } |
| 250 go func() { |
| 251 rdbuf := make([]uint8, 1<<16); |
| 252 for { |
| 253 nr, err := f.Read(rdbuf); |
| 254 w.Write(rdbuf[0:nr]); |
| 255 if err == os.EOF { |
| 256 break |
| 257 } |
| 258 } |
| 259 w.Close(); |
| 260 }(); |
| 261 |
| 262 tr := NewReader(r); |
| 263 nread := 0; |
| 264 |
| 265 for ; ; nread++ { |
| 266 hdr, err := tr.Next(); |
| 267 if hdr == nil || err == os.EOF { |
| 268 break |
| 269 } |
| 270 } |
| 271 |
| 272 if nread != len(test.headers) { |
| 273 t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n
", len(test.headers), nread) |
| 274 } |
| 275 } |
OLD | NEW |