github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/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 "time" 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 Mtime string 25 } 26 27 var writeTests = []WriteTest{ 28 { 29 Name: "foo", 30 Data: []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."), 31 Method: Store, 32 Mode: 0666, 33 Mtime: "02-01-08 00:01:02", 34 }, 35 { 36 Name: "bar", 37 Data: nil, // large data set in the test 38 Method: Deflate, 39 Mode: 0644, 40 Mtime: "03-02-08 01:02:03", 41 }, 42 { 43 Name: "setuid", 44 Data: []byte("setuid file"), 45 Method: Deflate, 46 Mode: 0755 | os.ModeSetuid, 47 Mtime: "04-03-08 02:03:04", 48 }, 49 { 50 Name: "setgid", 51 Data: []byte("setgid file"), 52 Method: Deflate, 53 Mode: 0755 | os.ModeSetgid, 54 Mtime: "05-04-08 03:04:04", 55 }, 56 { 57 Name: "symlink", 58 Data: []byte("../link/target"), 59 Method: Deflate, 60 Mode: 0755 | os.ModeSymlink, 61 Mtime: "03-02-08 11:22:33", 62 }, 63 } 64 65 func TestWriter(t *testing.T) { 66 largeData := make([]byte, 1<<17) 67 for i := range largeData { 68 largeData[i] = byte(rand.Int()) 69 } 70 writeTests[1].Data = largeData 71 defer func() { 72 writeTests[1].Data = nil 73 }() 74 75 // write a zip file 76 buf := new(bytes.Buffer) 77 w := NewWriter(buf) 78 79 for _, wt := range writeTests { 80 testCreate(t, w, &wt) 81 } 82 83 if err := w.Close(); err != nil { 84 t.Fatal(err) 85 } 86 87 // read it back 88 r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) 89 if err != nil { 90 t.Fatal(err) 91 } 92 for i, wt := range writeTests { 93 testReadFile(t, r.File[i], &wt) 94 } 95 } 96 97 func TestWriterOffset(t *testing.T) { 98 largeData := make([]byte, 1<<17) 99 for i := range largeData { 100 largeData[i] = byte(rand.Int()) 101 } 102 writeTests[1].Data = largeData 103 defer func() { 104 writeTests[1].Data = nil 105 }() 106 107 // write a zip file 108 buf := new(bytes.Buffer) 109 existingData := []byte{1, 2, 3, 1, 2, 3, 1, 2, 3} 110 n, _ := buf.Write(existingData) 111 w := NewWriter(buf) 112 w.SetOffset(int64(n)) 113 114 for _, wt := range writeTests { 115 testCreate(t, w, &wt) 116 } 117 118 if err := w.Close(); err != nil { 119 t.Fatal(err) 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 for i, wt := range writeTests { 128 testReadFile(t, r.File[i], &wt) 129 } 130 } 131 132 func TestWriterFlush(t *testing.T) { 133 var buf bytes.Buffer 134 w := NewWriter(struct{ io.Writer }{&buf}) 135 _, err := w.Create("foo") 136 if err != nil { 137 t.Fatal(err) 138 } 139 if buf.Len() > 0 { 140 t.Fatalf("Unexpected %d bytes already in buffer", buf.Len()) 141 } 142 if err := w.Flush(); err != nil { 143 t.Fatal(err) 144 } 145 if buf.Len() == 0 { 146 t.Fatal("No bytes written after Flush") 147 } 148 } 149 150 func testCreate(t *testing.T, w *Writer, wt *WriteTest) { 151 header := &FileHeader{ 152 Name: wt.Name, 153 Method: wt.Method, 154 } 155 if wt.Mode != 0 { 156 header.SetMode(wt.Mode) 157 } 158 mtime, err := time.Parse("01-02-06 15:04:05", wt.Mtime) 159 if err != nil { 160 t.Fatal("time.Parse:", err) 161 } 162 header.SetModTime(mtime) 163 f, err := w.CreateHeader(header) 164 if err != nil { 165 t.Fatal(err) 166 } 167 _, err = f.Write(wt.Data) 168 if err != nil { 169 t.Fatal(err) 170 } 171 } 172 173 func testReadFile(t *testing.T, f *File, wt *WriteTest) { 174 if f.Name != wt.Name { 175 t.Fatalf("File name: got %q, want %q", f.Name, wt.Name) 176 } 177 testFileMode(t, wt.Name, f, wt.Mode) 178 rc, err := f.Open() 179 if err != nil { 180 t.Fatal("opening:", err) 181 } 182 b, err := ioutil.ReadAll(rc) 183 if err != nil { 184 t.Fatal("reading:", err) 185 } 186 err = rc.Close() 187 if err != nil { 188 t.Fatal("closing:", err) 189 } 190 if !bytes.Equal(b, wt.Data) { 191 t.Errorf("File contents %q, want %q", b, wt.Data) 192 } 193 194 mtime, err := time.Parse("01-02-06 15:04:05", wt.Mtime) 195 if err != nil { 196 t.Fatal("time.Parse:", err) 197 } 198 199 diff := mtime.Sub(f.ModTime()) 200 if diff < 0 { 201 diff = -diff 202 } 203 204 // allow several time span 205 if diff > 5*time.Second { 206 t.Errorf("File modtime %v, want %v", mtime, f.ModTime()) 207 } 208 } 209 210 func BenchmarkCompressedZipGarbage(b *testing.B) { 211 b.ReportAllocs() 212 var buf bytes.Buffer 213 bigBuf := bytes.Repeat([]byte("a"), 1<<20) 214 for i := 0; i <= b.N; i++ { 215 buf.Reset() 216 zw := NewWriter(&buf) 217 for j := 0; j < 3; j++ { 218 w, _ := zw.CreateHeader(&FileHeader{ 219 Name: "foo", 220 Method: Deflate, 221 }) 222 w.Write(bigBuf) 223 } 224 zw.Close() 225 if i == 0 { 226 // Reset the timer after the first time through. 227 // This effectively discards the very large initial flate setup cost, 228 // as well as the initialization of bigBuf. 229 b.ResetTimer() 230 } 231 } 232 }