...

Source file src/compress/gzip/gzip_test.go

Documentation: compress/gzip

		 1  // Copyright 2010 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 gzip
		 6  
		 7  import (
		 8  	"bufio"
		 9  	"bytes"
		10  	"io"
		11  	"reflect"
		12  	"testing"
		13  	"time"
		14  )
		15  
		16  // TestEmpty tests that an empty payload still forms a valid GZIP stream.
		17  func TestEmpty(t *testing.T) {
		18  	buf := new(bytes.Buffer)
		19  
		20  	if err := NewWriter(buf).Close(); err != nil {
		21  		t.Fatalf("Writer.Close: %v", err)
		22  	}
		23  
		24  	r, err := NewReader(buf)
		25  	if err != nil {
		26  		t.Fatalf("NewReader: %v", err)
		27  	}
		28  	if want := (Header{OS: 255}); !reflect.DeepEqual(r.Header, want) {
		29  		t.Errorf("Header mismatch:\ngot	%#v\nwant %#v", r.Header, want)
		30  	}
		31  	b, err := io.ReadAll(r)
		32  	if err != nil {
		33  		t.Fatalf("ReadAll: %v", err)
		34  	}
		35  	if len(b) != 0 {
		36  		t.Fatalf("got %d bytes, want 0", len(b))
		37  	}
		38  	if err := r.Close(); err != nil {
		39  		t.Fatalf("Reader.Close: %v", err)
		40  	}
		41  }
		42  
		43  // TestRoundTrip tests that gzipping and then gunzipping is the identity
		44  // function.
		45  func TestRoundTrip(t *testing.T) {
		46  	buf := new(bytes.Buffer)
		47  
		48  	w := NewWriter(buf)
		49  	w.Comment = "comment"
		50  	w.Extra = []byte("extra")
		51  	w.ModTime = time.Unix(1e8, 0)
		52  	w.Name = "name"
		53  	if _, err := w.Write([]byte("payload")); err != nil {
		54  		t.Fatalf("Write: %v", err)
		55  	}
		56  	if err := w.Close(); err != nil {
		57  		t.Fatalf("Writer.Close: %v", err)
		58  	}
		59  
		60  	r, err := NewReader(buf)
		61  	if err != nil {
		62  		t.Fatalf("NewReader: %v", err)
		63  	}
		64  	b, err := io.ReadAll(r)
		65  	if err != nil {
		66  		t.Fatalf("ReadAll: %v", err)
		67  	}
		68  	if string(b) != "payload" {
		69  		t.Fatalf("payload is %q, want %q", string(b), "payload")
		70  	}
		71  	if r.Comment != "comment" {
		72  		t.Fatalf("comment is %q, want %q", r.Comment, "comment")
		73  	}
		74  	if string(r.Extra) != "extra" {
		75  		t.Fatalf("extra is %q, want %q", r.Extra, "extra")
		76  	}
		77  	if r.ModTime.Unix() != 1e8 {
		78  		t.Fatalf("mtime is %d, want %d", r.ModTime.Unix(), uint32(1e8))
		79  	}
		80  	if r.Name != "name" {
		81  		t.Fatalf("name is %q, want %q", r.Name, "name")
		82  	}
		83  	if err := r.Close(); err != nil {
		84  		t.Fatalf("Reader.Close: %v", err)
		85  	}
		86  }
		87  
		88  // TestLatin1 tests the internal functions for converting to and from Latin-1.
		89  func TestLatin1(t *testing.T) {
		90  	latin1 := []byte{0xc4, 'u', 0xdf, 'e', 'r', 'u', 'n', 'g', 0}
		91  	utf8 := "Äußerung"
		92  	z := Reader{r: bufio.NewReader(bytes.NewReader(latin1))}
		93  	s, err := z.readString()
		94  	if err != nil {
		95  		t.Fatalf("readString: %v", err)
		96  	}
		97  	if s != utf8 {
		98  		t.Fatalf("read latin-1: got %q, want %q", s, utf8)
		99  	}
	 100  
	 101  	buf := bytes.NewBuffer(make([]byte, 0, len(latin1)))
	 102  	c := Writer{w: buf}
	 103  	if err = c.writeString(utf8); err != nil {
	 104  		t.Fatalf("writeString: %v", err)
	 105  	}
	 106  	s = buf.String()
	 107  	if s != string(latin1) {
	 108  		t.Fatalf("write utf-8: got %q, want %q", s, string(latin1))
	 109  	}
	 110  }
	 111  
	 112  // TestLatin1RoundTrip tests that metadata that is representable in Latin-1
	 113  // survives a round trip.
	 114  func TestLatin1RoundTrip(t *testing.T) {
	 115  	testCases := []struct {
	 116  		name string
	 117  		ok	 bool
	 118  	}{
	 119  		{"", true},
	 120  		{"ASCII is OK", true},
	 121  		{"unless it contains a NUL\x00", false},
	 122  		{"no matter where \x00 occurs", false},
	 123  		{"\x00\x00\x00", false},
	 124  		{"Látin-1 also passes (U+00E1)", true},
	 125  		{"but LĀtin Extended-A (U+0100) does not", false},
	 126  		{"neither does 日本語", false},
	 127  		{"invalid UTF-8 also \xffails", false},
	 128  		{"\x00 as does Látin-1 with NUL", false},
	 129  	}
	 130  	for _, tc := range testCases {
	 131  		buf := new(bytes.Buffer)
	 132  
	 133  		w := NewWriter(buf)
	 134  		w.Name = tc.name
	 135  		err := w.Close()
	 136  		if (err == nil) != tc.ok {
	 137  			t.Errorf("Writer.Close: name = %q, err = %v", tc.name, err)
	 138  			continue
	 139  		}
	 140  		if !tc.ok {
	 141  			continue
	 142  		}
	 143  
	 144  		r, err := NewReader(buf)
	 145  		if err != nil {
	 146  			t.Errorf("NewReader: %v", err)
	 147  			continue
	 148  		}
	 149  		_, err = io.ReadAll(r)
	 150  		if err != nil {
	 151  			t.Errorf("ReadAll: %v", err)
	 152  			continue
	 153  		}
	 154  		if r.Name != tc.name {
	 155  			t.Errorf("name is %q, want %q", r.Name, tc.name)
	 156  			continue
	 157  		}
	 158  		if err := r.Close(); err != nil {
	 159  			t.Errorf("Reader.Close: %v", err)
	 160  			continue
	 161  		}
	 162  	}
	 163  }
	 164  
	 165  func TestWriterFlush(t *testing.T) {
	 166  	buf := new(bytes.Buffer)
	 167  
	 168  	w := NewWriter(buf)
	 169  	w.Comment = "comment"
	 170  	w.Extra = []byte("extra")
	 171  	w.ModTime = time.Unix(1e8, 0)
	 172  	w.Name = "name"
	 173  
	 174  	n0 := buf.Len()
	 175  	if n0 != 0 {
	 176  		t.Fatalf("buffer size = %d before writes; want 0", n0)
	 177  	}
	 178  
	 179  	if err := w.Flush(); err != nil {
	 180  		t.Fatal(err)
	 181  	}
	 182  
	 183  	n1 := buf.Len()
	 184  	if n1 == 0 {
	 185  		t.Fatal("no data after first flush")
	 186  	}
	 187  
	 188  	w.Write([]byte("x"))
	 189  
	 190  	n2 := buf.Len()
	 191  	if n1 != n2 {
	 192  		t.Fatalf("after writing a single byte, size changed from %d to %d; want no change", n1, n2)
	 193  	}
	 194  
	 195  	if err := w.Flush(); err != nil {
	 196  		t.Fatal(err)
	 197  	}
	 198  
	 199  	n3 := buf.Len()
	 200  	if n2 == n3 {
	 201  		t.Fatal("Flush didn't flush any data")
	 202  	}
	 203  }
	 204  
	 205  // Multiple gzip files concatenated form a valid gzip file.
	 206  func TestConcat(t *testing.T) {
	 207  	var buf bytes.Buffer
	 208  	w := NewWriter(&buf)
	 209  	w.Write([]byte("hello "))
	 210  	w.Close()
	 211  	w = NewWriter(&buf)
	 212  	w.Write([]byte("world\n"))
	 213  	w.Close()
	 214  
	 215  	r, err := NewReader(&buf)
	 216  	if err != nil {
	 217  		t.Fatal(err)
	 218  	}
	 219  	data, err := io.ReadAll(r)
	 220  	if string(data) != "hello world\n" || err != nil {
	 221  		t.Fatalf("ReadAll = %q, %v, want %q, nil", data, err, "hello world")
	 222  	}
	 223  }
	 224  
	 225  func TestWriterReset(t *testing.T) {
	 226  	buf := new(bytes.Buffer)
	 227  	buf2 := new(bytes.Buffer)
	 228  	z := NewWriter(buf)
	 229  	msg := []byte("hello world")
	 230  	z.Write(msg)
	 231  	z.Close()
	 232  	z.Reset(buf2)
	 233  	z.Write(msg)
	 234  	z.Close()
	 235  	if buf.String() != buf2.String() {
	 236  		t.Errorf("buf2 %q != original buf of %q", buf2.String(), buf.String())
	 237  	}
	 238  }
	 239  
	 240  type limitedWriter struct {
	 241  	N int
	 242  }
	 243  
	 244  func (l *limitedWriter) Write(p []byte) (n int, err error) {
	 245  	if n := l.N; n < len(p) {
	 246  		l.N = 0
	 247  		return n, io.ErrShortWrite
	 248  	}
	 249  	l.N -= len(p)
	 250  	return len(p), nil
	 251  }
	 252  
	 253  // Write should never return more bytes than the input slice.
	 254  func TestLimitedWrite(t *testing.T) {
	 255  	msg := []byte("a")
	 256  
	 257  	for lim := 2; lim < 20; lim++ {
	 258  		z := NewWriter(&limitedWriter{lim})
	 259  		if n, _ := z.Write(msg); n > len(msg) {
	 260  			t.Errorf("Write() = %d, want %d or less", n, len(msg))
	 261  		}
	 262  
	 263  		z.Reset(&limitedWriter{lim})
	 264  		z.Header = Header{
	 265  			Comment: "comment",
	 266  			Extra:	 []byte("extra"),
	 267  			ModTime: time.Now(),
	 268  			Name:		"name",
	 269  			OS:			1,
	 270  		}
	 271  		if n, _ := z.Write(msg); n > len(msg) {
	 272  			t.Errorf("Write() = %d, want %d or less", n, len(msg))
	 273  		}
	 274  	}
	 275  }
	 276  

View as plain text