1 // Copyright 2010 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.
20 Error error // the error that Opening this file should return
23 type ZipTestFile struct {
25 Content []byte // if blank, will attempt to compare against File
26 File string // name of file to compare to (relative to testdata/)
27 Mtime string // modified time in format "mm-dd-yy hh:mm:ss"
31 // Caution: The Mtime values found for the test files should correspond to
32 // the values listed with unzip -l <zipfile>. However, the values
33 // listed by unzip appear to be off by some hours. When creating
34 // fresh test files and testing them, this issue is not present.
35 // The test files were created in Sydney, so there might be a time
36 // zone issue. The time zone information does have to be encoded
37 // somewhere, because otherwise unzip -l could not provide a different
38 // time from what the archive/zip package provides, but there appears
39 // to be no documentation about this.
41 var tests = []ZipTest{
44 Comment: "This is a zipfile comment.",
48 Content: []byte("This is a test text file.\n"),
49 Mtime: "09-05-10 12:12:02",
53 Name: "gophercolor16x16.png",
54 File: "gophercolor16x16.png",
55 Mtime: "09-05-10 15:52:58",
66 Mtime: "03-04-10 00:24:16",
71 {Name: "readme.notzip", Error: FormatError},
77 Content: []byte("This is a test textfile.\n"),
78 Mtime: "02-02-11 13:06:20",
84 func TestReader(t *testing.T) {
85 for _, zt := range tests {
90 func readTestZip(t *testing.T, zt ZipTest) {
91 z, err := OpenReader("testdata/" + zt.Name)
93 t.Errorf("error=%v, want %v", err, zt.Error)
97 // bail if file is not zip
98 if err == FormatError {
103 // bail here if no Files expected to be tested
104 // (there may actually be files in the zip, but we don't care)
109 if z.Comment != zt.Comment {
110 t.Errorf("%s: comment=%q, want %q", zt.Name, z.Comment, zt.Comment)
112 if len(z.File) != len(zt.File) {
113 t.Errorf("%s: file count=%d, want %d", zt.Name, len(z.File), len(zt.File))
116 // test read of each file
117 for i, ft := range zt.File {
118 readTestFile(t, ft, z.File[i])
121 // test simultaneous reads
123 done := make(chan bool)
124 for i := 0; i < 5; i++ {
125 for j, ft := range zt.File {
127 readTestFile(t, ft, z.File[j])
137 // test invalid checksum
138 if !z.File[0].hasDataDescriptor() { // skip test when crc32 in dd
139 z.File[0].CRC32++ // invalidate
140 r, err := z.File[0].Open()
146 _, err = io.Copy(&b, r)
147 if err != ChecksumError {
148 t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ChecksumError)
153 func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
154 if f.Name != ft.Name {
155 t.Errorf("name=%q, want %q", f.Name, ft.Name)
158 mtime, err := time.Parse("01-02-06 15:04:05", ft.Mtime)
163 if got, want := f.Mtime_ns()/1e9, mtime.Seconds(); got != want {
164 t.Errorf("%s: mtime=%s (%d); want %s (%d)", f.Name, time.SecondsToUTC(got), got, mtime, want)
167 testFileMode(t, f, ft.Mode)
169 size0 := f.UncompressedSize
178 if size1 := f.UncompressedSize; size0 != size1 {
179 t.Errorf("file %q changed f.UncompressedSize from %d to %d", f.Name, size0, size1)
182 _, err = io.Copy(&b, r)
190 if len(ft.Content) != 0 {
192 } else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil {
197 if b.Len() != len(c) {
198 t.Errorf("%s: len=%d, want %d", f.Name, b.Len(), len(c))
202 for i, b := range b.Bytes() {
204 t.Errorf("%s: content[%d]=%q want %q", f.Name, i, b, c[i])
210 func testFileMode(t *testing.T, f *File, want uint32) {
211 mode, err := f.Mode()
214 t.Errorf("%s mode: got %v, want none", f.Name, mode)
216 } else if err != nil {
217 t.Errorf("%s mode: %s", f.Name, err)
218 } else if mode != want {
219 t.Errorf("%s mode: want 0x%x, got 0x%x", f.Name, want, mode)
223 func TestInvalidFiles(t *testing.T) {
224 const size = 1024 * 70 // 70kb
225 b := make([]byte, size)
228 _, err := NewReader(sliceReaderAt(b), size)
229 if err != FormatError {
230 t.Errorf("zeroes: error=%v, want %v", err, FormatError)
233 // repeated directoryEndSignatures
234 sig := make([]byte, 4)
235 binary.LittleEndian.PutUint32(sig, directoryEndSignature)
236 for i := 0; i < size-4; i += 4 {
239 _, err = NewReader(sliceReaderAt(b), size)
240 if err != FormatError {
241 t.Errorf("sigs: error=%v, want %v", err, FormatError)
245 type sliceReaderAt []byte
247 func (r sliceReaderAt) ReadAt(b []byte, off int64) (int, error) {
248 copy(b, r[int(off):int(off)+len(b)])