github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/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 TestWriterOffset(t *testing.T) { 91 largeData := make([]byte, 1<<17) 92 for i := range largeData { 93 largeData[i] = byte(rand.Int()) 94 } 95 writeTests[1].Data = largeData 96 defer func() { 97 writeTests[1].Data = nil 98 }() 99 100 // write a zip file 101 buf := new(bytes.Buffer) 102 existingData := []byte{1, 2, 3, 1, 2, 3, 1, 2, 3} 103 n, _ := buf.Write(existingData) 104 w := NewWriter(buf) 105 w.SetOffset(int64(n)) 106 107 for _, wt := range writeTests { 108 testCreate(t, w, &wt) 109 } 110 111 if err := w.Close(); err != nil { 112 t.Fatal(err) 113 } 114 115 // read it back 116 r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) 117 if err != nil { 118 t.Fatal(err) 119 } 120 for i, wt := range writeTests { 121 testReadFile(t, r.File[i], &wt) 122 } 123 } 124 125 func TestWriterFlush(t *testing.T) { 126 var buf bytes.Buffer 127 w := NewWriter(struct{ io.Writer }{&buf}) 128 _, err := w.Create("foo") 129 if err != nil { 130 t.Fatal(err) 131 } 132 if buf.Len() > 0 { 133 t.Fatalf("Unexpected %d bytes already in buffer", buf.Len()) 134 } 135 if err := w.Flush(); err != nil { 136 t.Fatal(err) 137 } 138 if buf.Len() == 0 { 139 t.Fatal("No bytes written after Flush") 140 } 141 } 142 143 func testCreate(t *testing.T, w *Writer, wt *WriteTest) { 144 header := &FileHeader{ 145 Name: wt.Name, 146 Method: wt.Method, 147 } 148 if wt.Mode != 0 { 149 header.SetMode(wt.Mode) 150 } 151 f, err := w.CreateHeader(header) 152 if err != nil { 153 t.Fatal(err) 154 } 155 _, err = f.Write(wt.Data) 156 if err != nil { 157 t.Fatal(err) 158 } 159 } 160 161 func testReadFile(t *testing.T, f *File, wt *WriteTest) { 162 if f.Name != wt.Name { 163 t.Fatalf("File name: got %q, want %q", f.Name, wt.Name) 164 } 165 testFileMode(t, wt.Name, f, wt.Mode) 166 rc, err := f.Open() 167 if err != nil { 168 t.Fatal("opening:", err) 169 } 170 b, err := ioutil.ReadAll(rc) 171 if err != nil { 172 t.Fatal("reading:", err) 173 } 174 err = rc.Close() 175 if err != nil { 176 t.Fatal("closing:", err) 177 } 178 if !bytes.Equal(b, wt.Data) { 179 t.Errorf("File contents %q, want %q", b, wt.Data) 180 } 181 } 182 183 func BenchmarkCompressedZipGarbage(b *testing.B) { 184 b.ReportAllocs() 185 var buf bytes.Buffer 186 bigBuf := bytes.Repeat([]byte("a"), 1<<20) 187 for i := 0; i <= b.N; i++ { 188 buf.Reset() 189 zw := NewWriter(&buf) 190 for j := 0; j < 3; j++ { 191 w, _ := zw.CreateHeader(&FileHeader{ 192 Name: "foo", 193 Method: Deflate, 194 }) 195 w.Write(bigBuf) 196 } 197 zw.Close() 198 if i == 0 { 199 // Reset the timer after the first time through. 200 // This effectively discards the very large initial flate setup cost, 201 // as well as the initialization of bigBuf. 202 b.ResetTimer() 203 } 204 } 205 }