...

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

View as plain text