github.com/laher/argo@v0.0.0-20140722103944-11d91c83cc0f/ar/reader_test.go (about) 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 ar 6 7 import ( 8 "bytes" 9 "crypto/md5" 10 "fmt" 11 "io" 12 "io/ioutil" 13 "os" 14 "path/filepath" 15 "reflect" 16 "strings" 17 "testing" 18 "time" 19 ) 20 21 type unarTest struct { 22 file string 23 headers []*Header 24 cksums []string 25 } 26 27 var simpleArTest = &unarTest{ 28 file: "testdata/common.ar", 29 headers: []*Header{ 30 { 31 Name: "small.txt", 32 Mode: 100664, 33 Uid: 1000, 34 Gid: 1000, 35 Size: 5, 36 ModTime: time.Unix(1405990895, 0), 37 }, 38 { 39 Name: "small2.txt", 40 Mode: 100664, 41 Uid: 1000, 42 Gid: 1000, 43 Size: 11, 44 ModTime: time.Unix(1405990895, 0), 45 }, 46 }, 47 cksums: []string{ 48 "e38b27eaccb4391bdec553a7f3ae6b2f", 49 "c65bd2e50a56a2138bf1716f2fd56fe9", 50 }, 51 } 52 var unarTests = []*unarTest{ 53 simpleArTest, 54 } 55 56 func TestNextString(t *testing.T) { 57 testLoop: 58 for i, test := range unarTests { 59 f, err := os.Open(test.file) 60 if err != nil { 61 t.Errorf("test %d: Unexpected error: %v", i, err) 62 continue 63 } 64 defer f.Close() 65 tr, err := NewReader(f) 66 if err != nil { 67 t.Errorf("test %d: Error checking file header: %v", i, err) 68 continue 69 } 70 for j := range test.headers { 71 hdr, err := tr.Next() 72 if err != nil || hdr == nil { 73 t.Errorf("test %d, entry %d: Didn't get entry: %v", i, j, err) 74 f.Close() 75 continue testLoop 76 } 77 if hdr.Size >= 6 { 78 str, err := tr.NextString(6) 79 if err != nil || len(str) != 6 { 80 t.Errorf("test %d, entry %d: Didn't get string: %s, %v", i, j, str, err) 81 f.Close() 82 continue testLoop 83 } 84 t.Logf("read first 6 bytes: %s", str) 85 } 86 } 87 hdr, err := tr.Next() 88 if err == io.EOF { 89 continue testLoop 90 } 91 if hdr != nil || err != nil { 92 t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, hdr, err) 93 } 94 } 95 } 96 97 func TestReader(t *testing.T) { 98 testLoop: 99 for i, test := range unarTests { 100 f, err := os.Open(test.file) 101 if err != nil { 102 t.Errorf("test %d: Unexpected error: %v", i, err) 103 continue 104 } 105 defer f.Close() 106 tr, err := NewReader(f) 107 if err != nil { 108 t.Errorf("test %d: Error checking file header: %v", i, err) 109 continue 110 } 111 for j, header := range test.headers { 112 hdr, err := tr.Next() 113 if err != nil || hdr == nil { 114 t.Errorf("test %d, entry %d: Didn't get entry: %v", i, j, err) 115 f.Close() 116 continue testLoop 117 } 118 if !reflect.DeepEqual(*hdr, *header) { 119 t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v", 120 i, j, *hdr, *header) 121 } 122 } 123 hdr, err := tr.Next() 124 if err == io.EOF { 125 continue testLoop 126 } 127 if hdr != nil || err != nil { 128 t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, hdr, err) 129 } 130 } 131 } 132 133 func TestPartialRead(t *testing.T) { 134 f, err := os.Open("testdata/common.ar") 135 if err != nil { 136 t.Fatalf("Unexpected error: %v", err) 137 } 138 defer f.Close() 139 140 tr, err := NewReader(f) 141 if err != nil || tr == nil { 142 t.Fatalf("Didn't get ar header: %v", err) 143 } 144 145 // Read the first four bytes; Next() should skip the last byte. 146 hdr, err := tr.Next() 147 if err != nil || hdr == nil { 148 t.Fatalf("Didn't get first file: %v", err) 149 } 150 buf := make([]byte, 4) 151 if _, err := io.ReadFull(tr, buf); err != nil { 152 t.Fatalf("Unexpected error: %v", err) 153 } 154 if expected := []byte("Kilt"); !bytes.Equal(buf, expected) { 155 t.Errorf("Contents = %v, want %v", buf, expected) 156 } 157 158 // Second file 159 hdr, err = tr.Next() 160 if err != nil || hdr == nil { 161 t.Fatalf("Didn't get second file: %v", err) 162 } 163 buf = make([]byte, 6) 164 if _, err := io.ReadFull(tr, buf); err != nil { 165 t.Fatalf("Unexpected error: %v", err) 166 } 167 if expected := []byte("Google"); !bytes.Equal(buf, expected) { 168 t.Errorf("Contents = %v, want %v", buf, expected) 169 } 170 } 171 172 func TestIncrementalRead(t *testing.T) { 173 test := simpleArTest 174 f, err := os.Open(test.file) 175 if err != nil { 176 t.Fatalf("Unexpected error: %v", err) 177 } 178 defer f.Close() 179 180 tr, err := NewReader(f) 181 if err != nil { 182 t.Fatalf("Unexpected error reading ar header: %v", err) 183 } 184 185 headers := test.headers 186 cksums := test.cksums 187 nread := 0 188 189 // loop over all files 190 for ; ; nread++ { 191 hdr, err := tr.Next() 192 if hdr == nil || err == io.EOF { 193 break 194 } 195 196 // check the header 197 if !reflect.DeepEqual(*hdr, *headers[nread]) { 198 t.Errorf("Incorrect header:\nhave %+v\nwant %+v", 199 hdr, headers[nread]) 200 } 201 202 // read file contents in little chunks EOF, 203 // checksumming all the way 204 h := md5.New() 205 rdbuf := make([]uint8, 8) 206 for { 207 nr, err := tr.Read(rdbuf) 208 if err == io.EOF { 209 break 210 } 211 if err != nil { 212 t.Errorf("Read: unexpected error %v\n", err) 213 break 214 } 215 h.Write(rdbuf[0:nr]) 216 } 217 // verify checksum 218 have := fmt.Sprintf("%x", h.Sum(nil)) 219 want := cksums[nread] 220 if want != have { 221 t.Errorf("Bad checksum on file %s:\nhave %+v\nwant %+v", hdr.Name, have, want) 222 } 223 } 224 if nread != len(headers) { 225 t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(headers), nread) 226 } 227 } 228 229 func TestNonSeekable(t *testing.T) { 230 test := simpleArTest 231 f, err := os.Open(test.file) 232 if err != nil { 233 t.Fatalf("Unexpected error: %v", err) 234 } 235 defer f.Close() 236 237 type readerOnly struct { 238 io.Reader 239 } 240 tr, err := NewReader(readerOnly{f}) 241 if err != nil { 242 t.Fatalf("NewReader error: %v", err) 243 } 244 nread := 0 245 246 for ; ; nread++ { 247 _, err = tr.Next() 248 if err == io.EOF { 249 break 250 } 251 if err != nil { 252 t.Fatalf("Unexpected error: %v", err) 253 } 254 } 255 256 if nread != len(test.headers) { 257 t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(test.headers), nread) 258 } 259 } 260 261 func TestUninitializedRead(t *testing.T) { 262 test := simpleArTest 263 f, err := os.Open(test.file) 264 if err != nil { 265 t.Fatalf("Unexpected error: %v", err) 266 } 267 defer f.Close() 268 269 tr, err := NewReader(f) 270 if err != nil { 271 t.Fatalf("NewReader error: %v", err) 272 } 273 _, err = tr.Read([]byte{}) 274 if err == nil || err != io.EOF { 275 t.Errorf("Unexpected error: %v, wanted %v", err, io.EOF) 276 } 277 278 } 279 280 type myCloser struct { 281 Reader io.Reader 282 closed bool 283 } 284 285 func (t myCloser) Read(p []byte) (int, error) { 286 if t.closed { 287 return -1, io.EOF 288 } 289 return t.Reader.Read(p) 290 } 291 292 func (t myCloser) Close() error { 293 t.closed = true 294 return nil 295 } 296 297 func TestNoFooter(t *testing.T) { 298 f, err := os.Open(filepath.Join("testdata", "nofooter.ar")) 299 if err != nil { 300 t.Fatalf("Unexpected error: %v", err) 301 } 302 defer f.Close() 303 304 tr, err := NewReader(f) 305 if err != nil { 306 t.Fatalf("NewReader error: %v", err) 307 } 308 _, err = tr.Read([]byte{}) 309 if err == nil || err != io.EOF { 310 t.Errorf("Unexpected error: %v, wanted %v", err, io.EOF) 311 } 312 nread := 0 313 314 // loop over all files 315 for ; ; nread++ { 316 hdr, err := tr.Next() 317 if hdr == nil || err == io.EOF { 318 break 319 } 320 _, err = io.Copy(ioutil.Discard, tr) 321 if nread == 1 { 322 if err == nil { 323 t.Fatalf("Read should have produced an error: %v", err) 324 } else { 325 t.Logf("Correctly produced an error: %v", err) 326 } 327 } else { 328 if err != nil { 329 t.Fatalf("Unexpected read error: %v", err) 330 } 331 } 332 } 333 334 } 335 func TestClosedReaderNextString(t *testing.T) { 336 sr := strings.NewReader("!<arch>\nblah") 337 r := myCloser{sr, false} 338 tr, err := NewReader(r) 339 if err != nil { 340 t.Errorf("Unexpected error returned by NewReader: %v", err) 341 } 342 r.Close() 343 str, err := tr.NextString(8) 344 if err == nil { 345 t.Errorf("No error returned by NextString: %s / %v", str, err) 346 } 347 } 348 349 func TestClosedReader(t *testing.T) { 350 r, _ := io.Pipe() 351 r.Close() 352 _, err := NewReader(r) 353 if err == nil { 354 t.Errorf("No error returned by NewReader: %v", err) 355 } 356 } 357 358 func TestInvalidArHeader(t *testing.T) { 359 r := strings.NewReader("not an ar file") 360 _, err := NewReader(r) 361 if err == nil { 362 t.Errorf("No error returned by NewReader: %v", err) 363 } 364 }