...
Run Format

Source file src/compress/flate/flate_test.go

Documentation: compress/flate

  // Copyright 2009 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  // This test tests some internals of the flate package.
  // The tests in package compress/gzip serve as the
  // end-to-end test of the decompressor.
  
  package flate
  
  import (
  	"bytes"
  	"encoding/hex"
  	"io"
  	"io/ioutil"
  	"strings"
  	"testing"
  )
  
  // The following test should not panic.
  func TestIssue5915(t *testing.T) {
  	bits := []int{4, 0, 0, 6, 4, 3, 2, 3, 3, 4, 4, 5, 0, 0, 0, 0, 5, 5, 6,
  		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 6, 0, 11, 0, 8, 0, 6, 6, 10, 8}
  	var h huffmanDecoder
  	if h.init(bits) {
  		t.Fatalf("Given sequence of bits is bad, and should not succeed.")
  	}
  }
  
  // The following test should not panic.
  func TestIssue5962(t *testing.T) {
  	bits := []int{4, 0, 0, 6, 4, 3, 2, 3, 3, 4, 4, 5, 0, 0, 0, 0,
  		5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}
  	var h huffmanDecoder
  	if h.init(bits) {
  		t.Fatalf("Given sequence of bits is bad, and should not succeed.")
  	}
  }
  
  // The following test should not panic.
  func TestIssue6255(t *testing.T) {
  	bits1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11}
  	bits2 := []int{11, 13}
  	var h huffmanDecoder
  	if !h.init(bits1) {
  		t.Fatalf("Given sequence of bits is good and should succeed.")
  	}
  	if h.init(bits2) {
  		t.Fatalf("Given sequence of bits is bad and should not succeed.")
  	}
  }
  
  func TestInvalidEncoding(t *testing.T) {
  	// Initialize Huffman decoder to recognize "0".
  	var h huffmanDecoder
  	if !h.init([]int{1}) {
  		t.Fatal("Failed to initialize Huffman decoder")
  	}
  
  	// Initialize decompressor with invalid Huffman coding.
  	var f decompressor
  	f.r = bytes.NewReader([]byte{0xff})
  
  	_, err := f.huffSym(&h)
  	if err == nil {
  		t.Fatal("Should have rejected invalid bit sequence")
  	}
  }
  
  func TestInvalidBits(t *testing.T) {
  	oversubscribed := []int{1, 2, 3, 4, 4, 5}
  	incomplete := []int{1, 2, 4, 4}
  	var h huffmanDecoder
  	if h.init(oversubscribed) {
  		t.Fatal("Should reject oversubscribed bit-length set")
  	}
  	if h.init(incomplete) {
  		t.Fatal("Should reject incomplete bit-length set")
  	}
  }
  
  func TestStreams(t *testing.T) {
  	// To verify any of these hexstrings as valid or invalid flate streams
  	// according to the C zlib library, you can use the Python wrapper library:
  	// >>> hex_string = "010100feff11"
  	// >>> import zlib
  	// >>> zlib.decompress(hex_string.decode("hex"), -15) # Negative means raw DEFLATE
  	// '\x11'
  
  	testCases := []struct {
  		desc   string // Description of the stream
  		stream string // Hexstring of the input DEFLATE stream
  		want   string // Expected result. Use "fail" to expect failure
  	}{{
  		"degenerate HCLenTree",
  		"05e0010000000000100000000000000000000000000000000000000000000000" +
  			"00000000000000000004",
  		"fail",
  	}, {
  		"complete HCLenTree, empty HLitTree, empty HDistTree",
  		"05e0010400000000000000000000000000000000000000000000000000000000" +
  			"00000000000000000010",
  		"fail",
  	}, {
  		"empty HCLenTree",
  		"05e0010000000000000000000000000000000000000000000000000000000000" +
  			"00000000000000000010",
  		"fail",
  	}, {
  		"complete HCLenTree, complete HLitTree, empty HDistTree, use missing HDist symbol",
  		"000100feff000de0010400000000100000000000000000000000000000000000" +
  			"0000000000000000000000000000002c",
  		"fail",
  	}, {
  		"complete HCLenTree, complete HLitTree, degenerate HDistTree, use missing HDist symbol",
  		"000100feff000de0010000000000000000000000000000000000000000000000" +
  			"00000000000000000610000000004070",
  		"fail",
  	}, {
  		"complete HCLenTree, empty HLitTree, empty HDistTree",
  		"05e0010400000000100400000000000000000000000000000000000000000000" +
  			"0000000000000000000000000008",
  		"fail",
  	}, {
  		"complete HCLenTree, empty HLitTree, degenerate HDistTree",
  		"05e0010400000000100400000000000000000000000000000000000000000000" +
  			"0000000000000000000800000008",
  		"fail",
  	}, {
  		"complete HCLenTree, degenerate HLitTree, degenerate HDistTree, use missing HLit symbol",
  		"05e0010400000000100000000000000000000000000000000000000000000000" +
  			"0000000000000000001c",
  		"fail",
  	}, {
  		"complete HCLenTree, complete HLitTree, too large HDistTree",
  		"edff870500000000200400000000000000000000000000000000000000000000" +
  			"000000000000000000080000000000000004",
  		"fail",
  	}, {
  		"complete HCLenTree, complete HLitTree, empty HDistTree, excessive repeater code",
  		"edfd870500000000200400000000000000000000000000000000000000000000" +
  			"000000000000000000e8b100",
  		"fail",
  	}, {
  		"complete HCLenTree, complete HLitTree, empty HDistTree of normal length 30",
  		"05fd01240000000000f8ffffffffffffffffffffffffffffffffffffffffffff" +
  			"ffffffffffffffffff07000000fe01",
  		"",
  	}, {
  		"complete HCLenTree, complete HLitTree, empty HDistTree of excessive length 31",
  		"05fe01240000000000f8ffffffffffffffffffffffffffffffffffffffffffff" +
  			"ffffffffffffffffff07000000fc03",
  		"fail",
  	}, {
  		"complete HCLenTree, over-subscribed HLitTree, empty HDistTree",
  		"05e001240000000000fcffffffffffffffffffffffffffffffffffffffffffff" +
  			"ffffffffffffffffff07f00f",
  		"fail",
  	}, {
  		"complete HCLenTree, under-subscribed HLitTree, empty HDistTree",
  		"05e001240000000000fcffffffffffffffffffffffffffffffffffffffffffff" +
  			"fffffffffcffffffff07f00f",
  		"fail",
  	}, {
  		"complete HCLenTree, complete HLitTree with single code, empty HDistTree",
  		"05e001240000000000f8ffffffffffffffffffffffffffffffffffffffffffff" +
  			"ffffffffffffffffff07f00f",
  		"01",
  	}, {
  		"complete HCLenTree, complete HLitTree with multiple codes, empty HDistTree",
  		"05e301240000000000f8ffffffffffffffffffffffffffffffffffffffffffff" +
  			"ffffffffffffffffff07807f",
  		"01",
  	}, {
  		"complete HCLenTree, complete HLitTree, degenerate HDistTree, use valid HDist symbol",
  		"000100feff000de0010400000000100000000000000000000000000000000000" +
  			"0000000000000000000000000000003c",
  		"00000000",
  	}, {
  		"complete HCLenTree, degenerate HLitTree, degenerate HDistTree",
  		"05e0010400000000100000000000000000000000000000000000000000000000" +
  			"0000000000000000000c",
  		"",
  	}, {
  		"complete HCLenTree, degenerate HLitTree, empty HDistTree",
  		"05e0010400000000100000000000000000000000000000000000000000000000" +
  			"00000000000000000004",
  		"",
  	}, {
  		"complete HCLenTree, complete HLitTree, empty HDistTree, spanning repeater code",
  		"edfd870500000000200400000000000000000000000000000000000000000000" +
  			"000000000000000000e8b000",
  		"",
  	}, {
  		"complete HCLenTree with length codes, complete HLitTree, empty HDistTree",
  		"ede0010400000000100000000000000000000000000000000000000000000000" +
  			"0000000000000000000400004000",
  		"",
  	}, {
  		"complete HCLenTree, complete HLitTree, degenerate HDistTree, use valid HLit symbol 284 with count 31",
  		"000100feff00ede0010400000000100000000000000000000000000000000000" +
  			"000000000000000000000000000000040000407f00",
  		"0000000000000000000000000000000000000000000000000000000000000000" +
  			"0000000000000000000000000000000000000000000000000000000000000000" +
  			"0000000000000000000000000000000000000000000000000000000000000000" +
  			"0000000000000000000000000000000000000000000000000000000000000000" +
  			"0000000000000000000000000000000000000000000000000000000000000000" +
  			"0000000000000000000000000000000000000000000000000000000000000000" +
  			"0000000000000000000000000000000000000000000000000000000000000000" +
  			"0000000000000000000000000000000000000000000000000000000000000000" +
  			"000000",
  	}, {
  		"complete HCLenTree, complete HLitTree, degenerate HDistTree, use valid HLit and HDist symbols",
  		"0cc2010d00000082b0ac4aff0eb07d27060000ffff",
  		"616263616263",
  	}, {
  		"fixed block, use reserved symbol 287",
  		"33180700",
  		"fail",
  	}, {
  		"raw block",
  		"010100feff11",
  		"11",
  	}, {
  		"issue 10426 - over-subscribed HCLenTree causes a hang",
  		"344c4a4e494d4b070000ff2e2eff2e2e2e2e2eff",
  		"fail",
  	}, {
  		"issue 11030 - empty HDistTree unexpectedly leads to error",
  		"05c0070600000080400fff37a0ca",
  		"",
  	}, {
  		"issue 11033 - empty HDistTree unexpectedly leads to error",
  		"050fb109c020cca5d017dcbca044881ee1034ec149c8980bbc413c2ab35be9dc" +
  			"b1473449922449922411202306ee97b0383a521b4ffdcf3217f9f7d3adb701",
  		"3130303634342068652e706870005d05355f7ed957ff084a90925d19e3ebc6d0" +
  			"c6d7",
  	}}
  
  	for i, tc := range testCases {
  		data, err := hex.DecodeString(tc.stream)
  		if err != nil {
  			t.Fatal(err)
  		}
  		data, err = ioutil.ReadAll(NewReader(bytes.NewReader(data)))
  		if tc.want == "fail" {
  			if err == nil {
  				t.Errorf("#%d (%s): got nil error, want non-nil", i, tc.desc)
  			}
  		} else {
  			if err != nil {
  				t.Errorf("#%d (%s): %v", i, tc.desc, err)
  				continue
  			}
  			if got := hex.EncodeToString(data); got != tc.want {
  				t.Errorf("#%d (%s):\ngot  %q\nwant %q", i, tc.desc, got, tc.want)
  			}
  
  		}
  	}
  }
  
  func TestTruncatedStreams(t *testing.T) {
  	const data = "\x00\f\x00\xf3\xffhello, world\x01\x00\x00\xff\xff"
  
  	for i := 0; i < len(data)-1; i++ {
  		r := NewReader(strings.NewReader(data[:i]))
  		_, err := io.Copy(ioutil.Discard, r)
  		if err != io.ErrUnexpectedEOF {
  			t.Errorf("io.Copy(%d) on truncated stream: got %v, want %v", i, err, io.ErrUnexpectedEOF)
  		}
  	}
  }
  
  // Verify that flate.Reader.Read returns (n, io.EOF) instead
  // of (n, nil) + (0, io.EOF) when possible.
  //
  // This helps net/http.Transport reuse HTTP/1 connections more
  // aggressively.
  //
  // See https://github.com/google/go-github/pull/317 for background.
  func TestReaderEarlyEOF(t *testing.T) {
  	t.Parallel()
  	testSizes := []int{
  		1, 2, 3, 4, 5, 6, 7, 8,
  		100, 1000, 10000, 100000,
  		128, 1024, 16384, 131072,
  
  		// Testing multiples of windowSize triggers the case
  		// where Read will fail to return an early io.EOF.
  		windowSize * 1, windowSize * 2, windowSize * 3,
  	}
  
  	var maxSize int
  	for _, n := range testSizes {
  		if maxSize < n {
  			maxSize = n
  		}
  	}
  
  	readBuf := make([]byte, 40)
  	data := make([]byte, maxSize)
  	for i := range data {
  		data[i] = byte(i)
  	}
  
  	for _, sz := range testSizes {
  		if testing.Short() && sz > windowSize {
  			continue
  		}
  		for _, flush := range []bool{true, false} {
  			earlyEOF := true // Do we expect early io.EOF?
  
  			var buf bytes.Buffer
  			w, _ := NewWriter(&buf, 5)
  			w.Write(data[:sz])
  			if flush {
  				// If a Flush occurs after all the actual data, the flushing
  				// semantics dictate that we will observe a (0, io.EOF) since
  				// Read must return data before it knows that the stream ended.
  				w.Flush()
  				earlyEOF = false
  			}
  			w.Close()
  
  			r := NewReader(&buf)
  			for {
  				n, err := r.Read(readBuf)
  				if err == io.EOF {
  					// If the availWrite == windowSize, then that means that the
  					// previous Read returned because the write buffer was full
  					// and it just so happened that the stream had no more data.
  					// This situation is rare, but unavoidable.
  					if r.(*decompressor).dict.availWrite() == windowSize {
  						earlyEOF = false
  					}
  
  					if n == 0 && earlyEOF {
  						t.Errorf("On size:%d flush:%v, Read() = (0, io.EOF), want (n, io.EOF)", sz, flush)
  					}
  					if n != 0 && !earlyEOF {
  						t.Errorf("On size:%d flush:%v, Read() = (%d, io.EOF), want (0, io.EOF)", sz, flush, n)
  					}
  					break
  				}
  				if err != nil {
  					t.Fatal(err)
  				}
  			}
  		}
  	}
  }
  

View as plain text