github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/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  }