Home | History | Annotate | Download | only in 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/ioutil"
     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 := ioutil.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 := ioutil.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 := "uerung"
     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 		{"Ltin-1 also passes (U+00E1)", true},
    125 		{"but Ltin Extended-A (U+0100) does not", false},
    126 		{"neither does ", false},
    127 		{"invalid UTF-8 also \xffails", false},
    128 		{"\x00 as does Ltin-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 = ioutil.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 	data, err := ioutil.ReadAll(r)
    217 	if string(data) != "hello world\n" || err != nil {
    218 		t.Fatalf("ReadAll = %q, %v, want %q, nil", data, err, "hello world")
    219 	}
    220 }
    221 
    222 func TestWriterReset(t *testing.T) {
    223 	buf := new(bytes.Buffer)
    224 	buf2 := new(bytes.Buffer)
    225 	z := NewWriter(buf)
    226 	msg := []byte("hello world")
    227 	z.Write(msg)
    228 	z.Close()
    229 	z.Reset(buf2)
    230 	z.Write(msg)
    231 	z.Close()
    232 	if buf.String() != buf2.String() {
    233 		t.Errorf("buf2 %q != original buf of %q", buf2.String(), buf.String())
    234 	}
    235 }
    236