...

Source file src/github.com/pierrec/lz4/v4/writer_test.go

Documentation: github.com/pierrec/lz4/v4

     1  package lz4_test
     2  
     3  import (
     4  	"archive/tar"
     5  	"bytes"
     6  	"fmt"
     7  	"io"
     8  	"io/ioutil"
     9  	"os"
    10  	"reflect"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/pierrec/lz4/v4"
    15  	"github.com/pierrec/lz4/v4/internal/lz4block"
    16  )
    17  
    18  func TestWriter(t *testing.T) {
    19  	goldenFiles := []string{
    20  		"testdata/empty.txt",
    21  		"testdata/e.txt",
    22  		"testdata/gettysburg.txt",
    23  		"testdata/Mark.Twain-Tom.Sawyer.txt",
    24  		"testdata/Mark.Twain-Tom.Sawyer_long.txt",
    25  		"testdata/pg1661.txt",
    26  		"testdata/pi.txt",
    27  		"testdata/random.data",
    28  		"testdata/repeat.txt",
    29  		"testdata/issue102.data",
    30  	}
    31  
    32  	for _, fname := range goldenFiles {
    33  		for _, option := range []lz4.Option{
    34  			lz4.ConcurrencyOption(1),
    35  			lz4.BlockChecksumOption(true),
    36  			lz4.SizeOption(123),
    37  			lz4.ConcurrencyOption(4),
    38  		} {
    39  			label := fmt.Sprintf("%s/%s", fname, option)
    40  			t.Run(label, func(t *testing.T) {
    41  				fname := fname
    42  				option := option
    43  				t.Parallel()
    44  
    45  				raw, err := ioutil.ReadFile(fname)
    46  				if err != nil {
    47  					t.Fatal(err)
    48  				}
    49  				r := bytes.NewReader(raw)
    50  
    51  				// Compress.
    52  				zout := new(bytes.Buffer)
    53  				zw := lz4.NewWriter(zout)
    54  				if err := zw.Apply(option, lz4.CompressionLevelOption(lz4.Level1)); err != nil {
    55  					t.Fatal(err)
    56  				}
    57  				_, err = io.Copy(zw, r)
    58  				if err != nil {
    59  					t.Fatal(err)
    60  				}
    61  				err = zw.Close()
    62  				if err != nil {
    63  					t.Fatal(err)
    64  				}
    65  
    66  				// Uncompress.
    67  				out := new(bytes.Buffer)
    68  				zr := lz4.NewReader(zout)
    69  				n, err := io.Copy(out, zr)
    70  				if err != nil {
    71  					t.Fatal(err)
    72  				}
    73  
    74  				// The uncompressed data must be the same as the initial input.
    75  				if got, want := int(n), len(raw); got != want {
    76  					t.Errorf("invalid sizes: got %d; want %d", got, want)
    77  				}
    78  
    79  				if got, want := out.Bytes(), raw; !bytes.Equal(got, want) {
    80  					t.Fatal("uncompressed data does not match original")
    81  				}
    82  
    83  				if strings.Contains(option.String(), "SizeOption") {
    84  					if got, want := zr.Size(), 123; got != want {
    85  						t.Errorf("invalid sizes: got %d; want %d", got, want)
    86  					}
    87  				}
    88  			})
    89  		}
    90  	}
    91  }
    92  
    93  func TestWriter_Reset(t *testing.T) {
    94  	data := pg1661
    95  	buf := new(bytes.Buffer)
    96  	src := bytes.NewReader(data)
    97  	zw := lz4.NewWriter(buf)
    98  
    99  	// Partial write.
   100  	_, _ = io.CopyN(zw, src, int64(len(data))/2)
   101  
   102  	buf.Reset()
   103  	src.Reset(data)
   104  	zw.Reset(buf)
   105  	zw.Reset(buf)
   106  	// Another time to maybe trigger some edge case.
   107  	if _, err := io.Copy(zw, src); err != nil {
   108  		t.Fatal(err)
   109  	}
   110  	if err := zw.Close(); err != nil {
   111  		t.Fatal(err)
   112  	}
   113  	// Cannot compare compressed outputs directly, so compare the uncompressed output.
   114  	out := new(bytes.Buffer)
   115  	if _, err := io.Copy(out, lz4.NewReader(buf)); err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	if !reflect.DeepEqual(out.Bytes(), data) {
   119  		t.Fatal("result does not match original")
   120  	}
   121  }
   122  
   123  func TestIssue41(t *testing.T) {
   124  	r, w := io.Pipe()
   125  	zw := lz4.NewWriter(w)
   126  	zr := lz4.NewReader(r)
   127  
   128  	data := "x"
   129  	go func() {
   130  		_, _ = fmt.Fprint(zw, data)
   131  		_ = zw.Close()
   132  		_ = w.Close()
   133  	}()
   134  	var buf bytes.Buffer
   135  	_, _ = buf.ReadFrom(zr)
   136  	if got, want := buf.String(), data; got != want {
   137  		t.Fatal("uncompressed data does not match original")
   138  	}
   139  }
   140  
   141  func TestIssue43(t *testing.T) {
   142  	r, w := io.Pipe()
   143  	go func() {
   144  		defer w.Close()
   145  
   146  		f, err := os.Open("testdata/issue43.data")
   147  		if err != nil {
   148  			panic(err)
   149  		}
   150  		defer f.Close()
   151  
   152  		zw := lz4.NewWriter(w)
   153  		defer zw.Close()
   154  
   155  		_, err = io.Copy(zw, f)
   156  		if err != nil {
   157  			panic(err)
   158  		}
   159  	}()
   160  	_, err := io.Copy(ioutil.Discard, lz4.NewReader(r))
   161  	if err != nil {
   162  		t.Fatal(err)
   163  	}
   164  }
   165  
   166  func TestIssue51(t *testing.T) {
   167  	data, err := ioutil.ReadFile("testdata/issue51.data")
   168  	if err != nil {
   169  		t.Fatal(err)
   170  	}
   171  
   172  	zbuf := make([]byte, 8192)
   173  
   174  	n, err := lz4block.CompressBlock(data, zbuf)
   175  	if err != nil {
   176  		t.Fatal(err)
   177  	}
   178  	zbuf = zbuf[:n]
   179  
   180  	buf := make([]byte, 8192)
   181  	n, err = lz4block.UncompressBlock(zbuf, buf, nil)
   182  	if err != nil {
   183  		t.Fatal(err)
   184  	}
   185  	buf = buf[:n]
   186  	if !bytes.Equal(data, buf) {
   187  		t.Fatal("processed data does not match input")
   188  	}
   189  }
   190  
   191  func TestIssue167(t *testing.T) {
   192  	src := []byte("\xe300000000000000\t\x00\x00")
   193  	dst := make([]byte, 18)
   194  	_, err := lz4.UncompressBlock(src, dst)
   195  	if err == nil {
   196  		t.Fatal("expected buffer too short error")
   197  	}
   198  }
   199  
   200  func TestIssue71(t *testing.T) {
   201  	for _, tc := range []string{
   202  		"abc",               // < mfLimit
   203  		"abcdefghijklmnopq", // > mfLimit
   204  	} {
   205  		t.Run(tc, func(t *testing.T) {
   206  			src := []byte(tc)
   207  			bound := lz4block.CompressBlockBound(len(tc))
   208  
   209  			// Small buffer.
   210  			zSmall := make([]byte, bound-1)
   211  			n, err := lz4block.CompressBlock(src, zSmall)
   212  			if err != nil {
   213  				t.Fatal(err)
   214  			}
   215  			if n != 0 {
   216  				t.Fatal("should be incompressible")
   217  			}
   218  
   219  			// Large enough buffer.
   220  			zLarge := make([]byte, bound)
   221  			n, err = lz4block.CompressBlock(src, zLarge)
   222  			if err != nil {
   223  				t.Fatal(err)
   224  			}
   225  			if n == 0 {
   226  				t.Fatal("should be compressible")
   227  			}
   228  		})
   229  	}
   230  }
   231  
   232  func TestWriterFlush(t *testing.T) {
   233  	out := new(bytes.Buffer)
   234  	zw := lz4.NewWriter(out)
   235  	if err := zw.Apply(); err != nil {
   236  		t.Fatal(err)
   237  	}
   238  	data := strings.Repeat("0123456789", 100)
   239  	if _, err := zw.Write([]byte(data)); err != nil {
   240  		t.Fatal(err)
   241  	}
   242  	// header only
   243  	if got, want := out.Len(), 7; got != want {
   244  		t.Fatalf("got %d, want %d", got, want)
   245  	}
   246  	if err := zw.Flush(); err != nil {
   247  		t.Fatal(err)
   248  	}
   249  	// header + data
   250  	if got, want := out.Len(), 7; got == want {
   251  		t.Fatalf("got %d, want %d", got, want)
   252  	}
   253  }
   254  
   255  func TestWriterLegacy(t *testing.T) {
   256  	goldenFiles := []string{
   257  		"testdata/vmlinux_LZ4_19377",
   258  		"testdata/bzImage_lz4_isolated",
   259  	}
   260  
   261  	for _, fname := range goldenFiles {
   262  		t.Run(fname, func(t *testing.T) {
   263  			fname := fname
   264  			t.Parallel()
   265  
   266  			src, err := ioutil.ReadFile(fname)
   267  			if err != nil {
   268  				t.Fatal(err)
   269  			}
   270  
   271  			out := new(bytes.Buffer)
   272  			zw := lz4.NewWriter(out)
   273  			if err := zw.Apply(lz4.LegacyOption(true), lz4.CompressionLevelOption(lz4.Fast)); err != nil {
   274  				t.Fatal(err)
   275  			}
   276  			if _, err := io.Copy(zw, bytes.NewReader(src)); err != nil {
   277  				t.Fatal(err)
   278  			}
   279  			if err := zw.Close(); err != nil {
   280  				t.Fatal(err)
   281  			}
   282  
   283  			out2 := new(bytes.Buffer)
   284  			zr := lz4.NewReader(out)
   285  			if _, err := io.Copy(out2, zr); err != nil {
   286  				t.Fatal(err)
   287  			}
   288  			if !bytes.Equal(out2.Bytes(), src) {
   289  				t.Fatal("uncompressed compressed output different from source")
   290  			}
   291  		})
   292  	}
   293  }
   294  
   295  func TestWriterConcurrency(t *testing.T) {
   296  	const someGiantFile = "testdata/vmlinux_LZ4_19377"
   297  
   298  	out := new(bytes.Buffer)
   299  	zw := lz4.NewWriter(out)
   300  	if err := zw.Apply(
   301  		lz4.ConcurrencyOption(4),
   302  		lz4.BlockSizeOption(lz4.Block4Mb),
   303  		lz4.ChecksumOption(true)); err != nil {
   304  		t.Fatal(err)
   305  	}
   306  
   307  	// Test writing a tar file.
   308  	tw := tar.NewWriter(zw)
   309  	stat, err := os.Stat(someGiantFile)
   310  	if err != nil {
   311  		t.Fatal(err)
   312  	}
   313  	header, err := tar.FileInfoHeader(stat, "")
   314  	if err != nil {
   315  		t.Fatal(err)
   316  	}
   317  	if err := tw.WriteHeader(header); err != nil {
   318  		t.Fatal(err)
   319  	}
   320  	src, err := os.Open(someGiantFile)
   321  	if err != nil {
   322  		t.Fatal(err)
   323  	}
   324  	copyBuf := make([]byte, 16<<20) // Use a 16 MiB buffer.
   325  	if _, err := io.CopyBuffer(tw, src, copyBuf); err != nil {
   326  		t.Fatal(err)
   327  	}
   328  	if err := tw.Close(); err != nil {
   329  		t.Fatal(err)
   330  	}
   331  	if err := zw.Close(); err != nil {
   332  		t.Fatal(err)
   333  	}
   334  
   335  	zr := lz4.NewReader(out)
   336  	if _, err := io.Copy(ioutil.Discard, zr); err != nil {
   337  		t.Fatal(err)
   338  	}
   339  }
   340  

View as plain text