Black Lives Matter. Support the Equal Justice Initiative.

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