...

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

Documentation: github.com/klauspost/compress/flate

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Copyright (c) 2015 Klaus Post
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package flate
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  	"io"
    12  	"os"
    13  	"reflect"
    14  	"strings"
    15  	"sync"
    16  	"testing"
    17  )
    18  
    19  type deflateTest struct {
    20  	in    []byte
    21  	level int
    22  	out   []byte
    23  }
    24  
    25  type deflateInflateTest struct {
    26  	in []byte
    27  }
    28  
    29  type reverseBitsTest struct {
    30  	in       uint16
    31  	bitCount uint8
    32  	out      uint16
    33  }
    34  
    35  var deflateTests = []*deflateTest{
    36  	0: {[]byte{}, 0, []byte{0x3, 0x0}},
    37  	1: {[]byte{0x11}, BestCompression, []byte{0x12, 0x4, 0xc, 0x0}},
    38  	2: {[]byte{0x11}, BestCompression, []byte{0x12, 0x4, 0xc, 0x0}},
    39  	3: {[]byte{0x11}, BestCompression, []byte{0x12, 0x4, 0xc, 0x0}},
    40  
    41  	4: {[]byte{0x11}, 0, []byte{0x0, 0x1, 0x0, 0xfe, 0xff, 0x11, 0x3, 0x0}},
    42  	5: {[]byte{0x11, 0x12}, 0, []byte{0x0, 0x2, 0x0, 0xfd, 0xff, 0x11, 0x12, 0x3, 0x0}},
    43  	6: {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0,
    44  		[]byte{0x0, 0x8, 0x0, 0xf7, 0xff, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x3, 0x0},
    45  	},
    46  	7:  {[]byte{}, 1, []byte{0x3, 0x0}},
    47  	8:  {[]byte{0x11}, BestCompression, []byte{0x12, 0x4, 0xc, 0x0}},
    48  	9:  {[]byte{0x11, 0x12}, BestCompression, []byte{0x12, 0x14, 0x2, 0xc, 0x0}},
    49  	10: {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, BestCompression, []byte{0x12, 0x84, 0x1, 0xc0, 0x0}},
    50  	11: {[]byte{}, 9, []byte{0x3, 0x0}},
    51  	12: {[]byte{0x11}, 9, []byte{0x12, 0x4, 0xc, 0x0}},
    52  	13: {[]byte{0x11, 0x12}, 9, []byte{0x12, 0x14, 0x2, 0xc, 0x0}},
    53  	14: {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{0x12, 0x84, 0x1, 0xc0, 0x0}},
    54  }
    55  
    56  var deflateInflateTests = []*deflateInflateTest{
    57  	{[]byte{}},
    58  	{[]byte{0x11}},
    59  	{[]byte{0x11, 0x12}},
    60  	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
    61  	{[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}},
    62  	{largeDataChunk()},
    63  }
    64  
    65  var reverseBitsTests = []*reverseBitsTest{
    66  	{1, 1, 1},
    67  	{1, 2, 2},
    68  	{1, 3, 4},
    69  	{1, 4, 8},
    70  	{1, 5, 16},
    71  	{17, 5, 17},
    72  	{257, 9, 257},
    73  	{29, 5, 23},
    74  }
    75  
    76  func largeDataChunk() []byte {
    77  	result := make([]byte, 100000)
    78  	for i := range result {
    79  		result[i] = byte(i * i & 0xFF)
    80  	}
    81  	return result
    82  }
    83  
    84  func TestBulkHash4(t *testing.T) {
    85  	for _, x := range deflateTests {
    86  		y := x.out
    87  		if len(y) >= minMatchLength {
    88  			y = append(y, y...)
    89  			for j := 4; j < len(y); j++ {
    90  				y := y[:j]
    91  				dst := make([]uint32, len(y)-minMatchLength+1)
    92  				for i := range dst {
    93  					dst[i] = uint32(i + 100)
    94  				}
    95  				bulkHash4(y, dst)
    96  				for i, val := range dst {
    97  					got := val
    98  					expect := hash4(y[i:])
    99  					if got != expect && got == uint32(i)+100 {
   100  						t.Errorf("Len:%d Index:%d, expected 0x%08x but not modified", len(y), i, expect)
   101  					} else if got != expect {
   102  						t.Errorf("Len:%d Index:%d, got 0x%08x expected:0x%08x", len(y), i, got, expect)
   103  					} else {
   104  						//t.Logf("Len:%d Index:%d OK (0x%08x)", len(y), i, got)
   105  					}
   106  				}
   107  			}
   108  		}
   109  	}
   110  }
   111  
   112  func TestDeflate(t *testing.T) {
   113  	for i, h := range deflateTests {
   114  		var buf bytes.Buffer
   115  		w, err := NewWriter(&buf, h.level)
   116  		if err != nil {
   117  			t.Errorf("NewWriter: %v", err)
   118  			continue
   119  		}
   120  		w.Write(h.in)
   121  		w.Close()
   122  		if !bytes.Equal(buf.Bytes(), h.out) {
   123  			t.Errorf("%d: Deflate(%d, %x) got \n%#v, want \n%#v", i, h.level, h.in, buf.Bytes(), h.out)
   124  		}
   125  	}
   126  }
   127  
   128  // A sparseReader returns a stream consisting of 0s followed by 1<<16 1s.
   129  // This tests missing hash references in a very large input.
   130  type sparseReader struct {
   131  	l   int64
   132  	cur int64
   133  }
   134  
   135  func (r *sparseReader) Read(b []byte) (n int, err error) {
   136  	if r.cur >= r.l {
   137  		return 0, io.EOF
   138  	}
   139  	n = len(b)
   140  	cur := r.cur + int64(n)
   141  	if cur > r.l {
   142  		n -= int(cur - r.l)
   143  		cur = r.l
   144  	}
   145  	for i := range b[0:n] {
   146  		if r.cur+int64(i) >= r.l-1<<16 {
   147  			b[i] = 1
   148  		} else {
   149  			b[i] = 0
   150  		}
   151  	}
   152  	r.cur = cur
   153  	return
   154  }
   155  
   156  func TestVeryLongSparseChunk(t *testing.T) {
   157  	if testing.Short() {
   158  		t.Skip("skipping sparse chunk during short test")
   159  	}
   160  	var buf bytes.Buffer
   161  	w, err := NewWriter(&buf, 1)
   162  	if err != nil {
   163  		t.Errorf("NewWriter: %v", err)
   164  		return
   165  	}
   166  	if _, err = io.Copy(w, &sparseReader{l: 23e8}); err != nil {
   167  		t.Errorf("Compress failed: %v", err)
   168  		return
   169  	}
   170  	t.Log("Length:", buf.Len())
   171  }
   172  
   173  type syncBuffer struct {
   174  	buf    bytes.Buffer
   175  	mu     sync.RWMutex
   176  	closed bool
   177  	ready  chan bool
   178  }
   179  
   180  func newSyncBuffer() *syncBuffer {
   181  	return &syncBuffer{ready: make(chan bool, 1)}
   182  }
   183  
   184  func (b *syncBuffer) Read(p []byte) (n int, err error) {
   185  	for {
   186  		b.mu.RLock()
   187  		n, err = b.buf.Read(p)
   188  		b.mu.RUnlock()
   189  		if n > 0 || b.closed {
   190  			return
   191  		}
   192  		<-b.ready
   193  	}
   194  }
   195  
   196  func (b *syncBuffer) signal() {
   197  	select {
   198  	case b.ready <- true:
   199  	default:
   200  	}
   201  }
   202  
   203  func (b *syncBuffer) Write(p []byte) (n int, err error) {
   204  	n, err = b.buf.Write(p)
   205  	b.signal()
   206  	return
   207  }
   208  
   209  func (b *syncBuffer) WriteMode() {
   210  	b.mu.Lock()
   211  }
   212  
   213  func (b *syncBuffer) ReadMode() {
   214  	b.mu.Unlock()
   215  	b.signal()
   216  }
   217  
   218  func (b *syncBuffer) Close() error {
   219  	b.closed = true
   220  	b.signal()
   221  	return nil
   222  }
   223  
   224  func testSync(t *testing.T, level int, input []byte, name string) {
   225  	if len(input) == 0 {
   226  		return
   227  	}
   228  
   229  	t.Logf("--testSync %d, %d, %s", level, len(input), name)
   230  	buf := newSyncBuffer()
   231  	buf1 := new(bytes.Buffer)
   232  	buf.WriteMode()
   233  	w, err := NewWriter(io.MultiWriter(buf, buf1), level)
   234  	if err != nil {
   235  		t.Errorf("NewWriter: %v", err)
   236  		return
   237  	}
   238  	r := NewReader(buf)
   239  
   240  	// Write half the input and read back.
   241  	for i := 0; i < 2; i++ {
   242  		var lo, hi int
   243  		if i == 0 {
   244  			lo, hi = 0, (len(input)+1)/2
   245  		} else {
   246  			lo, hi = (len(input)+1)/2, len(input)
   247  		}
   248  		t.Logf("#%d: write %d-%d", i, lo, hi)
   249  		if _, err := w.Write(input[lo:hi]); err != nil {
   250  			t.Errorf("testSync: write: %v", err)
   251  			return
   252  		}
   253  		if i == 0 {
   254  			if err := w.Flush(); err != nil {
   255  				t.Errorf("testSync: flush: %v", err)
   256  				return
   257  			}
   258  		} else {
   259  			if err := w.Close(); err != nil {
   260  				t.Errorf("testSync: close: %v", err)
   261  			}
   262  		}
   263  		buf.ReadMode()
   264  		out := make([]byte, hi-lo+1)
   265  		m, err := io.ReadAtLeast(r, out, hi-lo)
   266  		t.Logf("#%d: read %d", i, m)
   267  		if m != hi-lo || err != nil {
   268  			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())
   269  			return
   270  		}
   271  		if !bytes.Equal(input[lo:hi], out[:hi-lo]) {
   272  			t.Errorf("testSync/%d: read wrong bytes: %x vs %x", i, input[lo:hi], out[:hi-lo])
   273  			return
   274  		}
   275  		// This test originally checked that after reading
   276  		// the first half of the input, there was nothing left
   277  		// in the read buffer (buf.buf.Len() != 0) but that is
   278  		// not necessarily the case: the write Flush may emit
   279  		// some extra framing bits that are not necessary
   280  		// to process to obtain the first half of the uncompressed
   281  		// data.  The test ran correctly most of the time, because
   282  		// the background goroutine had usually read even
   283  		// those extra bits by now, but it's not a useful thing to
   284  		// check.
   285  		buf.WriteMode()
   286  	}
   287  	buf.ReadMode()
   288  	out := make([]byte, 10)
   289  	if n, err := r.Read(out); n > 0 || err != io.EOF {
   290  		t.Errorf("testSync (%d, %d, %s): final Read: %d, %v (hex: %x)", level, len(input), name, n, err, out[0:n])
   291  	}
   292  	if buf.buf.Len() != 0 {
   293  		t.Errorf("testSync (%d, %d, %s): extra data at end", level, len(input), name)
   294  	}
   295  	r.Close()
   296  
   297  	// stream should work for ordinary reader too
   298  	r = NewReader(buf1)
   299  	out, err = io.ReadAll(r)
   300  	if err != nil {
   301  		t.Errorf("testSync: read: %s", err)
   302  		return
   303  	}
   304  	r.Close()
   305  	if !bytes.Equal(input, out) {
   306  		t.Errorf("testSync: decompress(compress(data)) != data: level=%d input=%s", level, name)
   307  	}
   308  }
   309  
   310  func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) {
   311  	var buffer bytes.Buffer
   312  	w, err := NewWriter(&buffer, level)
   313  	if err != nil {
   314  		t.Errorf("NewWriter: %v", err)
   315  		return
   316  	}
   317  	w.Write(input)
   318  	w.Close()
   319  	if limit > 0 {
   320  		t.Logf("level: %d - Size:%.2f%%, %d b\n", level, float64(buffer.Len()*100)/float64(limit), buffer.Len())
   321  	}
   322  	if limit > 0 && buffer.Len() > limit {
   323  		t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit)
   324  	}
   325  
   326  	r := NewReader(&buffer)
   327  	out, err := io.ReadAll(r)
   328  	if err != nil {
   329  		t.Errorf("read: %s", err)
   330  		return
   331  	}
   332  	r.Close()
   333  	if !bytes.Equal(input, out) {
   334  		os.WriteFile("testdata/fails/"+t.Name()+".got", out, os.ModePerm)
   335  		os.WriteFile("testdata/fails/"+t.Name()+".want", input, os.ModePerm)
   336  		t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name)
   337  		return
   338  	}
   339  	testSync(t, level, input, name)
   340  }
   341  
   342  func testToFromWithLimit(t *testing.T, input []byte, name string, limit [11]int) {
   343  	for i := 0; i < 10; i++ {
   344  		testToFromWithLevelAndLimit(t, i, input, name, limit[i])
   345  	}
   346  	testToFromWithLevelAndLimit(t, -2, input, name, limit[10])
   347  }
   348  
   349  func TestDeflateInflate(t *testing.T) {
   350  	for i, h := range deflateInflateTests {
   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 // Number 11 is ConstantCompression
   368  }
   369  
   370  var deflateInflateStringTests = []deflateInflateStringTest{
   371  	{
   372  		"../testdata/e.txt",
   373  		"2.718281828...",
   374  		[...]int{100018, 67900, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790, 43683 + 100},
   375  	},
   376  	{
   377  		"../testdata/Mark.Twain-Tom.Sawyer.txt",
   378  		"Mark.Twain-Tom.Sawyer",
   379  		[...]int{387999, 185000, 182361, 179974, 174124, 168819, 162936, 160506, 160295, 160295, 233460 + 100},
   380  	},
   381  }
   382  
   383  func TestDeflateInflateString(t *testing.T) {
   384  	for _, test := range deflateInflateStringTests {
   385  		gold, err := os.ReadFile(test.filename)
   386  		if err != nil {
   387  			t.Error(err)
   388  		}
   389  		// Remove returns that may be present on Windows
   390  		neutral := strings.Map(func(r rune) rune {
   391  			if r != '\r' {
   392  				return r
   393  			}
   394  			return -1
   395  		}, string(gold))
   396  
   397  		testToFromWithLimit(t, []byte(neutral), test.label, test.limit)
   398  
   399  		if testing.Short() {
   400  			break
   401  		}
   402  	}
   403  }
   404  
   405  func TestReaderDict(t *testing.T) {
   406  	const (
   407  		dict = "hello world"
   408  		text = "hello again world"
   409  	)
   410  	var b bytes.Buffer
   411  	w, err := NewWriter(&b, 5)
   412  	if err != nil {
   413  		t.Fatalf("NewWriter: %v", err)
   414  	}
   415  	w.Write([]byte(dict))
   416  	w.Flush()
   417  	b.Reset()
   418  	w.Write([]byte(text))
   419  	w.Close()
   420  
   421  	r := NewReaderDict(&b, []byte(dict))
   422  	data, err := io.ReadAll(r)
   423  	if err != nil {
   424  		t.Fatal(err)
   425  	}
   426  	if string(data) != "hello again world" {
   427  		t.Fatalf("read returned %q want %q", string(data), text)
   428  	}
   429  }
   430  
   431  func TestWriterDict(t *testing.T) {
   432  	const (
   433  		dict = "hello world Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
   434  		text = "hello world Lorem ipsum dolor sit amet"
   435  	)
   436  	// This test is sensitive to algorithm changes that skip
   437  	// data in favour of speed. Higher levels are less prone to this
   438  	// so we test level 4-9.
   439  	for l := 4; l < 9; l++ {
   440  		var b bytes.Buffer
   441  		w, err := NewWriter(&b, l)
   442  		if err != nil {
   443  			t.Fatalf("level %d, NewWriter: %v", l, err)
   444  		}
   445  		w.Write([]byte(dict))
   446  		w.Flush()
   447  		b.Reset()
   448  		w.Write([]byte(text))
   449  		w.Close()
   450  
   451  		var b1 bytes.Buffer
   452  		w, _ = NewWriterDict(&b1, l, []byte(dict))
   453  		w.Write([]byte(text))
   454  		w.Close()
   455  
   456  		if !bytes.Equal(b1.Bytes(), b.Bytes()) {
   457  			t.Errorf("level %d, writer wrote\n%v\n want\n%v", l, b1.Bytes(), b.Bytes())
   458  		}
   459  	}
   460  }
   461  
   462  // See http://code.google.com/p/go/issues/detail?id=2508
   463  func TestRegression2508(t *testing.T) {
   464  	if testing.Short() {
   465  		t.Logf("test disabled with -short")
   466  		return
   467  	}
   468  	w, err := NewWriter(io.Discard, 1)
   469  	if err != nil {
   470  		t.Fatalf("NewWriter: %v", err)
   471  	}
   472  	buf := make([]byte, 1024)
   473  	for i := 0; i < 131072; i++ {
   474  		if _, err := w.Write(buf); err != nil {
   475  			t.Fatalf("writer failed: %v", err)
   476  		}
   477  	}
   478  	w.Close()
   479  }
   480  
   481  func TestWriterReset(t *testing.T) {
   482  	for level := -2; level <= 9; level++ {
   483  		if level == -1 {
   484  			level++
   485  		}
   486  		if testing.Short() && level > 1 {
   487  			break
   488  		}
   489  		w, err := NewWriter(io.Discard, level)
   490  		if err != nil {
   491  			t.Fatalf("NewWriter: %v", err)
   492  		}
   493  		buf := []byte("hello world")
   494  		for i := 0; i < 1024; i++ {
   495  			w.Write(buf)
   496  		}
   497  		w.Reset(io.Discard)
   498  
   499  		wref, err := NewWriter(io.Discard, level)
   500  		if err != nil {
   501  			t.Fatalf("NewWriter: %v", err)
   502  		}
   503  
   504  		// DeepEqual doesn't compare functions.
   505  		w.d.fill, wref.d.fill = nil, nil
   506  		w.d.step, wref.d.step = nil, nil
   507  		w.d.state, wref.d.state = nil, nil
   508  		w.d.fast, wref.d.fast = nil, nil
   509  
   510  		// hashMatch is always overwritten when used.
   511  		if w.d.tokens.n != 0 {
   512  			t.Errorf("level %d Writer not reset after Reset. %d tokens were present", level, w.d.tokens.n)
   513  		}
   514  		// As long as the length is 0, we don't care about the content.
   515  		w.d.tokens = wref.d.tokens
   516  
   517  		// We don't care if there are values in the window, as long as it is at d.index is 0
   518  		w.d.window = wref.d.window
   519  		if !reflect.DeepEqual(w, wref) {
   520  			t.Errorf("level %d Writer not reset after Reset", level)
   521  		}
   522  	}
   523  
   524  	for i := HuffmanOnly; i <= BestCompression; i++ {
   525  		testResetOutput(t, fmt.Sprint("level-", i), func(w io.Writer) (*Writer, error) { return NewWriter(w, i) })
   526  	}
   527  	dict := []byte(strings.Repeat("we are the world - how are you?", 3))
   528  	for i := HuffmanOnly; i <= BestCompression; i++ {
   529  		testResetOutput(t, fmt.Sprint("dict-level-", i), func(w io.Writer) (*Writer, error) { return NewWriterDict(w, i, dict) })
   530  	}
   531  	for i := HuffmanOnly; i <= BestCompression; i++ {
   532  		testResetOutput(t, fmt.Sprint("dict-reset-level-", i), func(w io.Writer) (*Writer, error) {
   533  			w2, err := NewWriter(nil, i)
   534  			if err != nil {
   535  				return w2, err
   536  			}
   537  			w2.ResetDict(w, dict)
   538  			return w2, nil
   539  		})
   540  	}
   541  	testResetOutput(t, fmt.Sprint("dict-reset-window"), func(w io.Writer) (*Writer, error) {
   542  		w2, err := NewWriterWindow(nil, 1024)
   543  		if err != nil {
   544  			return w2, err
   545  		}
   546  		w2.ResetDict(w, dict)
   547  		return w2, nil
   548  	})
   549  }
   550  
   551  func testResetOutput(t *testing.T, name string, newWriter func(w io.Writer) (*Writer, error)) {
   552  	t.Run(name, func(t *testing.T) {
   553  		buf := new(bytes.Buffer)
   554  		w, err := newWriter(buf)
   555  		if err != nil {
   556  			t.Fatalf("NewWriter: %v", err)
   557  		}
   558  		b := []byte("hello world - how are you doing?")
   559  		for i := 0; i < 1024; i++ {
   560  			w.Write(b)
   561  		}
   562  		w.Close()
   563  		out1 := buf.Bytes()
   564  
   565  		buf2 := new(bytes.Buffer)
   566  		w.Reset(buf2)
   567  		for i := 0; i < 1024; i++ {
   568  			w.Write(b)
   569  		}
   570  		w.Close()
   571  		out2 := buf2.Bytes()
   572  
   573  		if len(out1) != len(out2) {
   574  			t.Errorf("got %d, expected %d bytes", len(out2), len(out1))
   575  		}
   576  		if !bytes.Equal(out1, out2) {
   577  			mm := 0
   578  			for i, b := range out1[:len(out2)] {
   579  				if b != out2[i] {
   580  					t.Errorf("mismatch index %d: %02x, expected %02x", i, out2[i], b)
   581  				}
   582  				mm++
   583  				if mm == 10 {
   584  					t.Fatal("Stopping")
   585  				}
   586  			}
   587  		}
   588  		t.Logf("got %d bytes", len(out1))
   589  	})
   590  }
   591  
   592  // TestBestSpeed tests that round-tripping through deflate and then inflate
   593  // recovers the original input. The Write sizes are near the thresholds in the
   594  // compressor.encSpeed method (0, 16, 128), as well as near maxStoreBlockSize
   595  // (65535).
   596  func TestBestSpeed(t *testing.T) {
   597  	abc := make([]byte, 128)
   598  	for i := range abc {
   599  		abc[i] = byte(i)
   600  	}
   601  	abcabc := bytes.Repeat(abc, 131072/len(abc))
   602  	var want []byte
   603  
   604  	testCases := [][]int{
   605  		{65536, 0},
   606  		{65536, 1},
   607  		{65536, 1, 256},
   608  		{65536, 1, 65536},
   609  		{65536, 14},
   610  		{65536, 15},
   611  		{65536, 16},
   612  		{65536, 16, 256},
   613  		{65536, 16, 65536},
   614  		{65536, 127},
   615  		{65536, 128},
   616  		{65536, 128, 256},
   617  		{65536, 128, 65536},
   618  		{65536, 129},
   619  		{65536, 65536, 256},
   620  		{65536, 65536, 65536},
   621  	}
   622  
   623  	for i, tc := range testCases {
   624  		if testing.Short() && i > 5 {
   625  			t.Skip()
   626  		}
   627  		for _, firstN := range []int{1, 65534, 65535, 65536, 65537, 131072} {
   628  			tc[0] = firstN
   629  		outer:
   630  			for _, flush := range []bool{false, true} {
   631  				buf := new(bytes.Buffer)
   632  				want = want[:0]
   633  
   634  				w, err := NewWriter(buf, BestSpeed)
   635  				if err != nil {
   636  					t.Errorf("i=%d, firstN=%d, flush=%t: NewWriter: %v", i, firstN, flush, err)
   637  					continue
   638  				}
   639  				for _, n := range tc {
   640  					want = append(want, abcabc[:n]...)
   641  					if _, err := w.Write(abcabc[:n]); err != nil {
   642  						t.Errorf("i=%d, firstN=%d, flush=%t: Write: %v", i, firstN, flush, err)
   643  						continue outer
   644  					}
   645  					if !flush {
   646  						continue
   647  					}
   648  					if err := w.Flush(); err != nil {
   649  						t.Errorf("i=%d, firstN=%d, flush=%t: Flush: %v", i, firstN, flush, err)
   650  						continue outer
   651  					}
   652  				}
   653  				if err := w.Close(); err != nil {
   654  					t.Errorf("i=%d, firstN=%d, flush=%t: Close: %v", i, firstN, flush, err)
   655  					continue
   656  				}
   657  
   658  				r := NewReader(buf)
   659  				got, err := io.ReadAll(r)
   660  				if err != nil {
   661  					t.Errorf("i=%d, firstN=%d, flush=%t: ReadAll: %v", i, firstN, flush, err)
   662  					continue
   663  				}
   664  				r.Close()
   665  
   666  				if !bytes.Equal(got, want) {
   667  					t.Errorf("i=%d, firstN=%d, flush=%t: corruption during deflate-then-inflate", i, firstN, flush)
   668  					continue
   669  				}
   670  			}
   671  		}
   672  	}
   673  }
   674  

View as plain text