...
Run Format

Source file src/compress/zlib/writer_test.go

Documentation: compress/zlib

     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 zlib
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"internal/testenv"
    11  	"io"
    12  	"io/ioutil"
    13  	"os"
    14  	"testing"
    15  )
    16  
    17  var filenames = []string{
    18  	"../testdata/gettysburg.txt",
    19  	"../testdata/e.txt",
    20  	"../testdata/pi.txt",
    21  }
    22  
    23  var data = []string{
    24  	"test a reasonable sized string that can be compressed",
    25  }
    26  
    27  // Tests that compressing and then decompressing the given file at the given compression level and dictionary
    28  // yields equivalent bytes to the original file.
    29  func testFileLevelDict(t *testing.T, fn string, level int, d string) {
    30  	// Read the file, as golden output.
    31  	golden, err := os.Open(fn)
    32  	if err != nil {
    33  		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
    34  		return
    35  	}
    36  	defer golden.Close()
    37  	b0, err0 := ioutil.ReadAll(golden)
    38  	if err0 != nil {
    39  		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
    40  		return
    41  	}
    42  	testLevelDict(t, fn, b0, level, d)
    43  }
    44  
    45  func testLevelDict(t *testing.T, fn string, b0 []byte, level int, d string) {
    46  	// Make dictionary, if given.
    47  	var dict []byte
    48  	if d != "" {
    49  		dict = []byte(d)
    50  	}
    51  
    52  	// Push data through a pipe that compresses at the write end, and decompresses at the read end.
    53  	piper, pipew := io.Pipe()
    54  	defer piper.Close()
    55  	go func() {
    56  		defer pipew.Close()
    57  		zlibw, err := NewWriterLevelDict(pipew, level, dict)
    58  		if err != nil {
    59  			t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
    60  			return
    61  		}
    62  		defer zlibw.Close()
    63  		_, err = zlibw.Write(b0)
    64  		if err != nil {
    65  			t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
    66  			return
    67  		}
    68  	}()
    69  	zlibr, err := NewReaderDict(piper, dict)
    70  	if err != nil {
    71  		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
    72  		return
    73  	}
    74  	defer zlibr.Close()
    75  
    76  	// Compare the decompressed data.
    77  	b1, err1 := ioutil.ReadAll(zlibr)
    78  	if err1 != nil {
    79  		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
    80  		return
    81  	}
    82  	if len(b0) != len(b1) {
    83  		t.Errorf("%s (level=%d, dict=%q): length mismatch %d versus %d", fn, level, d, len(b0), len(b1))
    84  		return
    85  	}
    86  	for i := 0; i < len(b0); i++ {
    87  		if b0[i] != b1[i] {
    88  			t.Errorf("%s (level=%d, dict=%q): mismatch at %d, 0x%02x versus 0x%02x\n", fn, level, d, i, b0[i], b1[i])
    89  			return
    90  		}
    91  	}
    92  }
    93  
    94  func testFileLevelDictReset(t *testing.T, fn string, level int, dict []byte) {
    95  	var b0 []byte
    96  	var err error
    97  	if fn != "" {
    98  		b0, err = ioutil.ReadFile(fn)
    99  		if err != nil {
   100  			t.Errorf("%s (level=%d): %v", fn, level, err)
   101  			return
   102  		}
   103  	}
   104  
   105  	// Compress once.
   106  	buf := new(bytes.Buffer)
   107  	var zlibw *Writer
   108  	if dict == nil {
   109  		zlibw, err = NewWriterLevel(buf, level)
   110  	} else {
   111  		zlibw, err = NewWriterLevelDict(buf, level, dict)
   112  	}
   113  	if err == nil {
   114  		_, err = zlibw.Write(b0)
   115  	}
   116  	if err == nil {
   117  		err = zlibw.Close()
   118  	}
   119  	if err != nil {
   120  		t.Errorf("%s (level=%d): %v", fn, level, err)
   121  		return
   122  	}
   123  	out := buf.String()
   124  
   125  	// Reset and compress again.
   126  	buf2 := new(bytes.Buffer)
   127  	zlibw.Reset(buf2)
   128  	_, err = zlibw.Write(b0)
   129  	if err == nil {
   130  		err = zlibw.Close()
   131  	}
   132  	if err != nil {
   133  		t.Errorf("%s (level=%d): %v", fn, level, err)
   134  		return
   135  	}
   136  	out2 := buf2.String()
   137  
   138  	if out2 != out {
   139  		t.Errorf("%s (level=%d): different output after reset (got %d bytes, expected %d",
   140  			fn, level, len(out2), len(out))
   141  	}
   142  }
   143  
   144  func TestWriter(t *testing.T) {
   145  	for i, s := range data {
   146  		b := []byte(s)
   147  		tag := fmt.Sprintf("#%d", i)
   148  		testLevelDict(t, tag, b, DefaultCompression, "")
   149  		testLevelDict(t, tag, b, NoCompression, "")
   150  		testLevelDict(t, tag, b, HuffmanOnly, "")
   151  		for level := BestSpeed; level <= BestCompression; level++ {
   152  			testLevelDict(t, tag, b, level, "")
   153  		}
   154  	}
   155  }
   156  
   157  func TestWriterBig(t *testing.T) {
   158  	for i, fn := range filenames {
   159  		testFileLevelDict(t, fn, DefaultCompression, "")
   160  		testFileLevelDict(t, fn, NoCompression, "")
   161  		testFileLevelDict(t, fn, HuffmanOnly, "")
   162  		for level := BestSpeed; level <= BestCompression; level++ {
   163  			testFileLevelDict(t, fn, level, "")
   164  			if level >= 1 && testing.Short() && testenv.Builder() == "" {
   165  				break
   166  			}
   167  		}
   168  		if i == 0 && testing.Short() && testenv.Builder() == "" {
   169  			break
   170  		}
   171  	}
   172  }
   173  
   174  func TestWriterDict(t *testing.T) {
   175  	const dictionary = "0123456789."
   176  	for i, fn := range filenames {
   177  		testFileLevelDict(t, fn, DefaultCompression, dictionary)
   178  		testFileLevelDict(t, fn, NoCompression, dictionary)
   179  		testFileLevelDict(t, fn, HuffmanOnly, dictionary)
   180  		for level := BestSpeed; level <= BestCompression; level++ {
   181  			testFileLevelDict(t, fn, level, dictionary)
   182  			if level >= 1 && testing.Short() && testenv.Builder() == "" {
   183  				break
   184  			}
   185  		}
   186  		if i == 0 && testing.Short() && testenv.Builder() == "" {
   187  			break
   188  		}
   189  	}
   190  }
   191  
   192  func TestWriterReset(t *testing.T) {
   193  	const dictionary = "0123456789."
   194  	for _, fn := range filenames {
   195  		testFileLevelDictReset(t, fn, NoCompression, nil)
   196  		testFileLevelDictReset(t, fn, DefaultCompression, nil)
   197  		testFileLevelDictReset(t, fn, HuffmanOnly, nil)
   198  		testFileLevelDictReset(t, fn, NoCompression, []byte(dictionary))
   199  		testFileLevelDictReset(t, fn, DefaultCompression, []byte(dictionary))
   200  		testFileLevelDictReset(t, fn, HuffmanOnly, []byte(dictionary))
   201  		if testing.Short() {
   202  			break
   203  		}
   204  		for level := BestSpeed; level <= BestCompression; level++ {
   205  			testFileLevelDictReset(t, fn, level, nil)
   206  		}
   207  	}
   208  }
   209  
   210  func TestWriterDictIsUsed(t *testing.T) {
   211  	var input = []byte("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
   212  	var buf bytes.Buffer
   213  	compressor, err := NewWriterLevelDict(&buf, BestCompression, input)
   214  	if err != nil {
   215  		t.Errorf("error in NewWriterLevelDict: %s", err)
   216  		return
   217  	}
   218  	compressor.Write(input)
   219  	compressor.Close()
   220  	const expectedMaxSize = 25
   221  	output := buf.Bytes()
   222  	if len(output) > expectedMaxSize {
   223  		t.Errorf("result too large (got %d, want <= %d bytes). Is the dictionary being used?", len(output), expectedMaxSize)
   224  	}
   225  }
   226  

View as plain text