...

Source file src/github.com/klauspost/compress/flate/inflate_test.go

Documentation: github.com/klauspost/compress/flate

     1  // Copyright 2014 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 flate
     6  
     7  import (
     8  	"bytes"
     9  	"crypto/rand"
    10  	"io"
    11  	"strconv"
    12  	"strings"
    13  	"testing"
    14  )
    15  
    16  func TestReset(t *testing.T) {
    17  	ss := []string{
    18  		"lorem ipsum izzle fo rizzle",
    19  		"the quick brown fox jumped over",
    20  	}
    21  
    22  	deflated := make([]bytes.Buffer, 2)
    23  	for i, s := range ss {
    24  		w, _ := NewWriter(&deflated[i], 1)
    25  		w.Write([]byte(s))
    26  		w.Close()
    27  	}
    28  
    29  	inflated := make([]bytes.Buffer, 2)
    30  
    31  	f := NewReader(&deflated[0])
    32  	io.Copy(&inflated[0], f)
    33  	f.(Resetter).Reset(&deflated[1], nil)
    34  	io.Copy(&inflated[1], f)
    35  	f.Close()
    36  
    37  	for i, s := range ss {
    38  		if s != inflated[i].String() {
    39  			t.Errorf("inflated[%d]:\ngot  %q\nwant %q", i, inflated[i], s)
    40  		}
    41  	}
    42  }
    43  
    44  func TestReaderTruncated(t *testing.T) {
    45  	vectors := []struct{ input, output string }{
    46  		{"\x00", ""},
    47  		{"\x00\f", ""},
    48  		{"\x00\f\x00", ""},
    49  		{"\x00\f\x00\xf3\xff", ""},
    50  		{"\x00\f\x00\xf3\xffhello", "hello"},
    51  		{"\x00\f\x00\xf3\xffhello, world", "hello, world"},
    52  		{"\x02", ""},
    53  		{"\xf2H\xcd", "He"},
    54  		{"\xf2H͙0a\u0084\t", "Hel\x90\x90\x90\x90\x90"},
    55  		{"\xf2H͙0a\u0084\t\x00", "Hel\x90\x90\x90\x90\x90"},
    56  	}
    57  
    58  	for i, v := range vectors {
    59  		r := strings.NewReader(v.input)
    60  		zr := NewReader(r)
    61  		b, err := io.ReadAll(zr)
    62  		if err != io.ErrUnexpectedEOF {
    63  			t.Errorf("test %d, error mismatch: got %v, want io.ErrUnexpectedEOF", i, err)
    64  		}
    65  		if string(b) != v.output {
    66  			t.Errorf("test %d, output mismatch: got %q, want %q", i, b, v.output)
    67  		}
    68  	}
    69  }
    70  
    71  func TestResetDict(t *testing.T) {
    72  	dict := []byte("the lorem fox")
    73  	ss := []string{
    74  		"lorem ipsum izzle fo rizzle",
    75  		"the quick brown fox jumped over",
    76  	}
    77  
    78  	deflated := make([]bytes.Buffer, len(ss))
    79  	for i, s := range ss {
    80  		w, _ := NewWriterDict(&deflated[i], DefaultCompression, dict)
    81  		w.Write([]byte(s))
    82  		w.Close()
    83  	}
    84  
    85  	inflated := make([]bytes.Buffer, len(ss))
    86  
    87  	f := NewReader(nil)
    88  	for i := range inflated {
    89  		f.(Resetter).Reset(&deflated[i], dict)
    90  		io.Copy(&inflated[i], f)
    91  	}
    92  	f.Close()
    93  
    94  	for i, s := range ss {
    95  		if s != inflated[i].String() {
    96  			t.Errorf("inflated[%d]:\ngot  %q\nwant %q", i, inflated[i], s)
    97  		}
    98  	}
    99  }
   100  
   101  // Tests ported from zlib/test/infcover.c
   102  type infTest struct {
   103  	hex string
   104  	id  string
   105  	n   int
   106  }
   107  
   108  var infTests = []infTest{
   109  	{"0 0 0 0 0", "invalid stored block lengths", 1},
   110  	{"3 0", "fixed", 0},
   111  	{"6", "invalid block type", 1},
   112  	{"1 1 0 fe ff 0", "stored", 0},
   113  	{"fc 0 0", "too many length or distance symbols", 1},
   114  	{"4 0 fe ff", "invalid code lengths set", 1},
   115  	{"4 0 24 49 0", "invalid bit length repeat", 1},
   116  	{"4 0 24 e9 ff ff", "invalid bit length repeat", 1},
   117  	{"4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1},
   118  	{"4 80 49 92 24 49 92 24 71 ff ff 93 11 0", "invalid literal/lengths set", 1},
   119  	{"4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1},
   120  	{"4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1},
   121  	{"2 7e ff ff", "invalid distance code", 1},
   122  	{"c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1},
   123  
   124  	// also trailer mismatch just in inflate()
   125  	{"1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1},
   126  	{"1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", "incorrect length check", -1},
   127  	{"5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0},
   128  	{"5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", "long code", 0},
   129  	{"ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0},
   130  	{"ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c", "long distance and extra", 0},
   131  	{"ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0},
   132  }
   133  
   134  func TestInflate(t *testing.T) {
   135  	for _, test := range infTests {
   136  		hex := strings.Split(test.hex, " ")
   137  		data := make([]byte, len(hex))
   138  		for i, h := range hex {
   139  			b, _ := strconv.ParseInt(h, 16, 32)
   140  			data[i] = byte(b)
   141  		}
   142  		buf := bytes.NewReader(data)
   143  		r := NewReader(buf)
   144  
   145  		_, err := io.Copy(io.Discard, r)
   146  		if (test.n == 0 && err == nil) || (test.n != 0 && err != nil) {
   147  			t.Logf("%q: OK:", test.id)
   148  			t.Logf(" - got %v", err)
   149  			continue
   150  		}
   151  
   152  		if test.n == 0 && err != nil {
   153  			t.Errorf("%q: Expected no error, but got %v", test.id, err)
   154  			continue
   155  		}
   156  
   157  		if test.n != 0 && err == nil {
   158  			t.Errorf("%q:Expected an error, but got none", test.id)
   159  			continue
   160  		}
   161  		t.Fatal(test.n, err)
   162  	}
   163  
   164  	for _, test := range infOutTests {
   165  		hex := strings.Split(test.hex, " ")
   166  		data := make([]byte, len(hex))
   167  		for i, h := range hex {
   168  			b, _ := strconv.ParseInt(h, 16, 32)
   169  			data[i] = byte(b)
   170  		}
   171  		buf := bytes.NewReader(data)
   172  		r := NewReader(buf)
   173  
   174  		_, err := io.Copy(io.Discard, r)
   175  		if test.err == (err != nil) {
   176  			t.Logf("%q: OK:", test.id)
   177  			t.Logf(" - got %v", err)
   178  			continue
   179  		}
   180  
   181  		if test.err == false && err != nil {
   182  			t.Errorf("%q: Expected no error, but got %v", test.id, err)
   183  			continue
   184  		}
   185  
   186  		if test.err && err == nil {
   187  			t.Errorf("%q: Expected an error, but got none", test.id)
   188  			continue
   189  		}
   190  		t.Fatal(test.err, err)
   191  	}
   192  
   193  }
   194  
   195  // Tests ported from zlib/test/infcover.c
   196  // Since zlib inflate is push (writer) instead of pull (reader)
   197  // some of the window size tests have been removed, since they
   198  // are irrelevant.
   199  type infOutTest struct {
   200  	hex    string
   201  	id     string
   202  	step   int
   203  	win    int
   204  	length int
   205  	err    bool
   206  }
   207  
   208  var infOutTests = []infOutTest{
   209  	{"2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, false},
   210  	{"63 18 5 40 c 0", "window wrap", 3, -8, 300, false},
   211  	{"e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68 ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, true},
   212  	{"25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, true},
   213  	{"3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, true},
   214  	{"1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, true},
   215  	{"d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0", "fast 2nd level codes and too far back", 0, -8, 258, true},
   216  	{"63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, false},
   217  	{"63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", "contiguous and wrap around window", 6, -8, 259, false},
   218  	{"63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, false},
   219  	{"1f 8b 0 0", "bad gzip method", 0, 31, 0, true},
   220  	{"1f 8b 8 80", "bad gzip flags", 0, 31, 0, true},
   221  	{"77 85", "bad zlib method", 0, 15, 0, true},
   222  	{"78 9c", "bad zlib window size", 0, 8, 0, true},
   223  	{"1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, true},
   224  	{"1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length", 0, 47, 0, true},
   225  	{"78 90", "bad zlib header check", 0, 47, 0, true},
   226  	{"8 b8 0 0 0 1", "need dictionary", 0, 8, 0, true},
   227  	{"63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, false},
   228  	{"3 0", "use fixed blocks", 0, -15, 1, false},
   229  	{"", "bad window size", 0, 1, 0, true},
   230  }
   231  
   232  func TestWriteTo(t *testing.T) {
   233  	input := make([]byte, 100000)
   234  	n, err := rand.Read(input)
   235  	if err != nil {
   236  		t.Fatal(err)
   237  	}
   238  	if n != len(input) {
   239  		t.Fatal("did not fill buffer")
   240  	}
   241  	compressed := &bytes.Buffer{}
   242  	w, err := NewWriter(compressed, -2)
   243  	if err != nil {
   244  		t.Fatal(err)
   245  	}
   246  	n, err = w.Write(input)
   247  	if err != nil {
   248  		t.Fatal(err)
   249  	}
   250  	if n != len(input) {
   251  		t.Fatal("did not fill buffer")
   252  	}
   253  	w.Close()
   254  	buf := compressed.Bytes()
   255  
   256  	dec := NewReader(bytes.NewBuffer(buf))
   257  	// ReadAll does not use WriteTo, but we wrap it in a NopCloser to be sure.
   258  	readall, err := io.ReadAll(io.NopCloser(dec))
   259  	if err != nil {
   260  		t.Fatal(err)
   261  	}
   262  	if len(readall) != len(input) {
   263  		t.Fatal("did not decompress everything")
   264  	}
   265  
   266  	dec = NewReader(bytes.NewBuffer(buf))
   267  	wtbuf := &bytes.Buffer{}
   268  	written, err := dec.(io.WriterTo).WriteTo(wtbuf)
   269  	if err != nil {
   270  		t.Fatal(err)
   271  	}
   272  	if written != int64(len(input)) {
   273  		t.Error("Returned length did not match, expected", len(input), "got", written)
   274  	}
   275  	if wtbuf.Len() != len(input) {
   276  		t.Error("Actual Length did not match, expected", len(input), "got", wtbuf.Len())
   277  	}
   278  	if !bytes.Equal(wtbuf.Bytes(), input) {
   279  		t.Fatal("output did not match input")
   280  	}
   281  }
   282  

View as plain text