Files
VictoriaMetrics/lib/encoding/zstd/zstd_test.go
2026-02-18 14:28:30 +01:00

161 lines
4.2 KiB
Go

//go:build cgo
package zstd
import (
"bytes"
"encoding/hex"
"fmt"
"math/rand"
"testing"
pure "github.com/klauspost/compress/zstd"
cgo "github.com/valyala/gozstd"
)
func TestDecomrpessLimitedOK(t *testing.T) {
f := func(compressedData []byte, limit int) {
t.Helper()
_, err := DecompressLimited(nil, compressedData, limit)
if err != nil {
t.Fatalf("cannot decompress data with limit=%d: %s", limit, err)
}
}
var bb bytes.Buffer
for bb.Len() < 12*128*1024 {
fmt.Fprintf(&bb, "compress/decompress big data %d, ", bb.Len())
}
originData := bb.Bytes()
// block decompression
cd := CompressLevel(nil, originData, 0)
// decompressed size matches block limit
f(cd, len(originData))
// unlimited
f(cd, 0)
}
func TestDecompressLimitedFail(t *testing.T) {
f := func(input []byte, limit int) {
t.Helper()
_, err := DecompressLimited(nil, input, limit)
if err == nil {
t.Errorf("unexpected nil-error for decompress with limit: %d", limit)
}
}
var bb bytes.Buffer
for bb.Len() < 12*128*1024 {
fmt.Fprintf(&bb, "compress/decompress big data %d, ", bb.Len())
}
// valid input bigger than limit
f(bb.Bytes(), 1024)
input, err := hex.DecodeString("28b52ffd8400005ed0b209000030ecaf4412")
if err != nil {
t.Fatalf("BUG: unexpected hex input: %s", err)
}
// input with framecontent bigger than actual payload
f(input, 512)
// input with stream windowSize bigger than limit
input, err = hex.DecodeString("28b52ffd04981900003030304e8da22b")
if err != nil {
t.Fatalf("BUG: unexpected hex input: %s", err)
}
f(input, 8*1e6*10)
}
func TestCompressDecompress(t *testing.T) {
testCrossCompressDecompress(t, []byte("a"))
testCrossCompressDecompress(t, []byte("foobarbaz"))
r := rand.New(rand.NewSource(1))
var b []byte
for range 64 * 1024 {
b = append(b, byte(r.Int31n(256)))
}
testCrossCompressDecompress(t, b)
}
func testCrossCompressDecompress(t *testing.T, b []byte) {
testCompressDecompress(t, pureCompress, pureDecompress, b)
testCompressDecompress(t, cgoCompress, cgoDecompress, b)
testCompressDecompress(t, pureCompress, cgoDecompress, b)
testCompressDecompress(t, cgoCompress, pureDecompress, b)
}
func testCompressDecompress(t *testing.T, compress compressFn, decompress decompressFn, b []byte) {
bc, err := compress(nil, b, 5)
if err != nil {
t.Fatalf("unexpected error when compressing b=%x: %s", b, err)
}
bNew, err := decompress(nil, bc)
if err != nil {
t.Fatalf("unexpected error when decompressing b=%x from bc=%x: %s", b, bc, err)
}
if string(bNew) != string(b) {
t.Fatalf("invalid bNew; got\n%x; expecting\n%x", bNew, b)
}
prefix := []byte{1, 2, 33}
bcNew, err := compress(prefix, b, 5)
if err != nil {
t.Fatalf("unexpected error when compressing b=%x: %s", bcNew, err)
}
if string(bcNew[:len(prefix)]) != string(prefix) {
t.Fatalf("invalid prefix for b=%x; got\n%x; expecting\n%x", b, bcNew[:len(prefix)], prefix)
}
if string(bcNew[len(prefix):]) != string(bc) {
t.Fatalf("invalid prefixed bcNew for b=%x; got\n%x; expecting\n%x", b, bcNew[len(prefix):], bc)
}
bNew, err = decompress(prefix, bc)
if err != nil {
t.Fatalf("unexpected error when decompressing b=%x from bc=%x with prefix: %s", b, bc, err)
}
if string(bNew[:len(prefix)]) != string(prefix) {
t.Fatalf("invalid bNew prefix when decompressing bc=%x; got\n%x; expecting\n%x", bc, bNew[:len(prefix)], prefix)
}
if string(bNew[len(prefix):]) != string(b) {
t.Fatalf("invalid prefixed bNew; got\n%x; expecting\n%x", bNew[len(prefix):], b)
}
}
type compressFn func(dst, src []byte, compressionLevel int) ([]byte, error)
func pureCompress(dst, src []byte, _ int) ([]byte, error) {
w, err := pure.NewWriter(nil,
pure.WithEncoderCRC(false), // Disable CRC for performance reasons.
pure.WithEncoderLevel(pure.SpeedBestCompression))
if err != nil {
return nil, err
}
return w.EncodeAll(src, dst), nil
}
func cgoCompress(dst, src []byte, compressionLevel int) ([]byte, error) {
return cgo.CompressLevel(dst, src, compressionLevel), nil
}
type decompressFn func(dst, src []byte) ([]byte, error)
func pureDecompress(dst, src []byte) ([]byte, error) {
decoder, err := pure.NewReader(nil)
if err != nil {
return nil, err
}
return decoder.DecodeAll(src, dst)
}
func cgoDecompress(dst, src []byte) ([]byte, error) {
return cgo.Decompress(dst, src)
}