github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/archive/zip/writer_test.go (about) 1 // Copyright 2011 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 "io" 10 "io/ioutil" 11 "math/rand" 12 "os" 13 "strings" 14 "testing" 15 ) 16 17 // TODO(adg): a more sophisticated test suite 18 19 type WriteTest struct { 20 Name string 21 Data []byte 22 Method uint16 23 Mode os.FileMode 24 } 25 26 var writeTests = []WriteTest{ 27 { 28 Name: "foo", 29 Data: []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."), 30 Method: Store, 31 Mode: 0666, 32 }, 33 { 34 Name: "bar", 35 Data: nil, // large data set in the test 36 Method: Deflate, 37 Mode: 0644, 38 }, 39 { 40 Name: "setuid", 41 Data: []byte("setuid file"), 42 Method: Deflate, 43 Mode: 0755 | os.ModeSetuid, 44 }, 45 { 46 Name: "setgid", 47 Data: []byte("setgid file"), 48 Method: Deflate, 49 Mode: 0755 | os.ModeSetgid, 50 }, 51 { 52 Name: "symlink", 53 Data: []byte("../link/target"), 54 Method: Deflate, 55 Mode: 0755 | os.ModeSymlink, 56 }, 57 } 58 59 func TestWriter(t *testing.T) { 60 largeData := make([]byte, 1<<17) 61 for i := range largeData { 62 largeData[i] = byte(rand.Int()) 63 } 64 writeTests[1].Data = largeData 65 defer func() { 66 writeTests[1].Data = nil 67 }() 68 69 // write a zip file 70 buf := new(bytes.Buffer) 71 w := NewWriter(buf) 72 73 for _, wt := range writeTests { 74 testCreate(t, w, &wt) 75 } 76 77 if err := w.Close(); err != nil { 78 t.Fatal(err) 79 } 80 81 // read it back 82 r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) 83 if err != nil { 84 t.Fatal(err) 85 } 86 for i, wt := range writeTests { 87 testReadFile(t, r.File[i], &wt) 88 } 89 } 90 91 // TestWriterComment is test for EOCD comment read/write. 92 func TestWriterComment(t *testing.T) { 93 var tests = []struct { 94 comment string 95 ok bool 96 }{ 97 {"hi, hello", true}, 98 {"hi, こんにちわ", true}, 99 {strings.Repeat("a", uint16max), true}, 100 {strings.Repeat("a", uint16max+1), false}, 101 } 102 103 for _, test := range tests { 104 // write a zip file 105 buf := new(bytes.Buffer) 106 w := NewWriter(buf) 107 w.Comment = test.comment 108 109 if err := w.Close(); test.ok == (err != nil) { 110 t.Fatal(err) 111 } 112 113 if w.closed != test.ok { 114 t.Fatalf("Writer.closed: got %v, want %v", w.closed, test.ok) 115 } 116 117 // skip read test in failure cases 118 if !test.ok { 119 continue 120 } 121 122 // read it back 123 r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) 124 if err != nil { 125 t.Fatal(err) 126 } 127 if r.Comment != test.comment { 128 t.Fatalf("Reader.Comment: got %v, want %v", r.Comment, test.comment) 129 } 130 } 131 } 132 133 func TestWriterUTF8(t *testing.T) { 134 var utf8Tests = []struct { 135 name string 136 comment string 137 expect uint16 138 }{ 139 { 140 name: "hi, hello", 141 comment: "in the world", 142 expect: 0x8, 143 }, 144 { 145 name: "hi, こんにちわ", 146 comment: "in the world", 147 expect: 0x808, 148 }, 149 { 150 name: "hi, hello", 151 comment: "in the 世界", 152 expect: 0x808, 153 }, 154 { 155 name: "hi, こんにちわ", 156 comment: "in the 世界", 157 expect: 0x808, 158 }, 159 } 160 161 // write a zip file 162 buf := new(bytes.Buffer) 163 w := NewWriter(buf) 164 165 for _, test := range utf8Tests { 166 h := &FileHeader{ 167 Name: test.name, 168 Comment: test.comment, 169 Method: Deflate, 170 } 171 w, err := w.CreateHeader(h) 172 if err != nil { 173 t.Fatal(err) 174 } 175 w.Write([]byte{}) 176 } 177 178 if err := w.Close(); err != nil { 179 t.Fatal(err) 180 } 181 182 // read it back 183 r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) 184 if err != nil { 185 t.Fatal(err) 186 } 187 for i, test := range utf8Tests { 188 got := r.File[i].Flags 189 t.Logf("name %v, comment %v", test.name, test.comment) 190 if got != test.expect { 191 t.Fatalf("Flags: got %v, want %v", got, test.expect) 192 } 193 } 194 } 195 196 func TestWriterOffset(t *testing.T) { 197 largeData := make([]byte, 1<<17) 198 for i := range largeData { 199 largeData[i] = byte(rand.Int()) 200 } 201 writeTests[1].Data = largeData 202 defer func() { 203 writeTests[1].Data = nil 204 }() 205 206 // write a zip file 207 buf := new(bytes.Buffer) 208 existingData := []byte{1, 2, 3, 1, 2, 3, 1, 2, 3} 209 n, _ := buf.Write(existingData) 210 w := NewWriter(buf) 211 w.SetOffset(int64(n)) 212 213 for _, wt := range writeTests { 214 testCreate(t, w, &wt) 215 } 216 217 if err := w.Close(); err != nil { 218 t.Fatal(err) 219 } 220 221 // read it back 222 r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) 223 if err != nil { 224 t.Fatal(err) 225 } 226 for i, wt := range writeTests { 227 testReadFile(t, r.File[i], &wt) 228 } 229 } 230 231 func TestWriterFlush(t *testing.T) { 232 var buf bytes.Buffer 233 w := NewWriter(struct{ io.Writer }{&buf}) 234 _, err := w.Create("foo") 235 if err != nil { 236 t.Fatal(err) 237 } 238 if buf.Len() > 0 { 239 t.Fatalf("Unexpected %d bytes already in buffer", buf.Len()) 240 } 241 if err := w.Flush(); err != nil { 242 t.Fatal(err) 243 } 244 if buf.Len() == 0 { 245 t.Fatal("No bytes written after Flush") 246 } 247 } 248 249 func testCreate(t *testing.T, w *Writer, wt *WriteTest) { 250 header := &FileHeader{ 251 Name: wt.Name, 252 Method: wt.Method, 253 } 254 if wt.Mode != 0 { 255 header.SetMode(wt.Mode) 256 } 257 f, err := w.CreateHeader(header) 258 if err != nil { 259 t.Fatal(err) 260 } 261 _, err = f.Write(wt.Data) 262 if err != nil { 263 t.Fatal(err) 264 } 265 } 266 267 func testReadFile(t *testing.T, f *File, wt *WriteTest) { 268 if f.Name != wt.Name { 269 t.Fatalf("File name: got %q, want %q", f.Name, wt.Name) 270 } 271 testFileMode(t, wt.Name, f, wt.Mode) 272 rc, err := f.Open() 273 if err != nil { 274 t.Fatal("opening:", err) 275 } 276 b, err := ioutil.ReadAll(rc) 277 if err != nil { 278 t.Fatal("reading:", err) 279 } 280 err = rc.Close() 281 if err != nil { 282 t.Fatal("closing:", err) 283 } 284 if !bytes.Equal(b, wt.Data) { 285 t.Errorf("File contents %q, want %q", b, wt.Data) 286 } 287 } 288 289 func BenchmarkCompressedZipGarbage(b *testing.B) { 290 bigBuf := bytes.Repeat([]byte("a"), 1<<20) 291 292 runOnce := func(buf *bytes.Buffer) { 293 buf.Reset() 294 zw := NewWriter(buf) 295 for j := 0; j < 3; j++ { 296 w, _ := zw.CreateHeader(&FileHeader{ 297 Name: "foo", 298 Method: Deflate, 299 }) 300 w.Write(bigBuf) 301 } 302 zw.Close() 303 } 304 305 b.ReportAllocs() 306 // Run once and then reset the timer. 307 // This effectively discards the very large initial flate setup cost, 308 // as well as the initialization of bigBuf. 309 runOnce(&bytes.Buffer{}) 310 b.ResetTimer() 311 312 b.RunParallel(func(pb *testing.PB) { 313 var buf bytes.Buffer 314 for pb.Next() { 315 runOnce(&buf) 316 } 317 }) 318 }