mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
211 lines
5.5 KiB
Go
211 lines
5.5 KiB
Go
package zstd
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"io/ioutil"
|
|
"runtime/debug"
|
|
"testing"
|
|
)
|
|
|
|
func failOnError(t *testing.T, msg string, err error) {
|
|
if err != nil {
|
|
debug.PrintStack()
|
|
t.Fatalf("%s: %s", msg, err)
|
|
}
|
|
}
|
|
|
|
func testCompressionDecompression(t *testing.T, dict []byte, payload []byte) {
|
|
var w bytes.Buffer
|
|
writer := NewWriterLevelDict(&w, DefaultCompression, dict)
|
|
_, err := writer.Write(payload)
|
|
failOnError(t, "Failed writing to compress object", err)
|
|
failOnError(t, "Failed to close compress object", writer.Close())
|
|
out := w.Bytes()
|
|
t.Logf("Compressed %v -> %v bytes", len(payload), len(out))
|
|
failOnError(t, "Failed compressing", err)
|
|
rr := bytes.NewReader(out)
|
|
// Check that we can decompress with Decompress()
|
|
decompressed, err := Decompress(nil, out)
|
|
failOnError(t, "Failed to decompress with Decompress()", err)
|
|
if string(payload) != string(decompressed) {
|
|
t.Fatalf("Payload did not match, lengths: %v & %v", len(payload), len(decompressed))
|
|
}
|
|
|
|
// Decompress
|
|
r := NewReaderDict(rr, dict)
|
|
dst := make([]byte, len(payload))
|
|
n, err := r.Read(dst)
|
|
if err != nil {
|
|
failOnError(t, "Failed to read for decompression", err)
|
|
}
|
|
dst = dst[:n]
|
|
if string(payload) != string(dst) { // Only print if we can print
|
|
if len(payload) < 100 && len(dst) < 100 {
|
|
t.Fatalf("Cannot compress and decompress: %s != %s", payload, dst)
|
|
} else {
|
|
t.Fatalf("Cannot compress and decompress (lengths: %v bytes & %v bytes)", len(payload), len(dst))
|
|
}
|
|
}
|
|
// Check EOF
|
|
n, err = r.Read(dst)
|
|
if err != io.EOF && len(dst) > 0 { // If we want 0 bytes, that should work
|
|
t.Fatalf("Error should have been EOF, was %s instead: (%v bytes read: %s)", err, n, dst[:n])
|
|
}
|
|
failOnError(t, "Failed to close decompress object", r.Close())
|
|
}
|
|
|
|
func TestResize(t *testing.T) {
|
|
if len(resize(nil, 129)) != 129 {
|
|
t.Fatalf("Cannot allocate new slice")
|
|
}
|
|
a := make([]byte, 1, 200)
|
|
b := resize(a, 129)
|
|
if &a[0] != &b[0] {
|
|
t.Fatalf("Address changed")
|
|
}
|
|
if len(b) != 129 {
|
|
t.Fatalf("Wrong size")
|
|
}
|
|
c := make([]byte, 5, 10)
|
|
d := resize(c, 129)
|
|
if len(d) != 129 {
|
|
t.Fatalf("Cannot allocate a new slice")
|
|
}
|
|
}
|
|
|
|
func TestStreamSimpleCompressionDecompression(t *testing.T) {
|
|
testCompressionDecompression(t, nil, []byte("Hello world!"))
|
|
}
|
|
|
|
func TestStreamEmptySlice(t *testing.T) {
|
|
testCompressionDecompression(t, nil, []byte{})
|
|
}
|
|
|
|
func TestZstdReaderLong(t *testing.T) {
|
|
var long bytes.Buffer
|
|
for i := 0; i < 10000; i++ {
|
|
long.Write([]byte("Hellow World!"))
|
|
}
|
|
testCompressionDecompression(t, nil, long.Bytes())
|
|
}
|
|
|
|
func TestStreamCompressionDecompression(t *testing.T) {
|
|
payload := []byte("Hello World!")
|
|
repeat := 10000
|
|
var intermediate bytes.Buffer
|
|
w := NewWriterLevel(&intermediate, 4)
|
|
for i := 0; i < repeat; i++ {
|
|
_, err := w.Write(payload)
|
|
failOnError(t, "Failed writing to compress object", err)
|
|
}
|
|
w.Close()
|
|
// Decompress
|
|
r := NewReader(&intermediate)
|
|
dst := make([]byte, len(payload))
|
|
for i := 0; i < repeat; i++ {
|
|
n, err := r.Read(dst)
|
|
failOnError(t, "Failed to decompress", err)
|
|
if n != len(payload) {
|
|
t.Fatalf("Did not read enough bytes: %v != %v", n, len(payload))
|
|
}
|
|
if string(dst) != string(payload) {
|
|
t.Fatalf("Did not read the same %s != %s", string(dst), string(payload))
|
|
}
|
|
}
|
|
// Check EOF
|
|
n, err := r.Read(dst)
|
|
if err != io.EOF {
|
|
t.Fatalf("Error should have been EOF, was %s instead: (%v bytes read: %s)", err, n, dst[:n])
|
|
}
|
|
failOnError(t, "Failed to close decompress object", r.Close())
|
|
}
|
|
|
|
func TestStreamRealPayload(t *testing.T) {
|
|
if raw == nil {
|
|
t.Skip(ErrNoPayloadEnv)
|
|
}
|
|
testCompressionDecompression(t, nil, raw)
|
|
}
|
|
|
|
func TestStreamEmptyPayload(t *testing.T) {
|
|
w := bytes.NewBuffer(nil)
|
|
writer := NewWriter(w)
|
|
_, err := writer.Write(nil)
|
|
failOnError(t, "failed to write empty slice", err)
|
|
err = writer.Close()
|
|
failOnError(t, "failed to close", err)
|
|
compressed := w.Bytes()
|
|
t.Logf("compressed buffer: 0x%x", compressed)
|
|
// Now recheck that if we decompress, we get empty slice
|
|
r := bytes.NewBuffer(compressed)
|
|
reader := NewReader(r)
|
|
decompressed, err := ioutil.ReadAll(reader)
|
|
failOnError(t, "failed to read", err)
|
|
err = reader.Close()
|
|
failOnError(t, "failed to close", err)
|
|
if string(decompressed) != "" {
|
|
t.Fatalf("Expected empty slice as decompressed, got %v instead", decompressed)
|
|
}
|
|
}
|
|
|
|
func BenchmarkStreamCompression(b *testing.B) {
|
|
if raw == nil {
|
|
b.Fatal(ErrNoPayloadEnv)
|
|
}
|
|
var intermediate bytes.Buffer
|
|
w := NewWriter(&intermediate)
|
|
defer w.Close()
|
|
b.SetBytes(int64(len(raw)))
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, err := w.Write(raw)
|
|
if err != nil {
|
|
b.Fatalf("Failed writing to compress object: %s", err)
|
|
}
|
|
// Prevent from unbound buffer growth.
|
|
intermediate.Reset()
|
|
}
|
|
}
|
|
|
|
func BenchmarkStreamDecompression(b *testing.B) {
|
|
if raw == nil {
|
|
b.Fatal(ErrNoPayloadEnv)
|
|
}
|
|
compressed, err := Compress(nil, raw)
|
|
if err != nil {
|
|
b.Fatalf("Failed to compress: %s", err)
|
|
}
|
|
_, err = Decompress(nil, compressed)
|
|
if err != nil {
|
|
b.Fatalf("Problem: %s", err)
|
|
}
|
|
|
|
dst := make([]byte, len(raw))
|
|
b.SetBytes(int64(len(raw)))
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
rr := bytes.NewReader(compressed)
|
|
r := NewReader(rr)
|
|
_, err := r.Read(dst)
|
|
if err != nil {
|
|
b.Fatalf("Failed to decompress: %s", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
type breakingReader struct {
|
|
}
|
|
|
|
func (r *breakingReader) Read(p []byte) (int, error) {
|
|
return len(p) - 1, io.ErrUnexpectedEOF
|
|
}
|
|
|
|
func TestUnexpectedEOFHandling(t *testing.T) {
|
|
r := NewReader(&breakingReader{})
|
|
_, err := r.Read(make([]byte, 1024))
|
|
if err == nil {
|
|
t.Error("Underlying error was handled silently")
|
|
}
|
|
}
|