github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/compress/flate/writer_test.go (about)

     1  // Copyright 2012 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  	"math/rand"
    13  	"runtime"
    14  	"testing"
    15  )
    16  
    17  func BenchmarkEncode(b *testing.B) {
    18  	doBench(b, func(b *testing.B, buf0 []byte, level, n int) {
    19  		b.StopTimer()
    20  		b.SetBytes(int64(n))
    21  
    22  		buf1 := make([]byte, n)
    23  		for i := 0; i < n; i += len(buf0) {
    24  			if len(buf0) > n-i {
    25  				buf0 = buf0[:n-i]
    26  			}
    27  			copy(buf1[i:], buf0)
    28  		}
    29  		buf0 = nil
    30  		w, err := NewWriter(ioutil.Discard, level)
    31  		if err != nil {
    32  			b.Fatal(err)
    33  		}
    34  		runtime.GC()
    35  		b.StartTimer()
    36  		for i := 0; i < b.N; i++ {
    37  			w.Reset(ioutil.Discard)
    38  			w.Write(buf1)
    39  			w.Close()
    40  		}
    41  	})
    42  }
    43  
    44  // errorWriter is a writer that fails after N writes.
    45  type errorWriter struct {
    46  	N int
    47  }
    48  
    49  func (e *errorWriter) Write(b []byte) (int, error) {
    50  	if e.N <= 0 {
    51  		return 0, io.ErrClosedPipe
    52  	}
    53  	e.N--
    54  	return len(b), nil
    55  }
    56  
    57  // Test if errors from the underlying writer is passed upwards.
    58  func TestWriteError(t *testing.T) {
    59  	t.Parallel()
    60  	buf := new(bytes.Buffer)
    61  	n := 65536
    62  	if !testing.Short() {
    63  		n *= 4
    64  	}
    65  	for i := 0; i < n; i++ {
    66  		fmt.Fprintf(buf, "asdasfasf%d%dfghfgujyut%dyutyu\n", i, i, i)
    67  	}
    68  	in := buf.Bytes()
    69  	// We create our own buffer to control number of writes.
    70  	copyBuffer := make([]byte, 128)
    71  	for l := 0; l < 10; l++ {
    72  		for fail := 1; fail <= 256; fail *= 2 {
    73  			// Fail after 'fail' writes
    74  			ew := &errorWriter{N: fail}
    75  			w, err := NewWriter(ew, l)
    76  			if err != nil {
    77  				t.Fatalf("NewWriter: level %d: %v", l, err)
    78  			}
    79  			n, err := io.CopyBuffer(w, struct{ io.Reader }{bytes.NewBuffer(in)}, copyBuffer)
    80  			if err == nil {
    81  				t.Fatalf("Level %d: Expected an error, writer was %#v", l, ew)
    82  			}
    83  			n2, err := w.Write([]byte{1, 2, 2, 3, 4, 5})
    84  			if n2 != 0 {
    85  				t.Fatal("Level", l, "Expected 0 length write, got", n)
    86  			}
    87  			if err == nil {
    88  				t.Fatal("Level", l, "Expected an error")
    89  			}
    90  			err = w.Flush()
    91  			if err == nil {
    92  				t.Fatal("Level", l, "Expected an error on flush")
    93  			}
    94  			err = w.Close()
    95  			if err == nil {
    96  				t.Fatal("Level", l, "Expected an error on close")
    97  			}
    98  
    99  			w.Reset(ioutil.Discard)
   100  			n2, err = w.Write([]byte{1, 2, 3, 4, 5, 6})
   101  			if err != nil {
   102  				t.Fatal("Level", l, "Got unexpected error after reset:", err)
   103  			}
   104  			if n2 == 0 {
   105  				t.Fatal("Level", l, "Got 0 length write, expected > 0")
   106  			}
   107  			if testing.Short() {
   108  				return
   109  			}
   110  		}
   111  	}
   112  }
   113  
   114  // Test if two runs produce identical results
   115  // even when writing different sizes to the Writer.
   116  func TestDeterministic(t *testing.T) {
   117  	t.Parallel()
   118  	for i := 0; i <= 9; i++ {
   119  		t.Run(fmt.Sprint("L", i), func(t *testing.T) { testDeterministic(i, t) })
   120  	}
   121  	t.Run("LM2", func(t *testing.T) { testDeterministic(-2, t) })
   122  }
   123  
   124  func testDeterministic(i int, t *testing.T) {
   125  	t.Parallel()
   126  	// Test so much we cross a good number of block boundaries.
   127  	var length = maxStoreBlockSize*30 + 500
   128  	if testing.Short() {
   129  		length /= 10
   130  	}
   131  
   132  	// Create a random, but compressible stream.
   133  	rng := rand.New(rand.NewSource(1))
   134  	t1 := make([]byte, length)
   135  	for i := range t1 {
   136  		t1[i] = byte(rng.Int63() & 7)
   137  	}
   138  
   139  	// Do our first encode.
   140  	var b1 bytes.Buffer
   141  	br := bytes.NewBuffer(t1)
   142  	w, err := NewWriter(&b1, i)
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  	// Use a very small prime sized buffer.
   147  	cbuf := make([]byte, 787)
   148  	_, err = io.CopyBuffer(w, struct{ io.Reader }{br}, cbuf)
   149  	if err != nil {
   150  		t.Fatal(err)
   151  	}
   152  	w.Close()
   153  
   154  	// We choose a different buffer size,
   155  	// bigger than a maximum block, and also a prime.
   156  	var b2 bytes.Buffer
   157  	cbuf = make([]byte, 81761)
   158  	br2 := bytes.NewBuffer(t1)
   159  	w2, err := NewWriter(&b2, i)
   160  	if err != nil {
   161  		t.Fatal(err)
   162  	}
   163  	_, err = io.CopyBuffer(w2, struct{ io.Reader }{br2}, cbuf)
   164  	if err != nil {
   165  		t.Fatal(err)
   166  	}
   167  	w2.Close()
   168  
   169  	b1b := b1.Bytes()
   170  	b2b := b2.Bytes()
   171  
   172  	if !bytes.Equal(b1b, b2b) {
   173  		t.Errorf("level %d did not produce deterministic result, result mismatch, len(a) = %d, len(b) = %d", i, len(b1b), len(b2b))
   174  	}
   175  }