213 lines
5.4 KiB
Go
213 lines
5.4 KiB
Go
// Copyright 2009 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 zlib
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"testing"
|
|
)
|
|
|
|
var filenames = []string{
|
|
"../testdata/gettysburg.txt",
|
|
"../testdata/e.txt",
|
|
"../testdata/pi.txt",
|
|
}
|
|
|
|
var data = []string{
|
|
"test a reasonable sized string that can be compressed",
|
|
}
|
|
|
|
// Tests that compressing and then decompressing the given file at the given compression level and dictionary
|
|
// yields equivalent bytes to the original file.
|
|
func testFileLevelDict(t *testing.T, fn string, level int, d string) {
|
|
// Read the file, as golden output.
|
|
golden, err := os.Open(fn)
|
|
if err != nil {
|
|
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
|
|
return
|
|
}
|
|
defer golden.Close()
|
|
b0, err0 := ioutil.ReadAll(golden)
|
|
if err0 != nil {
|
|
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
|
|
return
|
|
}
|
|
testLevelDict(t, fn, b0, level, d)
|
|
}
|
|
|
|
func testLevelDict(t *testing.T, fn string, b0 []byte, level int, d string) {
|
|
// Make dictionary, if given.
|
|
var dict []byte
|
|
if d != "" {
|
|
dict = []byte(d)
|
|
}
|
|
|
|
// Push data through a pipe that compresses at the write end, and decompresses at the read end.
|
|
piper, pipew := io.Pipe()
|
|
defer piper.Close()
|
|
go func() {
|
|
defer pipew.Close()
|
|
zlibw, err := NewWriterLevelDict(pipew, level, dict)
|
|
if err != nil {
|
|
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
|
|
return
|
|
}
|
|
defer zlibw.Close()
|
|
_, err = zlibw.Write(b0)
|
|
if err != nil {
|
|
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
|
|
return
|
|
}
|
|
}()
|
|
zlibr, err := NewReaderDict(piper, dict)
|
|
if err != nil {
|
|
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
|
|
return
|
|
}
|
|
defer zlibr.Close()
|
|
|
|
// Compare the decompressed data.
|
|
b1, err1 := ioutil.ReadAll(zlibr)
|
|
if err1 != nil {
|
|
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
|
|
return
|
|
}
|
|
if len(b0) != len(b1) {
|
|
t.Errorf("%s (level=%d, dict=%q): length mismatch %d versus %d", fn, level, d, len(b0), len(b1))
|
|
return
|
|
}
|
|
for i := 0; i < len(b0); i++ {
|
|
if b0[i] != b1[i] {
|
|
t.Errorf("%s (level=%d, dict=%q): mismatch at %d, 0x%02x versus 0x%02x\n", fn, level, d, i, b0[i], b1[i])
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func testFileLevelDictReset(t *testing.T, fn string, level int, dict []byte) {
|
|
var b0 []byte
|
|
var err error
|
|
if fn != "" {
|
|
b0, err = ioutil.ReadFile(fn)
|
|
if err != nil {
|
|
t.Errorf("%s (level=%d): %v", fn, level, err)
|
|
return
|
|
}
|
|
}
|
|
|
|
// Compress once.
|
|
buf := new(bytes.Buffer)
|
|
var zlibw *Writer
|
|
if dict == nil {
|
|
zlibw, err = NewWriterLevel(buf, level)
|
|
} else {
|
|
zlibw, err = NewWriterLevelDict(buf, level, dict)
|
|
}
|
|
if err == nil {
|
|
_, err = zlibw.Write(b0)
|
|
}
|
|
if err == nil {
|
|
err = zlibw.Close()
|
|
}
|
|
if err != nil {
|
|
t.Errorf("%s (level=%d): %v", fn, level, err)
|
|
return
|
|
}
|
|
out := buf.String()
|
|
|
|
// Reset and compress again.
|
|
buf2 := new(bytes.Buffer)
|
|
zlibw.Reset(buf2)
|
|
_, err = zlibw.Write(b0)
|
|
if err == nil {
|
|
err = zlibw.Close()
|
|
}
|
|
if err != nil {
|
|
t.Errorf("%s (level=%d): %v", fn, level, err)
|
|
return
|
|
}
|
|
out2 := buf2.String()
|
|
|
|
if out2 != out {
|
|
t.Errorf("%s (level=%d): different output after reset (got %d bytes, expected %d",
|
|
fn, level, len(out2), len(out))
|
|
}
|
|
}
|
|
|
|
func TestWriter(t *testing.T) {
|
|
for i, s := range data {
|
|
b := []byte(s)
|
|
tag := fmt.Sprintf("#%d", i)
|
|
testLevelDict(t, tag, b, DefaultCompression, "")
|
|
testLevelDict(t, tag, b, NoCompression, "")
|
|
testLevelDict(t, tag, b, HuffmanOnly, "")
|
|
for level := BestSpeed; level <= BestCompression; level++ {
|
|
testLevelDict(t, tag, b, level, "")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWriterBig(t *testing.T) {
|
|
for _, fn := range filenames {
|
|
testFileLevelDict(t, fn, DefaultCompression, "")
|
|
testFileLevelDict(t, fn, NoCompression, "")
|
|
testFileLevelDict(t, fn, HuffmanOnly, "")
|
|
for level := BestSpeed; level <= BestCompression; level++ {
|
|
testFileLevelDict(t, fn, level, "")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWriterDict(t *testing.T) {
|
|
const dictionary = "0123456789."
|
|
for _, fn := range filenames {
|
|
testFileLevelDict(t, fn, DefaultCompression, dictionary)
|
|
testFileLevelDict(t, fn, NoCompression, dictionary)
|
|
testFileLevelDict(t, fn, HuffmanOnly, dictionary)
|
|
for level := BestSpeed; level <= BestCompression; level++ {
|
|
testFileLevelDict(t, fn, level, dictionary)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWriterReset(t *testing.T) {
|
|
const dictionary = "0123456789."
|
|
for _, fn := range filenames {
|
|
testFileLevelDictReset(t, fn, NoCompression, nil)
|
|
testFileLevelDictReset(t, fn, DefaultCompression, nil)
|
|
testFileLevelDictReset(t, fn, HuffmanOnly, nil)
|
|
testFileLevelDictReset(t, fn, NoCompression, []byte(dictionary))
|
|
testFileLevelDictReset(t, fn, DefaultCompression, []byte(dictionary))
|
|
testFileLevelDictReset(t, fn, HuffmanOnly, []byte(dictionary))
|
|
if testing.Short() {
|
|
break
|
|
}
|
|
for level := BestSpeed; level <= BestCompression; level++ {
|
|
testFileLevelDictReset(t, fn, level, nil)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWriterDictIsUsed(t *testing.T) {
|
|
var input = []byte("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
|
|
var buf bytes.Buffer
|
|
compressor, err := NewWriterLevelDict(&buf, BestCompression, input)
|
|
if err != nil {
|
|
t.Errorf("error in NewWriterLevelDict: %s", err)
|
|
return
|
|
}
|
|
compressor.Write(input)
|
|
compressor.Close()
|
|
const expectedMaxSize = 25
|
|
output := buf.Bytes()
|
|
if len(output) > expectedMaxSize {
|
|
t.Errorf("result too large (got %d, want <= %d bytes). Is the dictionary being used?", len(output), expectedMaxSize)
|
|
}
|
|
}
|