lsgo/lz4/internal/lz4block/block_test.go

167 lines
4.0 KiB
Go

//+build go1.9
package lz4block_test
import (
"bytes"
"fmt"
"io/ioutil"
"testing"
"github.com/pierrec/lz4/v4"
"github.com/pierrec/lz4/v4/internal/lz4block"
)
type testcase struct {
file string
compressible bool
src []byte
}
var rawFiles = []testcase{
// {"testdata/207326ba-36f8-11e7-954a-aca46ba8ca73.png", true, nil},
{"../../testdata/e.txt", false, nil},
{"../../testdata/gettysburg.txt", true, nil},
{"../../testdata/Mark.Twain-Tom.Sawyer.txt", true, nil},
{"../../testdata/pg1661.txt", true, nil},
{"../../testdata/pi.txt", false, nil},
{"../../testdata/random.data", false, nil},
{"../../testdata/repeat.txt", true, nil},
{"../../testdata/pg1661.txt", true, nil},
}
func TestCompressUncompressBlock(t *testing.T) {
type compressor func(s, d []byte) (int, error)
run := func(t *testing.T, tc testcase, compress compressor) int {
t.Helper()
src := tc.src
// Compress the data.
zbuf := make([]byte, lz4block.CompressBlockBound(len(src)))
n, err := compress(src, zbuf)
if err != nil {
t.Error(err)
return 0
}
zbuf = zbuf[:n]
// Make sure that it was actually compressed unless not compressible.
if !tc.compressible {
return 0
}
if n == 0 || n >= len(src) {
t.Errorf("data not compressed: %d/%d", n, len(src))
return 0
}
// Uncompress the data.
buf := make([]byte, len(src))
n, err = lz4block.UncompressBlock(zbuf, buf)
if err != nil {
t.Fatal(err)
} else if n < 0 || n > len(buf) {
t.Fatalf("returned written bytes > len(buf): n=%d available=%d", n, len(buf))
} else if n != len(src) {
t.Errorf("expected to decompress into %d bytes got %d", len(src), n)
}
buf = buf[:n]
if !bytes.Equal(src, buf) {
var c int
for i, b := range buf {
if c > 10 {
break
}
if src[i] != b {
t.Errorf("%d: exp(%x) != got(%x)", i, src[i], buf[i])
c++
}
}
t.Fatal("uncompressed compressed data not matching initial input")
return 0
}
return len(zbuf)
}
for _, tc := range rawFiles {
src, err := ioutil.ReadFile(tc.file)
if err != nil {
t.Fatal(err)
}
tc.src = src
var n, nhc int
t.Run("", func(t *testing.T) {
tc := tc
t.Run(tc.file, func(t *testing.T) {
n = run(t, tc, func(src, dst []byte) (int, error) {
return lz4block.CompressBlock(src, dst)
})
})
t.Run(fmt.Sprintf("%s HC", tc.file), func(t *testing.T) {
nhc = run(t, tc, func(src, dst []byte) (int, error) {
return lz4.CompressBlockHC(src, dst, 10, nil, nil)
})
})
})
if !t.Failed() {
t.Logf("%-40s: %8d / %8d / %8d\n", tc.file, n, nhc, len(src))
}
}
}
func TestCompressCornerCase_CopyDstUpperBound(t *testing.T) {
type compressor func(s, d []byte) (int, error)
run := func(src []byte, compress compressor) {
t.Helper()
// Compress the data.
// We provide a destination that is too small to trigger an out-of-bounds,
// which makes it return the error we want.
zbuf := make([]byte, int(float64(len(src))*0.40))
_, err := compress(src, zbuf)
if err != lz4.ErrInvalidSourceShortBuffer {
t.Fatal("err should be ErrInvalidSourceShortBuffer, was", err)
}
}
file := "../../testdata/upperbound.data"
src, err := ioutil.ReadFile(file)
if err != nil {
t.Fatal(err)
}
t.Run(file, func(t *testing.T) {
t.Parallel()
run(src, func(src, dst []byte) (int, error) {
return lz4block.CompressBlock(src, dst)
})
})
t.Run(fmt.Sprintf("%s HC", file), func(t *testing.T) {
t.Parallel()
run(src, func(src, dst []byte) (int, error) {
return lz4block.CompressBlockHC(src, dst, 16)
})
})
}
func TestIssue23(t *testing.T) {
compressBuf := make([]byte, lz4block.CompressBlockBound(1<<16))
for j := 1; j < 16; j++ {
var buf [1 << 16]byte
for i := 0; i < len(buf); i += j {
buf[i] = 1
}
n, _ := lz4block.CompressBlock(buf[:], compressBuf)
if got, want := n, 300; got > want {
t.Fatalf("not able to compress repeated data: got %d; want %d", got, want)
}
}
}