...
Run Format

Source file src/compress/flate/writer_test.go

Documentation: compress/flate

  // Copyright 2012 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  package flate
  
  import (
  	"bytes"
  	"fmt"
  	"io"
  	"io/ioutil"
  	"math/rand"
  	"runtime"
  	"testing"
  )
  
  func BenchmarkEncode(b *testing.B) {
  	doBench(b, func(b *testing.B, buf0 []byte, level, n int) {
  		b.StopTimer()
  		b.SetBytes(int64(n))
  
  		buf1 := make([]byte, n)
  		for i := 0; i < n; i += len(buf0) {
  			if len(buf0) > n-i {
  				buf0 = buf0[:n-i]
  			}
  			copy(buf1[i:], buf0)
  		}
  		buf0 = nil
  		w, err := NewWriter(ioutil.Discard, level)
  		if err != nil {
  			b.Fatal(err)
  		}
  		runtime.GC()
  		b.StartTimer()
  		for i := 0; i < b.N; i++ {
  			w.Reset(ioutil.Discard)
  			w.Write(buf1)
  			w.Close()
  		}
  	})
  }
  
  // errorWriter is a writer that fails after N writes.
  type errorWriter struct {
  	N int
  }
  
  func (e *errorWriter) Write(b []byte) (int, error) {
  	if e.N <= 0 {
  		return 0, io.ErrClosedPipe
  	}
  	e.N--
  	return len(b), nil
  }
  
  // Test if errors from the underlying writer is passed upwards.
  func TestWriteError(t *testing.T) {
  	t.Parallel()
  	buf := new(bytes.Buffer)
  	n := 65536
  	if !testing.Short() {
  		n *= 4
  	}
  	for i := 0; i < n; i++ {
  		fmt.Fprintf(buf, "asdasfasf%d%dfghfgujyut%dyutyu\n", i, i, i)
  	}
  	in := buf.Bytes()
  	// We create our own buffer to control number of writes.
  	copyBuffer := make([]byte, 128)
  	for l := 0; l < 10; l++ {
  		for fail := 1; fail <= 256; fail *= 2 {
  			// Fail after 'fail' writes
  			ew := &errorWriter{N: fail}
  			w, err := NewWriter(ew, l)
  			if err != nil {
  				t.Fatalf("NewWriter: level %d: %v", l, err)
  			}
  			n, err := io.CopyBuffer(w, struct{ io.Reader }{bytes.NewBuffer(in)}, copyBuffer)
  			if err == nil {
  				t.Fatalf("Level %d: Expected an error, writer was %#v", l, ew)
  			}
  			n2, err := w.Write([]byte{1, 2, 2, 3, 4, 5})
  			if n2 != 0 {
  				t.Fatal("Level", l, "Expected 0 length write, got", n)
  			}
  			if err == nil {
  				t.Fatal("Level", l, "Expected an error")
  			}
  			err = w.Flush()
  			if err == nil {
  				t.Fatal("Level", l, "Expected an error on flush")
  			}
  			err = w.Close()
  			if err == nil {
  				t.Fatal("Level", l, "Expected an error on close")
  			}
  
  			w.Reset(ioutil.Discard)
  			n2, err = w.Write([]byte{1, 2, 3, 4, 5, 6})
  			if err != nil {
  				t.Fatal("Level", l, "Got unexpected error after reset:", err)
  			}
  			if n2 == 0 {
  				t.Fatal("Level", l, "Got 0 length write, expected > 0")
  			}
  			if testing.Short() {
  				return
  			}
  		}
  	}
  }
  
  // Test if two runs produce identical results
  // even when writing different sizes to the Writer.
  func TestDeterministic(t *testing.T) {
  	t.Parallel()
  	for i := 0; i <= 9; i++ {
  		t.Run(fmt.Sprint("L", i), func(t *testing.T) { testDeterministic(i, t) })
  	}
  	t.Run("LM2", func(t *testing.T) { testDeterministic(-2, t) })
  }
  
  func testDeterministic(i int, t *testing.T) {
  	t.Parallel()
  	// Test so much we cross a good number of block boundaries.
  	var length = maxStoreBlockSize*30 + 500
  	if testing.Short() {
  		length /= 10
  	}
  
  	// Create a random, but compressible stream.
  	rng := rand.New(rand.NewSource(1))
  	t1 := make([]byte, length)
  	for i := range t1 {
  		t1[i] = byte(rng.Int63() & 7)
  	}
  
  	// Do our first encode.
  	var b1 bytes.Buffer
  	br := bytes.NewBuffer(t1)
  	w, err := NewWriter(&b1, i)
  	if err != nil {
  		t.Fatal(err)
  	}
  	// Use a very small prime sized buffer.
  	cbuf := make([]byte, 787)
  	_, err = io.CopyBuffer(w, struct{ io.Reader }{br}, cbuf)
  	if err != nil {
  		t.Fatal(err)
  	}
  	w.Close()
  
  	// We choose a different buffer size,
  	// bigger than a maximum block, and also a prime.
  	var b2 bytes.Buffer
  	cbuf = make([]byte, 81761)
  	br2 := bytes.NewBuffer(t1)
  	w2, err := NewWriter(&b2, i)
  	if err != nil {
  		t.Fatal(err)
  	}
  	_, err = io.CopyBuffer(w2, struct{ io.Reader }{br2}, cbuf)
  	if err != nil {
  		t.Fatal(err)
  	}
  	w2.Close()
  
  	b1b := b1.Bytes()
  	b2b := b2.Bytes()
  
  	if !bytes.Equal(b1b, b2b) {
  		t.Errorf("level %d did not produce deterministic result, result mismatch, len(a) = %d, len(b) = %d", i, len(b1b), len(b2b))
  	}
  }
  

View as plain text