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