...

Source file src/compress/lzw/writer_test.go

Documentation: compress/lzw

		 1  // Copyright 2011 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 lzw
		 6  
		 7  import (
		 8  	"bytes"
		 9  	"fmt"
		10  	"internal/testenv"
		11  	"io"
		12  	"math"
		13  	"os"
		14  	"runtime"
		15  	"testing"
		16  )
		17  
		18  var filenames = []string{
		19  	"../testdata/gettysburg.txt",
		20  	"../testdata/e.txt",
		21  	"../testdata/pi.txt",
		22  }
		23  
		24  // testFile tests that compressing and then decompressing the given file with
		25  // the given options yields equivalent bytes to the original file.
		26  func testFile(t *testing.T, fn string, order Order, litWidth int) {
		27  	// Read the file, as golden output.
		28  	golden, err := os.Open(fn)
		29  	if err != nil {
		30  		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
		31  		return
		32  	}
		33  	defer golden.Close()
		34  
		35  	// Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
		36  	raw, err := os.Open(fn)
		37  	if err != nil {
		38  		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
		39  		return
		40  	}
		41  
		42  	piper, pipew := io.Pipe()
		43  	defer piper.Close()
		44  	go func() {
		45  		defer raw.Close()
		46  		defer pipew.Close()
		47  		lzww := NewWriter(pipew, order, litWidth)
		48  		defer lzww.Close()
		49  		var b [4096]byte
		50  		for {
		51  			n, err0 := raw.Read(b[:])
		52  			if err0 != nil && err0 != io.EOF {
		53  				t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err0)
		54  				return
		55  			}
		56  			_, err1 := lzww.Write(b[:n])
		57  			if err1 != nil {
		58  				t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err1)
		59  				return
		60  			}
		61  			if err0 == io.EOF {
		62  				break
		63  			}
		64  		}
		65  	}()
		66  	lzwr := NewReader(piper, order, litWidth)
		67  	defer lzwr.Close()
		68  
		69  	// Compare the two.
		70  	b0, err0 := io.ReadAll(golden)
		71  	b1, err1 := io.ReadAll(lzwr)
		72  	if err0 != nil {
		73  		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err0)
		74  		return
		75  	}
		76  	if err1 != nil {
		77  		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err1)
		78  		return
		79  	}
		80  	if len(b1) != len(b0) {
		81  		t.Errorf("%s (order=%d litWidth=%d): length mismatch %d != %d", fn, order, litWidth, len(b1), len(b0))
		82  		return
		83  	}
		84  	for i := 0; i < len(b0); i++ {
		85  		if b1[i] != b0[i] {
		86  			t.Errorf("%s (order=%d litWidth=%d): mismatch at %d, 0x%02x != 0x%02x\n", fn, order, litWidth, i, b1[i], b0[i])
		87  			return
		88  		}
		89  	}
		90  }
		91  
		92  func TestWriter(t *testing.T) {
		93  	for _, filename := range filenames {
		94  		for _, order := range [...]Order{LSB, MSB} {
		95  			// The test data "2.71828 etcetera" is ASCII text requiring at least 6 bits.
		96  			for litWidth := 6; litWidth <= 8; litWidth++ {
		97  				if filename == "../testdata/gettysburg.txt" && litWidth == 6 {
		98  					continue
		99  				}
	 100  				testFile(t, filename, order, litWidth)
	 101  			}
	 102  		}
	 103  		if testing.Short() && testenv.Builder() == "" {
	 104  			break
	 105  		}
	 106  	}
	 107  }
	 108  
	 109  func TestWriterReset(t *testing.T) {
	 110  	for _, order := range [...]Order{LSB, MSB} {
	 111  		t.Run(fmt.Sprintf("Order %d", order), func(t *testing.T) {
	 112  			for litWidth := 6; litWidth <= 8; litWidth++ {
	 113  				t.Run(fmt.Sprintf("LitWidth %d", litWidth), func(t *testing.T) {
	 114  					var data []byte
	 115  					if litWidth == 6 {
	 116  						data = []byte{1, 2, 3}
	 117  					} else {
	 118  						data = []byte(`lorem ipsum dolor sit amet`)
	 119  					}
	 120  					var buf bytes.Buffer
	 121  					w := NewWriter(&buf, order, litWidth)
	 122  					if _, err := w.Write(data); err != nil {
	 123  						t.Errorf("write: %v: %v", string(data), err)
	 124  					}
	 125  
	 126  					if err := w.Close(); err != nil {
	 127  						t.Errorf("close: %v", err)
	 128  					}
	 129  
	 130  					b1 := buf.Bytes()
	 131  					buf.Reset()
	 132  
	 133  					w.(*Writer).Reset(&buf, order, litWidth)
	 134  
	 135  					if _, err := w.Write(data); err != nil {
	 136  						t.Errorf("write: %v: %v", string(data), err)
	 137  					}
	 138  
	 139  					if err := w.Close(); err != nil {
	 140  						t.Errorf("close: %v", err)
	 141  					}
	 142  					b2 := buf.Bytes()
	 143  
	 144  					if !bytes.Equal(b1, b2) {
	 145  						t.Errorf("bytes written were not same")
	 146  					}
	 147  				})
	 148  			}
	 149  		})
	 150  	}
	 151  }
	 152  
	 153  func TestWriterReturnValues(t *testing.T) {
	 154  	w := NewWriter(io.Discard, LSB, 8)
	 155  	n, err := w.Write([]byte("asdf"))
	 156  	if n != 4 || err != nil {
	 157  		t.Errorf("got %d, %v, want 4, nil", n, err)
	 158  	}
	 159  }
	 160  
	 161  func TestSmallLitWidth(t *testing.T) {
	 162  	w := NewWriter(io.Discard, LSB, 2)
	 163  	if _, err := w.Write([]byte{0x03}); err != nil {
	 164  		t.Fatalf("write a byte < 1<<2: %v", err)
	 165  	}
	 166  	if _, err := w.Write([]byte{0x04}); err == nil {
	 167  		t.Fatal("write a byte >= 1<<2: got nil error, want non-nil")
	 168  	}
	 169  }
	 170  
	 171  func BenchmarkEncoder(b *testing.B) {
	 172  	buf, err := os.ReadFile("../testdata/e.txt")
	 173  	if err != nil {
	 174  		b.Fatal(err)
	 175  	}
	 176  	if len(buf) == 0 {
	 177  		b.Fatalf("test file has no data")
	 178  	}
	 179  
	 180  	for e := 4; e <= 6; e++ {
	 181  		n := int(math.Pow10(e))
	 182  		buf0 := buf
	 183  		buf1 := make([]byte, n)
	 184  		for i := 0; i < n; i += len(buf0) {
	 185  			if len(buf0) > n-i {
	 186  				buf0 = buf0[:n-i]
	 187  			}
	 188  			copy(buf1[i:], buf0)
	 189  		}
	 190  		buf0 = nil
	 191  		runtime.GC()
	 192  		b.Run(fmt.Sprint("1e", e), func(b *testing.B) {
	 193  			b.SetBytes(int64(n))
	 194  			for i := 0; i < b.N; i++ {
	 195  				w := NewWriter(io.Discard, LSB, 8)
	 196  				w.Write(buf1)
	 197  				w.Close()
	 198  			}
	 199  		})
	 200  		b.Run(fmt.Sprint("1e-Reuse", e), func(b *testing.B) {
	 201  			b.SetBytes(int64(n))
	 202  			w := NewWriter(io.Discard, LSB, 8)
	 203  			for i := 0; i < b.N; i++ {
	 204  				w.Write(buf1)
	 205  				w.Close()
	 206  				w.(*Writer).Reset(io.Discard, LSB, 8)
	 207  			}
	 208  		})
	 209  	}
	 210  }
	 211  

View as plain text