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