github.com/aloncn/graphics-go@v0.0.1/src/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  	"fmt"
    10  	"internal/testenv"
    11  	"io"
    12  	"io/ioutil"
    13  	"reflect"
    14  	"sync"
    15  	"testing"
    16  )
    17  
    18  type deflateTest struct {
    19  	in    []byte
    20  	level int
    21  	out   []byte
    22  }
    23  
    24  type deflateInflateTest struct {
    25  	in []byte
    26  }
    27  
    28  type reverseBitsTest struct {
    29  	in       uint16
    30  	bitCount uint8
    31  	out      uint16
    32  }
    33  
    34  var deflateTests = []*deflateTest{
    35  	{[]byte{}, 0, []byte{1, 0, 0, 255, 255}},
    36  	{[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}},
    37  	{[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}},
    38  	{[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}},
    39  
    40  	{[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}},
    41  	{[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}},
    42  	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0,
    43  		[]byte{0, 8, 0, 247, 255, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0, 0, 255, 255},
    44  	},
    45  	{[]byte{}, 1, []byte{1, 0, 0, 255, 255}},
    46  	{[]byte{0x11}, 1, []byte{18, 4, 4, 0, 0, 255, 255}},
    47  	{[]byte{0x11, 0x12}, 1, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
    48  	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 1, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
    49  	{[]byte{}, 9, []byte{1, 0, 0, 255, 255}},
    50  	{[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}},
    51  	{[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
    52  	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
    53  }
    54  
    55  var deflateInflateTests = []*deflateInflateTest{
    56  	{[]byte{}},
    57  	{[]byte{0x11}},
    58  	{[]byte{0x11, 0x12}},
    59  	{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
    60  	{[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}},
    61  	{largeDataChunk()},
    62  }
    63  
    64  var reverseBitsTests = []*reverseBitsTest{
    65  	{1, 1, 1},
    66  	{1, 2, 2},
    67  	{1, 3, 4},
    68  	{1, 4, 8},
    69  	{1, 5, 16},
    70  	{17, 5, 17},
    71  	{257, 9, 257},
    72  	{29, 5, 23},
    73  }
    74  
    75  func largeDataChunk() []byte {
    76  	result := make([]byte, 100000)
    77  	for i := range result {
    78  		result[i] = byte(i * i & 0xFF)
    79  	}
    80  	return result
    81  }
    82  
    83  func TestDeflate(t *testing.T) {
    84  	for _, h := range deflateTests {
    85  		var buf bytes.Buffer
    86  		w, err := NewWriter(&buf, h.level)
    87  		if err != nil {
    88  			t.Errorf("NewWriter: %v", err)
    89  			continue
    90  		}
    91  		w.Write(h.in)
    92  		w.Close()
    93  		if !bytes.Equal(buf.Bytes(), h.out) {
    94  			t.Errorf("Deflate(%d, %x) = %x, want %x", h.level, h.in, buf.Bytes(), h.out)
    95  		}
    96  	}
    97  }
    98  
    99  // A sparseReader returns a stream consisting of 0s followed by 1<<16 1s.
   100  // This tests missing hash references in a very large input.
   101  type sparseReader struct {
   102  	l   int64
   103  	cur int64
   104  }
   105  
   106  func (r *sparseReader) Read(b []byte) (n int, err error) {
   107  	if r.cur >= r.l {
   108  		return 0, io.EOF
   109  	}
   110  	n = len(b)
   111  	cur := r.cur + int64(n)
   112  	if cur > r.l {
   113  		n -= int(cur - r.l)
   114  		cur = r.l
   115  	}
   116  	for i := range b[0:n] {
   117  		if r.cur+int64(i) >= r.l-1<<16 {
   118  			b[i] = 1
   119  		} else {
   120  			b[i] = 0
   121  		}
   122  	}
   123  	r.cur = cur
   124  	return
   125  }
   126  
   127  func TestVeryLongSparseChunk(t *testing.T) {
   128  	if testing.Short() {
   129  		t.Skip("skipping sparse chunk during short test")
   130  	}
   131  	w, err := NewWriter(ioutil.Discard, 1)
   132  	if err != nil {
   133  		t.Errorf("NewWriter: %v", err)
   134  		return
   135  	}
   136  	if _, err = io.Copy(w, &sparseReader{l: 23E8}); err != nil {
   137  		t.Errorf("Compress failed: %v", err)
   138  		return
   139  	}
   140  }
   141  
   142  type syncBuffer struct {
   143  	buf    bytes.Buffer
   144  	mu     sync.RWMutex
   145  	closed bool
   146  	ready  chan bool
   147  }
   148  
   149  func newSyncBuffer() *syncBuffer {
   150  	return &syncBuffer{ready: make(chan bool, 1)}
   151  }
   152  
   153  func (b *syncBuffer) Read(p []byte) (n int, err error) {
   154  	for {
   155  		b.mu.RLock()
   156  		n, err = b.buf.Read(p)
   157  		b.mu.RUnlock()
   158  		if n > 0 || b.closed {
   159  			return
   160  		}
   161  		<-b.ready
   162  	}
   163  }
   164  
   165  func (b *syncBuffer) signal() {
   166  	select {
   167  	case b.ready <- true:
   168  	default:
   169  	}
   170  }
   171  
   172  func (b *syncBuffer) Write(p []byte) (n int, err error) {
   173  	n, err = b.buf.Write(p)
   174  	b.signal()
   175  	return
   176  }
   177  
   178  func (b *syncBuffer) WriteMode() {
   179  	b.mu.Lock()
   180  }
   181  
   182  func (b *syncBuffer) ReadMode() {
   183  	b.mu.Unlock()
   184  	b.signal()
   185  }
   186  
   187  func (b *syncBuffer) Close() error {
   188  	b.closed = true
   189  	b.signal()
   190  	return nil
   191  }
   192  
   193  func testSync(t *testing.T, level int, input []byte, name string) {
   194  	if len(input) == 0 {
   195  		return
   196  	}
   197  
   198  	t.Logf("--testSync %d, %d, %s", level, len(input), name)
   199  	buf := newSyncBuffer()
   200  	buf1 := new(bytes.Buffer)
   201  	buf.WriteMode()
   202  	w, err := NewWriter(io.MultiWriter(buf, buf1), level)
   203  	if err != nil {
   204  		t.Errorf("NewWriter: %v", err)
   205  		return
   206  	}
   207  	r := NewReader(buf)
   208  
   209  	// Write half the input and read back.
   210  	for i := 0; i < 2; i++ {
   211  		var lo, hi int
   212  		if i == 0 {
   213  			lo, hi = 0, (len(input)+1)/2
   214  		} else {
   215  			lo, hi = (len(input)+1)/2, len(input)
   216  		}
   217  		t.Logf("#%d: write %d-%d", i, lo, hi)
   218  		if _, err := w.Write(input[lo:hi]); err != nil {
   219  			t.Errorf("testSync: write: %v", err)
   220  			return
   221  		}
   222  		if i == 0 {
   223  			if err := w.Flush(); err != nil {
   224  				t.Errorf("testSync: flush: %v", err)
   225  				return
   226  			}
   227  		} else {
   228  			if err := w.Close(); err != nil {
   229  				t.Errorf("testSync: close: %v", err)
   230  			}
   231  		}
   232  		buf.ReadMode()
   233  		out := make([]byte, hi-lo+1)
   234  		m, err := io.ReadAtLeast(r, out, hi-lo)
   235  		t.Logf("#%d: read %d", i, m)
   236  		if m != hi-lo || err != nil {
   237  			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())
   238  			return
   239  		}
   240  		if !bytes.Equal(input[lo:hi], out[:hi-lo]) {
   241  			t.Errorf("testSync/%d: read wrong bytes: %x vs %x", i, input[lo:hi], out[:hi-lo])
   242  			return
   243  		}
   244  		// This test originally checked that after reading
   245  		// the first half of the input, there was nothing left
   246  		// in the read buffer (buf.buf.Len() != 0) but that is
   247  		// not necessarily the case: the write Flush may emit
   248  		// some extra framing bits that are not necessary
   249  		// to process to obtain the first half of the uncompressed
   250  		// data.  The test ran correctly most of the time, because
   251  		// the background goroutine had usually read even
   252  		// those extra bits by now, but it's not a useful thing to
   253  		// check.
   254  		buf.WriteMode()
   255  	}
   256  	buf.ReadMode()
   257  	out := make([]byte, 10)
   258  	if n, err := r.Read(out); n > 0 || err != io.EOF {
   259  		t.Errorf("testSync (%d, %d, %s): final Read: %d, %v (hex: %x)", level, len(input), name, n, err, out[0:n])
   260  	}
   261  	if buf.buf.Len() != 0 {
   262  		t.Errorf("testSync (%d, %d, %s): extra data at end", level, len(input), name)
   263  	}
   264  	r.Close()
   265  
   266  	// stream should work for ordinary reader too
   267  	r = NewReader(buf1)
   268  	out, err = ioutil.ReadAll(r)
   269  	if err != nil {
   270  		t.Errorf("testSync: read: %s", err)
   271  		return
   272  	}
   273  	r.Close()
   274  	if !bytes.Equal(input, out) {
   275  		t.Errorf("testSync: decompress(compress(data)) != data: level=%d input=%s", level, name)
   276  	}
   277  }
   278  
   279  func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) {
   280  	var buffer bytes.Buffer
   281  	w, err := NewWriter(&buffer, level)
   282  	if err != nil {
   283  		t.Errorf("NewWriter: %v", err)
   284  		return
   285  	}
   286  	w.Write(input)
   287  	w.Close()
   288  	if limit > 0 && buffer.Len() > limit {
   289  		t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit)
   290  		return
   291  	}
   292  	r := NewReader(&buffer)
   293  	out, err := ioutil.ReadAll(r)
   294  	if err != nil {
   295  		t.Errorf("read: %s", err)
   296  		return
   297  	}
   298  	r.Close()
   299  	if !bytes.Equal(input, out) {
   300  		t.Errorf("decompress(compress(data)) != data: level=%d input=%s", level, name)
   301  		return
   302  	}
   303  	testSync(t, level, input, name)
   304  }
   305  
   306  func testToFromWithLimit(t *testing.T, input []byte, name string, limit [10]int) {
   307  	for i := 0; i < 10; i++ {
   308  		testToFromWithLevelAndLimit(t, i, input, name, limit[i])
   309  	}
   310  }
   311  
   312  func TestDeflateInflate(t *testing.T) {
   313  	for i, h := range deflateInflateTests {
   314  		testToFromWithLimit(t, h.in, fmt.Sprintf("#%d", i), [10]int{})
   315  	}
   316  }
   317  
   318  func TestReverseBits(t *testing.T) {
   319  	for _, h := range reverseBitsTests {
   320  		if v := reverseBits(h.in, h.bitCount); v != h.out {
   321  			t.Errorf("reverseBits(%v,%v) = %v, want %v",
   322  				h.in, h.bitCount, v, h.out)
   323  		}
   324  	}
   325  }
   326  
   327  type deflateInflateStringTest struct {
   328  	filename string
   329  	label    string
   330  	limit    [10]int
   331  }
   332  
   333  var deflateInflateStringTests = []deflateInflateStringTest{
   334  	{
   335  		"../testdata/e.txt",
   336  		"2.718281828...",
   337  		[...]int{100018, 50650, 50960, 51150, 50930, 50790, 50790, 50790, 50790, 50790},
   338  	},
   339  	{
   340  		"../testdata/Mark.Twain-Tom.Sawyer.txt",
   341  		"Mark.Twain-Tom.Sawyer",
   342  		[...]int{407330, 187598, 180361, 172974, 169160, 163476, 160936, 160506, 160295, 160295},
   343  	},
   344  }
   345  
   346  func TestDeflateInflateString(t *testing.T) {
   347  	if testing.Short() && testenv.Builder() == "" {
   348  		t.Skip("skipping in short mode")
   349  	}
   350  	for _, test := range deflateInflateStringTests {
   351  		gold, err := ioutil.ReadFile(test.filename)
   352  		if err != nil {
   353  			t.Error(err)
   354  		}
   355  		testToFromWithLimit(t, gold, test.label, test.limit)
   356  		if testing.Short() {
   357  			break
   358  		}
   359  	}
   360  }
   361  
   362  func TestReaderDict(t *testing.T) {
   363  	const (
   364  		dict = "hello world"
   365  		text = "hello again world"
   366  	)
   367  	var b bytes.Buffer
   368  	w, err := NewWriter(&b, 5)
   369  	if err != nil {
   370  		t.Fatalf("NewWriter: %v", err)
   371  	}
   372  	w.Write([]byte(dict))
   373  	w.Flush()
   374  	b.Reset()
   375  	w.Write([]byte(text))
   376  	w.Close()
   377  
   378  	r := NewReaderDict(&b, []byte(dict))
   379  	data, err := ioutil.ReadAll(r)
   380  	if err != nil {
   381  		t.Fatal(err)
   382  	}
   383  	if string(data) != "hello again world" {
   384  		t.Fatalf("read returned %q want %q", string(data), text)
   385  	}
   386  }
   387  
   388  func TestWriterDict(t *testing.T) {
   389  	const (
   390  		dict = "hello world"
   391  		text = "hello again world"
   392  	)
   393  	var b bytes.Buffer
   394  	w, err := NewWriter(&b, 5)
   395  	if err != nil {
   396  		t.Fatalf("NewWriter: %v", err)
   397  	}
   398  	w.Write([]byte(dict))
   399  	w.Flush()
   400  	b.Reset()
   401  	w.Write([]byte(text))
   402  	w.Close()
   403  
   404  	var b1 bytes.Buffer
   405  	w, _ = NewWriterDict(&b1, 5, []byte(dict))
   406  	w.Write([]byte(text))
   407  	w.Close()
   408  
   409  	if !bytes.Equal(b1.Bytes(), b.Bytes()) {
   410  		t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes())
   411  	}
   412  }
   413  
   414  // See https://golang.org/issue/2508
   415  func TestRegression2508(t *testing.T) {
   416  	if testing.Short() {
   417  		t.Logf("test disabled with -short")
   418  		return
   419  	}
   420  	w, err := NewWriter(ioutil.Discard, 1)
   421  	if err != nil {
   422  		t.Fatalf("NewWriter: %v", err)
   423  	}
   424  	buf := make([]byte, 1024)
   425  	for i := 0; i < 131072; i++ {
   426  		if _, err := w.Write(buf); err != nil {
   427  			t.Fatalf("writer failed: %v", err)
   428  		}
   429  	}
   430  	w.Close()
   431  }
   432  
   433  func TestWriterReset(t *testing.T) {
   434  	for level := 0; level <= 9; level++ {
   435  		if testing.Short() && level > 1 {
   436  			break
   437  		}
   438  		w, err := NewWriter(ioutil.Discard, level)
   439  		if err != nil {
   440  			t.Fatalf("NewWriter: %v", err)
   441  		}
   442  		buf := []byte("hello world")
   443  		n := 1024
   444  		if testing.Short() {
   445  			n = 10
   446  		}
   447  		for i := 0; i < n; i++ {
   448  			w.Write(buf)
   449  		}
   450  		w.Reset(ioutil.Discard)
   451  
   452  		wref, err := NewWriter(ioutil.Discard, level)
   453  		if err != nil {
   454  			t.Fatalf("NewWriter: %v", err)
   455  		}
   456  
   457  		// DeepEqual doesn't compare functions.
   458  		w.d.fill, wref.d.fill = nil, nil
   459  		w.d.step, wref.d.step = nil, nil
   460  		if !reflect.DeepEqual(w, wref) {
   461  			t.Errorf("level %d Writer not reset after Reset", level)
   462  		}
   463  	}
   464  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, NoCompression) })
   465  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, DefaultCompression) })
   466  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, BestCompression) })
   467  	dict := []byte("we are the world")
   468  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, NoCompression, dict) })
   469  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, DefaultCompression, dict) })
   470  	testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, BestCompression, dict) })
   471  }
   472  
   473  func testResetOutput(t *testing.T, newWriter func(w io.Writer) (*Writer, error)) {
   474  	buf := new(bytes.Buffer)
   475  	w, err := newWriter(buf)
   476  	if err != nil {
   477  		t.Fatalf("NewWriter: %v", err)
   478  	}
   479  	b := []byte("hello world")
   480  	for i := 0; i < 1024; i++ {
   481  		w.Write(b)
   482  	}
   483  	w.Close()
   484  	out1 := buf.String()
   485  
   486  	buf2 := new(bytes.Buffer)
   487  	w.Reset(buf2)
   488  	for i := 0; i < 1024; i++ {
   489  		w.Write(b)
   490  	}
   491  	w.Close()
   492  	out2 := buf2.String()
   493  
   494  	if out1 != out2 {
   495  		t.Errorf("got %q, expected %q", out2, out1)
   496  	}
   497  	t.Logf("got %d bytes", len(out1))
   498  }