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