OSDN Git Service

libgo: Update to weekly.2011-11-02.
[pf3gnuchains/gcc-fork.git] / libgo / go / archive / zip / reader_test.go
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.
4
5 package zip
6
7 import (
8         "bytes"
9         "encoding/binary"
10         "io"
11         "io/ioutil"
12         "testing"
13         "time"
14 )
15
16 type ZipTest struct {
17         Name    string
18         Comment string
19         File    []ZipTestFile
20         Error   error // the error that Opening this file should return
21 }
22
23 type ZipTestFile struct {
24         Name    string
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"
28         Mode    uint32
29 }
30
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.
40
41 var tests = []ZipTest{
42         {
43                 Name:    "test.zip",
44                 Comment: "This is a zipfile comment.",
45                 File: []ZipTestFile{
46                         {
47                                 Name:    "test.txt",
48                                 Content: []byte("This is a test text file.\n"),
49                                 Mtime:   "09-05-10 12:12:02",
50                                 Mode:    0x81a4,
51                         },
52                         {
53                                 Name:  "gophercolor16x16.png",
54                                 File:  "gophercolor16x16.png",
55                                 Mtime: "09-05-10 15:52:58",
56                                 Mode:  0x81a4,
57                         },
58                 },
59         },
60         {
61                 Name: "r.zip",
62                 File: []ZipTestFile{
63                         {
64                                 Name:  "r/r.zip",
65                                 File:  "r.zip",
66                                 Mtime: "03-04-10 00:24:16",
67                         },
68                 },
69         },
70         {Name: "readme.zip"},
71         {Name: "readme.notzip", Error: FormatError},
72         {
73                 Name: "dd.zip",
74                 File: []ZipTestFile{
75                         {
76                                 Name:    "filename",
77                                 Content: []byte("This is a test textfile.\n"),
78                                 Mtime:   "02-02-11 13:06:20",
79                         },
80                 },
81         },
82 }
83
84 func TestReader(t *testing.T) {
85         for _, zt := range tests {
86                 readTestZip(t, zt)
87         }
88 }
89
90 func readTestZip(t *testing.T, zt ZipTest) {
91         z, err := OpenReader("testdata/" + zt.Name)
92         if err != zt.Error {
93                 t.Errorf("error=%v, want %v", err, zt.Error)
94                 return
95         }
96
97         // bail if file is not zip
98         if err == FormatError {
99                 return
100         }
101         defer z.Close()
102
103         // bail here if no Files expected to be tested
104         // (there may actually be files in the zip, but we don't care)
105         if zt.File == nil {
106                 return
107         }
108
109         if z.Comment != zt.Comment {
110                 t.Errorf("%s: comment=%q, want %q", zt.Name, z.Comment, zt.Comment)
111         }
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))
114         }
115
116         // test read of each file
117         for i, ft := range zt.File {
118                 readTestFile(t, ft, z.File[i])
119         }
120
121         // test simultaneous reads
122         n := 0
123         done := make(chan bool)
124         for i := 0; i < 5; i++ {
125                 for j, ft := range zt.File {
126                         go func() {
127                                 readTestFile(t, ft, z.File[j])
128                                 done <- true
129                         }()
130                         n++
131                 }
132         }
133         for ; n > 0; n-- {
134                 <-done
135         }
136
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()
141                 if err != nil {
142                         t.Error(err)
143                         return
144                 }
145                 var b bytes.Buffer
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)
149                 }
150         }
151 }
152
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)
156         }
157
158         mtime, err := time.Parse("01-02-06 15:04:05", ft.Mtime)
159         if err != nil {
160                 t.Error(err)
161                 return
162         }
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)
165         }
166
167         testFileMode(t, f, ft.Mode)
168
169         size0 := f.UncompressedSize
170
171         var b bytes.Buffer
172         r, err := f.Open()
173         if err != nil {
174                 t.Error(err)
175                 return
176         }
177
178         if size1 := f.UncompressedSize; size0 != size1 {
179                 t.Errorf("file %q changed f.UncompressedSize from %d to %d", f.Name, size0, size1)
180         }
181
182         _, err = io.Copy(&b, r)
183         if err != nil {
184                 t.Error(err)
185                 return
186         }
187         r.Close()
188
189         var c []byte
190         if len(ft.Content) != 0 {
191                 c = ft.Content
192         } else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil {
193                 t.Error(err)
194                 return
195         }
196
197         if b.Len() != len(c) {
198                 t.Errorf("%s: len=%d, want %d", f.Name, b.Len(), len(c))
199                 return
200         }
201
202         for i, b := range b.Bytes() {
203                 if b != c[i] {
204                         t.Errorf("%s: content[%d]=%q want %q", f.Name, i, b, c[i])
205                         return
206                 }
207         }
208 }
209
210 func testFileMode(t *testing.T, f *File, want uint32) {
211         mode, err := f.Mode()
212         if want == 0 {
213                 if err == nil {
214                         t.Errorf("%s mode: got %v, want none", f.Name, mode)
215                 }
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)
220         }
221 }
222
223 func TestInvalidFiles(t *testing.T) {
224         const size = 1024 * 70 // 70kb
225         b := make([]byte, size)
226
227         // zeroes
228         _, err := NewReader(sliceReaderAt(b), size)
229         if err != FormatError {
230                 t.Errorf("zeroes: error=%v, want %v", err, FormatError)
231         }
232
233         // repeated directoryEndSignatures
234         sig := make([]byte, 4)
235         binary.LittleEndian.PutUint32(sig, directoryEndSignature)
236         for i := 0; i < size-4; i += 4 {
237                 copy(b[i:i+4], sig)
238         }
239         _, err = NewReader(sliceReaderAt(b), size)
240         if err != FormatError {
241                 t.Errorf("sigs: error=%v, want %v", err, FormatError)
242         }
243 }
244
245 type sliceReaderAt []byte
246
247 func (r sliceReaderAt) ReadAt(b []byte, off int64) (int, error) {
248         copy(b, r[int(off):int(off)+len(b)])
249         return len(b), nil
250 }