github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/compress/flate/deflate_test.go (about)

     1  // Copyright 2009 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  	"errors"
    10  	"fmt"
    11  	"internal/testenv"
    12  	"io"
    13  	"io/ioutil"
    14  	"reflect"
    15  	"runtime/debug"
    16  	"sync"
    17  	"testing"
    18  )
    19  
    20  type deflateTest struct {
    21  	in    []byte
    22  	level int
    23  	out   []byte
    24  }
    25  
    26  type deflateInflateTest struct {
    27  	in []byte
    28  }
    29  
    30  type reverseBitsTest struct {
    31  	in       uint16
    32  	bitCount uint8
    33  	out      uint16
    34  }
    35  
    36  var deflateTests = []*deflateTest{
    37  	{[]byte{}, 0, []byte{1, 0, 0, 255, 255}},
    38  	{[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}},
    39  	{[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}},
    40  	{[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}},
    41  
    42  	{[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}},
    43  	{[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}},
    44  	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0,
    45  		[]byte{0, 8, 0, 247, 255, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0, 0, 255, 255},
    46  	},
    47  	{[]byte{}, 2, []byte{1, 0, 0, 255, 255}},
    48  	{[]byte{0x11}, 2, []byte{18, 4, 4, 0, 0, 255, 255}},
    49  	{[]byte{0x11, 0x12}, 2, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
    50  	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 2, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
    51  	{[]byte{}, 9, []byte{1, 0, 0, 255, 255}},
    52  	{[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}},
    53  	{[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
    54  	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
    55  }
    56  
    57  var deflateInflateTests = []*deflateInflateTest{
    58  	{[]byte{}},
    59  	{[]byte{0x11}},
    60  	{[]byte{0x11, 0x12}},
    61  	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
    62  	{[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}},
    63  	{largeDataChunk()},
    64  }
    65  
    66  var reverseBitsTests = []*reverseBitsTest{
    67  	{1, 1, 1},
    68  	{1, 2, 2},
    69  	{1, 3, 4},
    70  	{1, 4, 8},
    71  	{1, 5, 16},
    72  	{17, 5, 17},
    73  	{257, 9, 257},
    74  	{29, 5, 23},
    75  }
    76  
    77  func largeDataChunk() []byte {
    78  	result := make([]byte, 100000)
    79  	for i := range result {
    80  		result[i] = byte(i * i & 0xFF)
    81  	}
    82  	return result
    83  }
    84  
    85  func TestBulkHash4(t *testing.T) {
    86  	for _, x := range deflateTests {
    87  		y := x.out
    88  		if len(y) < minMatchLength {
    89  			continue
    90  		}
    91  		y = append(y, y...)
    92  		for j := 4; j < len(y); j++ {
    93  			y := y[:j]
    94  			dst := make([]uint32, len(y)-minMatchLength+1)
    95  			for i := range dst {
    96  				dst[i] = uint32(i + 100)
    97  			}
    98  			bulkHash4(y, dst)
    99  			for i, got := range dst {
   100  				want := hash4(y[i:])
   101  				if got != want && got == uint32(i)+100 {
   102  					t.Errorf("Len:%d Index:%d, want 0x%08x but not modified", len(y), i, want)
   103  				} else if got != want {
   104  					t.Errorf("Len:%d Index:%d, got 0x%08x want:0x%08x", len(y), i, got, want)
   105  				}
   106  			}
   107  		}
   108  	}
   109  }
   110  
   111  func TestDeflate(t *testing.T) {
   112  	for _, h := range deflateTests {
   113  		var buf bytes.Buffer
   114  		w, err := NewWriter(&buf, h.level)
   115  		if err != nil {
   116  			t.Errorf("NewWriter: %v", err)
   117  			continue
   118  		}
   119  		w.Write(h.in)
   120  		w.Close()
   121  		if !bytes.Equal(buf.Bytes(), h.out) {
   122  			t.Errorf("Deflate(%d, %x) = \n%#v, want \n%#v", h.level, h.in, buf.Bytes(), h.out)
   123  		}
   124  	}
   125  }
   126  
   127  // A sparseReader returns a stream consisting of 0s followed by 1<<16 1s.
   128  // This tests missing hash references in a very large input.
   129  type sparseReader struct {
   130  	l   int64
   131  	cur int64
   132  }
   133  
   134  func (r *sparseReader) Read(b []byte) (n int, err error) {
   135  	if r.cur >= r.l {
   136  		return 0, io.EOF
   137  	}
   138  	n = len(b)
   139  	cur := r.cur + int64(n)
   140  	if cur > r.l {
   141  		n -= int(cur - r.l)
   142  		cur = r.l
   143  	}
   144  	for i := range b[0:n] {
   145  		if r.cur+int64(i) >= r.l-1<<16 {
   146  			b[i] = 1
   147  		} else {
   148  			b[i] = 0
   149  		}
   150  	}
   151  	r.cur = cur
   152  	return
   153  }
   154  
   155  func TestVeryLongSparseChunk(t *testing.T) {
   156  	if testing.Short() {
   157  		t.Skip("skipping sparse chunk during short test")
   158  	}
   159  	w, err := NewWriter(ioutil.Discard, 1)
   160  	if err != nil {
   161  		t.Errorf("NewWriter: %v", err)
   162  		return
   163  	}
   164  	if _, err = io.Copy(w, &sparseReader{l: 23e8}); err != nil {
   165  		t.Errorf("Compress failed: %v", err)
   166  		return
   167  	}
   168  }
   169  
   170  type syncBuffer struct {
   171  	buf    bytes.Buffer
   172  	mu     sync.RWMutex
   173  	closed bool
   174  	ready  chan bool
   175  }
   176  
   177  func newSyncBuffer() *syncBuffer {
   178  	return &syncBuffer{ready: make(chan bool, 1)}
   179  }
   180  
   181  func (b *syncBuffer) Read(p []byte) (n int, err error) {
   182  	for {
   183  		b.mu.RLock()
   184  		n, err = b.buf.Read(p)
   185  		b.mu.RUnlock()
   186  		if n > 0 || b.closed {
   187  			return
   188  		}
   189  		<-b.ready
   190  	}
   191  }
   192  
   193  func (b *syncBuffer) signal() {
   194  	select {
   195  	case b.ready <- true:
   196  	default:
   197  	}
   198  }
   199  
   200  func (b *syncBuffer) Write(p []byte) (n int, err error) {
   201  	n, err = b.buf.Write(p)
   202  	b.signal()
   203  	return
   204  }
   205  
   206  func (b *syncBuffer) WriteMode() {
   207  	b.mu.Lock()
   208  }
   209  
   210  func (b *syncBuffer) ReadMode() {
   211  	b.mu.Unlock()
   212  	b.signal()
   213  }
   214  
   215  func (b *syncBuffer) Close() error {
   216  	b.closed = true
   217  	b.signal()
   218  	return nil
   219  }
   220  
   221  func testSync(t *testing.T, level int, input []byte, name string) {
   222  	if len(input) == 0 {
   223  		return
   224  	}
   225  
   226  	t.Logf("--testSync %d, %d, %s", level, len(input), name)
   227  	buf := newSyncBuffer()
   228  	buf1 := new(bytes.Buffer)
   229  	buf.WriteMode()
   230  	w, err := NewWriter(io.MultiWriter(buf, buf1), level)
   231  	if err != nil {
   232  		t.Errorf("NewWriter: %v", err)
   233  		return
   234  	}
   235  	r := NewReader(buf)
   236  
   237  	// Write half the input and read back.
   238  	for i := 0; i < 2; i++ {
   239  		var lo, hi int
   240  		if i == 0 {
   241  			lo, hi = 0, (len(input)+1)/2
   242  		} else {
   243  			lo, hi = (len(input)+1)/2, len(input)
   244  		}
   245  		t.Logf("#%d: write %d-%d", i, lo, hi)
   246  		if _, err := w.Write(input[lo:hi]); err != nil {
   247  			t.Errorf("testSync: write: %v", err)
   248  			return
   249  		}
   250  		if i == 0 {
   251  			if err := w.Flush(); err != nil {
   252  				t.Errorf("testSync: flush: %v", err)
   253  				return
   254  			}
   255  		} else {
   256  			if err := w.Close(); err != nil {
   257  				t.Errorf("testSync: close: %v", err)
   258  			}
   259  		}
   260  		buf.ReadMode()
   261  		out := make([]byte, hi-lo+1)
   262  		m, err := io.ReadAtLeast(r, out, hi-lo)
   263  		t.Logf("#%d: read %d", i, m)
   264  		if m != hi-lo || err != nil {
   265  			t.Errorf("testSync/%d (%d, %d, %s): read %d: %d, %v (%d left)", i, level, len(input), name, hi-lo, m, err, buf.buf.Len())
   266  			return
   267  		}
   268  		if !bytes.Equal(input[lo:hi], out[:hi-lo]) {
   269  			t.Errorf("testSync/%d: read wrong bytes: %x vs %x", i, input[lo:hi], out[:hi-lo])
   270  			return
   271  		}
   272  		// This test originally checked that after reading
   273  		// the first half of the input, there was nothing left
   274  		// in the read buffer (buf.buf.Len() != 0) but that is
   275  		// not necessarily the case: the write Flush may emit
   276  		// some extra framing bits that are not necessary
   277  		// to process to obtain the first half of the uncompressed
   278  		// data. The test ran correctly most of the time, because
   279  		// the background goroutine had usually read even
   280  		// those extra bits by now, but it's not a useful thing to
   281  		// check.
   282  		buf.WriteMode()
   283  	}
   284  	buf.ReadMode()
   285  	out := make([]byte, 10)
   286  	if n, err := r.Read(out); n > 0 || err != io.EOF {
   287  		t.Errorf("testSync (%d, %d, %s): final Read: %d, %v (hex: %x)", level, len(input), name, n, err, out[0:n])
   288  	}
   289  	if buf.buf.Len() != 0 {
   290  		t.Errorf("testSync (%d, %d, %s): extra data at end", level, len(input), name)
   291  	}
   292  	r.Close()
   293  
   294  	// stream should work for ordinary reader too
   295  	r = NewReader(buf1)
   296  	out, err = ioutil.ReadAll(r)
   297  	if err != nil {
   298  		t.Errorf("testSync: read: %s", err)
   299  		return
   300  	}
   301  	r.Close()
   302  	if !bytes.Equal(input, out) {
   303  		t.Errorf("testSync: decompress(compress(data)) != data: level=%d input=%s", level, name)
   304  	}
   305  }
   306  
   307  func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) {
   308  	var buffer bytes.Buffer
   309  	w, err := NewWriter(&buffer, level)
   310  	if err != nil {
   311  		t.Errorf("NewWriter: %v", err)
   312  		return
   313  	}
   314  	w.Write(input)
   315  	w.Close()
   316  	if limit > 0 && buffer.Len() > limit {
   317  		t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit)
   318  		return
   319  	}
   320  	if limit > 0 {
   321  		t.Logf("level: %d, size:%.2f%%, %d b\n", level, float64(buffer.Len()*100)/float64(limit), buffer.Len())
   322  	}
   323  	r := NewReader(&buffer)
   324  	out, err := ioutil.ReadAll(r)
   325  	if err != nil {
   326  		t.Errorf("read: %s", err)
   327  		return
   328  	}
   329  	r.Close()
   330  	if !bytes.Equal(input, out) {
   331  		t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name)
   332  		return
   333  	}
   334  	testSync(t, level, input, name)
   335  }
   336  
   337  func testToFromWithLimit(t *testing.T, input []byte, name string, limit [11]int) {
   338  	for i := 0; i < 10; i++ {
   339  		testToFromWithLevelAndLimit(t, i, input, name, limit[i])
   340  	}
   341  	// Test HuffmanCompression
   342  	testToFromWithLevelAndLimit(t, -2, input, name, limit[10])
   343  }
   344  
   345  func TestDeflateInflate(t *testing.T) {
   346  	t.Parallel()
   347  	for i, h := range deflateInflateTests {
   348  		if testing.Short() && len(h.in) > 10000 {
   349  			continue
   350  		}
   351  		testToFromWithLimit(t, h.in, fmt.Sprintf("#%d", i), [11]int{})
   352  	}
   353  }
   354  
   355  func TestReverseBits(t *testing.T) {
   356  	for _, h := range reverseBitsTests {
   357  		if v := reverseBits(h.in, h.bitCount); v != h.out {
   358  			t.Errorf("reverseBits(%v,%v) = %v, want %v",
   359  				h.in, h.bitCount, v, h.out)
   360  		}
   361  	}
   362  }
   363  
   364  type deflateInflateStringTest struct {
   365  	filename string
   366  	label    string
   367  	limit    [11]int
   368  }
   369  
   370  var deflateInflateStringTests = []deflateInflateStringTest{
   371  	{
   372  		"../testdata/e.txt",
   373  		"2.718281828...",
   374  		[...]int{100018, 50650, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790, 43683},
   375  	},
   376  	{
   377  		"testdata/Isaac.Newton-Opticks.txt",
   378  		"Isaac.Newton-Opticks",
   379  		[...]int{567248, 218338, 198211, 193152, 181100, 175427, 175427, 173597, 173422, 173422, 325240},
   380  	},
   381  }
   382  
   383  func TestDeflateInflateString(t *testing.T) {
   384  	t.Parallel()
   385  	if testing.Short() && testenv.Builder() == "" {
   386  		t.Skip("skipping in short mode")
   387  	}
   388  	for _, test := range deflateInflateStringTests {
   389  		gold, err := ioutil.ReadFile(test.filename)
   390  		if err != nil {
   391  			t.Error(err)
   392  		}
   393  		testToFromWithLimit(t, gold, test.label, test.limit)
   394  		if testing.Short() {
   395  			break
   396  		}
   397  	}
   398  }
   399  
   400  func TestReaderDict(t *testing.T) {
   401  	const (
   402  		dict = "hello world"
   403  		text = "hello again world"
   404  	)
   405  	var b bytes.Buffer
   406  	w, err := NewWriter(&b, 5)
   407  	if err != nil {
   408  		t.Fatalf("NewWriter: %v", err)
   409  	}
   410  	w.Write([]byte(dict))
   411  	w.Flush()
   412  	b.Reset()
   413  	w.Write([]byte(text))
   414  	w.Close()
   415  
   416  	r := NewReaderDict(&b, []byte(dict))
   417  	data, err := ioutil.ReadAll(r)
   418  	if err != nil {
   419  		t.Fatal(err)
   420  	}
   421  	if string(data) != "hello again world" {
   422  		t.Fatalf("read returned %q want %q", string(data), text)
   423  	}
   424  }
   425  
   426  func TestWriterDict(t *testing.T) {
   427  	const (
   428  		dict = "hello world"
   429  		text = "hello again world"
   430  	)
   431  	var b bytes.Buffer
   432  	w, err := NewWriter(&b, 5)
   433  	if err != nil {
   434  		t.Fatalf("NewWriter: %v", err)
   435  	}
   436  	w.Write([]byte(dict))
   437  	w.Flush()
   438  	b.Reset()
   439  	w.Write([]byte(text))
   440  	w.Close()
   441  
   442  	var b1 bytes.Buffer
   443  	w, _ = NewWriterDict(&b1, 5, []byte(dict))
   444  	w.Write([]byte(text))
   445  	w.Close()
   446  
   447  	if !bytes.Equal(b1.Bytes(), b.Bytes()) {
   448  		t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes())
   449  	}
   450  }
   451  
   452  // See https://golang.org/issue/2508
   453  func TestRegression2508(t *testing.T) {
   454  	if testing.Short() {
   455  		t.Logf("test disabled with -short")
   456  		return
   457  	}
   458  	w, err := NewWriter(ioutil.Discard, 1)
   459  	if err != nil {
   460  		t.Fatalf("NewWriter: %v", err)
   461  	}
   462  	buf := make([]byte, 1024)
   463  	for i := 0; i < 131072; i++ {
   464  		if _, err := w.Write(buf); err != nil {
   465  			t.Fatalf("writer failed: %v", err)
   466  		}
   467  	}
   468  	w.Close()
   469  }
   470  
   471  func TestWriterReset(t *testing.T) {
   472  	t.Parallel()
   473  	for level := 0; level <= 9; level++ {
   474  		if testing.Short() && level > 1 {
   475  			break
   476  		}
   477  		w, err := NewWriter(ioutil.Discard, level)
   478  		if err != nil {
   479  			t.Fatalf("NewWriter: %v", err)
   480  		}
   481  		buf := []byte("hello world")
   482  		n := 1024
   483  		if testing.Short() {
   484  			n = 10
   485  		}
   486  		for i := 0; i < n; i++ {
   487  			w.Write(buf)
   488  		}
   489  		w.Reset(ioutil.Discard)
   490  
   491  		wref, err := NewWriter(ioutil.Discard, level)
   492  		if err != nil {
   493  			t.Fatalf("NewWriter: %v", err)
   494  		}
   495  
   496  		// DeepEqual doesn't compare functions.
   497  		w.d.fill, wref.d.fill = nil, nil
   498  		w.d.step, wref.d.step = nil, nil
   499  		w.d.bulkHasher, wref.d.bulkHasher = nil, nil
   500  		w.d.bestSpeed, wref.d.bestSpeed = nil, nil
   501  		// hashMatch is always overwritten when used.
   502  		copy(w.d.hashMatch[:], wref.d.hashMatch[:])
   503  		if len(w.d.tokens) != 0 {
   504  			t.Errorf("level %d Writer not reset after Reset. %d tokens were present", level, len(w.d.tokens))
   505  		}
   506  		// As long as the length is 0, we don't care about the content.
   507  		w.d.tokens = wref.d.tokens
   508  
   509  		// We don't care if there are values in the window, as long as it is at d.index is 0
   510  		w.d.window = wref.d.window
   511  		if !reflect.DeepEqual(w, wref) {
   512  			t.Errorf("level %d Writer not reset after Reset", level)
   513  		}
   514  	}
   515  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, NoCompression) })
   516  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, DefaultCompression) })
   517  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, BestCompression) })
   518  	dict := []byte("we are the world")
   519  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, NoCompression, dict) })
   520  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, DefaultCompression, dict) })
   521  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, BestCompression, dict) })
   522  }
   523  
   524  func testResetOutput(t *testing.T, newWriter func(w io.Writer) (*Writer, error)) {
   525  	buf := new(bytes.Buffer)
   526  	w, err := newWriter(buf)
   527  	if err != nil {
   528  		t.Fatalf("NewWriter: %v", err)
   529  	}
   530  	b := []byte("hello world")
   531  	for i := 0; i < 1024; i++ {
   532  		w.Write(b)
   533  	}
   534  	w.Close()
   535  	out1 := buf.Bytes()
   536  
   537  	buf2 := new(bytes.Buffer)
   538  	w.Reset(buf2)
   539  	for i := 0; i < 1024; i++ {
   540  		w.Write(b)
   541  	}
   542  	w.Close()
   543  	out2 := buf2.Bytes()
   544  
   545  	if len(out1) != len(out2) {
   546  		t.Errorf("got %d, expected %d bytes", len(out2), len(out1))
   547  		return
   548  	}
   549  	if !bytes.Equal(out1, out2) {
   550  		mm := 0
   551  		for i, b := range out1[:len(out2)] {
   552  			if b != out2[i] {
   553  				t.Errorf("mismatch index %d: %#02x, expected %#02x", i, out2[i], b)
   554  			}
   555  			mm++
   556  			if mm == 10 {
   557  				t.Fatal("Stopping")
   558  			}
   559  		}
   560  	}
   561  	t.Logf("got %d bytes", len(out1))
   562  }
   563  
   564  // TestBestSpeed tests that round-tripping through deflate and then inflate
   565  // recovers the original input. The Write sizes are near the thresholds in the
   566  // compressor.encSpeed method (0, 16, 128), as well as near maxStoreBlockSize
   567  // (65535).
   568  func TestBestSpeed(t *testing.T) {
   569  	t.Parallel()
   570  	abc := make([]byte, 128)
   571  	for i := range abc {
   572  		abc[i] = byte(i)
   573  	}
   574  	abcabc := bytes.Repeat(abc, 131072/len(abc))
   575  	var want []byte
   576  
   577  	testCases := [][]int{
   578  		{65536, 0},
   579  		{65536, 1},
   580  		{65536, 1, 256},
   581  		{65536, 1, 65536},
   582  		{65536, 14},
   583  		{65536, 15},
   584  		{65536, 16},
   585  		{65536, 16, 256},
   586  		{65536, 16, 65536},
   587  		{65536, 127},
   588  		{65536, 128},
   589  		{65536, 128, 256},
   590  		{65536, 128, 65536},
   591  		{65536, 129},
   592  		{65536, 65536, 256},
   593  		{65536, 65536, 65536},
   594  	}
   595  
   596  	for i, tc := range testCases {
   597  		if i >= 3 && testing.Short() {
   598  			break
   599  		}
   600  		for _, firstN := range []int{1, 65534, 65535, 65536, 65537, 131072} {
   601  			tc[0] = firstN
   602  		outer:
   603  			for _, flush := range []bool{false, true} {
   604  				buf := new(bytes.Buffer)
   605  				want = want[:0]
   606  
   607  				w, err := NewWriter(buf, BestSpeed)
   608  				if err != nil {
   609  					t.Errorf("i=%d, firstN=%d, flush=%t: NewWriter: %v", i, firstN, flush, err)
   610  					continue
   611  				}
   612  				for _, n := range tc {
   613  					want = append(want, abcabc[:n]...)
   614  					if _, err := w.Write(abcabc[:n]); err != nil {
   615  						t.Errorf("i=%d, firstN=%d, flush=%t: Write: %v", i, firstN, flush, err)
   616  						continue outer
   617  					}
   618  					if !flush {
   619  						continue
   620  					}
   621  					if err := w.Flush(); err != nil {
   622  						t.Errorf("i=%d, firstN=%d, flush=%t: Flush: %v", i, firstN, flush, err)
   623  						continue outer
   624  					}
   625  				}
   626  				if err := w.Close(); err != nil {
   627  					t.Errorf("i=%d, firstN=%d, flush=%t: Close: %v", i, firstN, flush, err)
   628  					continue
   629  				}
   630  
   631  				r := NewReader(buf)
   632  				got, err := ioutil.ReadAll(r)
   633  				if err != nil {
   634  					t.Errorf("i=%d, firstN=%d, flush=%t: ReadAll: %v", i, firstN, flush, err)
   635  					continue
   636  				}
   637  				r.Close()
   638  
   639  				if !bytes.Equal(got, want) {
   640  					t.Errorf("i=%d, firstN=%d, flush=%t: corruption during deflate-then-inflate", i, firstN, flush)
   641  					continue
   642  				}
   643  			}
   644  		}
   645  	}
   646  }
   647  
   648  var errIO = errors.New("IO error")
   649  
   650  // failWriter fails with errIO exactly at the nth call to Write.
   651  type failWriter struct{ n int }
   652  
   653  func (w *failWriter) Write(b []byte) (int, error) {
   654  	w.n--
   655  	if w.n == -1 {
   656  		return 0, errIO
   657  	}
   658  	return len(b), nil
   659  }
   660  
   661  func TestWriterPersistentError(t *testing.T) {
   662  	t.Parallel()
   663  	d, err := ioutil.ReadFile("testdata/Isaac.Newton-Opticks.txt")
   664  	if err != nil {
   665  		t.Fatalf("ReadFile: %v", err)
   666  	}
   667  	d = d[:10000] // Keep this test short
   668  
   669  	zw, err := NewWriter(nil, DefaultCompression)
   670  	if err != nil {
   671  		t.Fatalf("NewWriter: %v", err)
   672  	}
   673  
   674  	// Sweep over the threshold at which an error is returned.
   675  	// The variable i makes it such that the ith call to failWriter.Write will
   676  	// return errIO. Since failWriter errors are not persistent, we must ensure
   677  	// that flate.Writer errors are persistent.
   678  	for i := 0; i < 1000; i++ {
   679  		fw := &failWriter{i}
   680  		zw.Reset(fw)
   681  
   682  		_, werr := zw.Write(d)
   683  		cerr := zw.Close()
   684  		if werr != errIO && werr != nil {
   685  			t.Errorf("test %d, mismatching Write error: got %v, want %v", i, werr, errIO)
   686  		}
   687  		if cerr != errIO && fw.n < 0 {
   688  			t.Errorf("test %d, mismatching Close error: got %v, want %v", i, cerr, errIO)
   689  		}
   690  		if fw.n >= 0 {
   691  			// At this point, the failure threshold was sufficiently high enough
   692  			// that we wrote the whole stream without any errors.
   693  			return
   694  		}
   695  	}
   696  }
   697  
   698  func TestBestSpeedMatch(t *testing.T) {
   699  	t.Parallel()
   700  	cases := []struct {
   701  		previous, current []byte
   702  		t, s, want        int32
   703  	}{{
   704  		previous: []byte{0, 0, 0, 1, 2},
   705  		current:  []byte{3, 4, 5, 0, 1, 2, 3, 4, 5},
   706  		t:        -3,
   707  		s:        3,
   708  		want:     6,
   709  	}, {
   710  		previous: []byte{0, 0, 0, 1, 2},
   711  		current:  []byte{2, 4, 5, 0, 1, 2, 3, 4, 5},
   712  		t:        -3,
   713  		s:        3,
   714  		want:     3,
   715  	}, {
   716  		previous: []byte{0, 0, 0, 1, 1},
   717  		current:  []byte{3, 4, 5, 0, 1, 2, 3, 4, 5},
   718  		t:        -3,
   719  		s:        3,
   720  		want:     2,
   721  	}, {
   722  		previous: []byte{0, 0, 0, 1, 2},
   723  		current:  []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
   724  		t:        -1,
   725  		s:        0,
   726  		want:     4,
   727  	}, {
   728  		previous: []byte{0, 0, 0, 1, 2, 3, 4, 5, 2, 2},
   729  		current:  []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
   730  		t:        -7,
   731  		s:        4,
   732  		want:     5,
   733  	}, {
   734  		previous: []byte{9, 9, 9, 9, 9},
   735  		current:  []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
   736  		t:        -1,
   737  		s:        0,
   738  		want:     0,
   739  	}, {
   740  		previous: []byte{9, 9, 9, 9, 9},
   741  		current:  []byte{9, 2, 2, 2, 1, 2, 3, 4, 5},
   742  		t:        0,
   743  		s:        1,
   744  		want:     0,
   745  	}, {
   746  		previous: []byte{},
   747  		current:  []byte{9, 2, 2, 2, 1, 2, 3, 4, 5},
   748  		t:        -5,
   749  		s:        1,
   750  		want:     0,
   751  	}, {
   752  		previous: []byte{},
   753  		current:  []byte{9, 2, 2, 2, 1, 2, 3, 4, 5},
   754  		t:        -1,
   755  		s:        1,
   756  		want:     0,
   757  	}, {
   758  		previous: []byte{},
   759  		current:  []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
   760  		t:        0,
   761  		s:        1,
   762  		want:     3,
   763  	}, {
   764  		previous: []byte{3, 4, 5},
   765  		current:  []byte{3, 4, 5},
   766  		t:        -3,
   767  		s:        0,
   768  		want:     3,
   769  	}, {
   770  		previous: make([]byte, 1000),
   771  		current:  make([]byte, 1000),
   772  		t:        -1000,
   773  		s:        0,
   774  		want:     maxMatchLength - 4,
   775  	}, {
   776  		previous: make([]byte, 200),
   777  		current:  make([]byte, 500),
   778  		t:        -200,
   779  		s:        0,
   780  		want:     maxMatchLength - 4,
   781  	}, {
   782  		previous: make([]byte, 200),
   783  		current:  make([]byte, 500),
   784  		t:        0,
   785  		s:        1,
   786  		want:     maxMatchLength - 4,
   787  	}, {
   788  		previous: make([]byte, maxMatchLength-4),
   789  		current:  make([]byte, 500),
   790  		t:        -(maxMatchLength - 4),
   791  		s:        0,
   792  		want:     maxMatchLength - 4,
   793  	}, {
   794  		previous: make([]byte, 200),
   795  		current:  make([]byte, 500),
   796  		t:        -200,
   797  		s:        400,
   798  		want:     100,
   799  	}, {
   800  		previous: make([]byte, 10),
   801  		current:  make([]byte, 500),
   802  		t:        200,
   803  		s:        400,
   804  		want:     100,
   805  	}}
   806  	for i, c := range cases {
   807  		e := deflateFast{prev: c.previous}
   808  		got := e.matchLen(c.s, c.t, c.current)
   809  		if got != c.want {
   810  			t.Errorf("Test %d: match length, want %d, got %d", i, c.want, got)
   811  		}
   812  	}
   813  }
   814  
   815  func TestBestSpeedMaxMatchOffset(t *testing.T) {
   816  	t.Parallel()
   817  	const abc, xyz = "abcdefgh", "stuvwxyz"
   818  	for _, matchBefore := range []bool{false, true} {
   819  		for _, extra := range []int{0, inputMargin - 1, inputMargin, inputMargin + 1, 2 * inputMargin} {
   820  			for offsetAdj := -5; offsetAdj <= +5; offsetAdj++ {
   821  				report := func(desc string, err error) {
   822  					t.Errorf("matchBefore=%t, extra=%d, offsetAdj=%d: %s%v",
   823  						matchBefore, extra, offsetAdj, desc, err)
   824  				}
   825  
   826  				offset := maxMatchOffset + offsetAdj
   827  
   828  				// Make src to be a []byte of the form
   829  				//	"%s%s%s%s%s" % (abc, zeros0, xyzMaybe, abc, zeros1)
   830  				// where:
   831  				//	zeros0 is approximately maxMatchOffset zeros.
   832  				//	xyzMaybe is either xyz or the empty string.
   833  				//	zeros1 is between 0 and 30 zeros.
   834  				// The difference between the two abc's will be offset, which
   835  				// is maxMatchOffset plus or minus a small adjustment.
   836  				src := make([]byte, offset+len(abc)+extra)
   837  				copy(src, abc)
   838  				if !matchBefore {
   839  					copy(src[offset-len(xyz):], xyz)
   840  				}
   841  				copy(src[offset:], abc)
   842  
   843  				buf := new(bytes.Buffer)
   844  				w, err := NewWriter(buf, BestSpeed)
   845  				if err != nil {
   846  					report("NewWriter: ", err)
   847  					continue
   848  				}
   849  				if _, err := w.Write(src); err != nil {
   850  					report("Write: ", err)
   851  					continue
   852  				}
   853  				if err := w.Close(); err != nil {
   854  					report("Writer.Close: ", err)
   855  					continue
   856  				}
   857  
   858  				r := NewReader(buf)
   859  				dst, err := ioutil.ReadAll(r)
   860  				r.Close()
   861  				if err != nil {
   862  					report("ReadAll: ", err)
   863  					continue
   864  				}
   865  
   866  				if !bytes.Equal(dst, src) {
   867  					report("", fmt.Errorf("bytes differ after round-tripping"))
   868  					continue
   869  				}
   870  			}
   871  		}
   872  	}
   873  }
   874  
   875  func TestMaxStackSize(t *testing.T) {
   876  	// This test must not run in parallel with other tests as debug.SetMaxStack
   877  	// affects all goroutines.
   878  	n := debug.SetMaxStack(1 << 16)
   879  	defer debug.SetMaxStack(n)
   880  
   881  	var wg sync.WaitGroup
   882  	defer wg.Wait()
   883  
   884  	b := make([]byte, 1<<20)
   885  	for level := HuffmanOnly; level <= BestCompression; level++ {
   886  		// Run in separate goroutine to increase probability of stack regrowth.
   887  		wg.Add(1)
   888  		go func(level int) {
   889  			defer wg.Done()
   890  			zw, err := NewWriter(ioutil.Discard, level)
   891  			if err != nil {
   892  				t.Errorf("level %d, NewWriter() = %v, want nil", level, err)
   893  			}
   894  			if n, err := zw.Write(b); n != len(b) || err != nil {
   895  				t.Errorf("level %d, Write() = (%d, %v), want (%d, nil)", level, n, err, len(b))
   896  			}
   897  			if err := zw.Close(); err != nil {
   898  				t.Errorf("level %d, Close() = %v, want nil", level, err)
   899  			}
   900  			zw.Reset(ioutil.Discard)
   901  		}(level)
   902  	}
   903  }