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  }