VictoriaMetrics/lib/bytesutil/bytebuffer_test.go

305 lines
7.6 KiB
Go

package bytesutil
import (
"bytes"
"fmt"
"io"
"testing"
"time"
)
func TestByteBuffer(t *testing.T) {
var bb ByteBuffer
n, err := bb.Write(nil)
if err != nil {
t.Fatalf("cannot write nil: %s", err)
}
if n != 0 {
t.Fatalf("unexpected n when writing nil; got %d; want %d", n, 0)
}
if len(bb.B) != 0 {
t.Fatalf("unexpected len(bb.B) after writing nil; got %d; want %d", len(bb.B), 0)
}
n, err = bb.Write([]byte{})
if err != nil {
t.Fatalf("cannot write empty slice: %s", err)
}
if n != 0 {
t.Fatalf("unexpected n when writing empty slice; got %d; want %d", n, 0)
}
if len(bb.B) != 0 {
t.Fatalf("unexpected len(bb.B) after writing empty slice; got %d; want %d", len(bb.B), 0)
}
data1 := []byte("123")
n, err = bb.Write(data1)
if err != nil {
t.Fatalf("cannot write %q: %s", data1, err)
}
if n != len(data1) {
t.Fatalf("unexpected n when writing %q; got %d; want %d", data1, n, len(data1))
}
if string(bb.B) != string(data1) {
t.Fatalf("unexpected bb.B; got %q; want %q", bb.B, data1)
}
data2 := []byte("1")
n, err = bb.Write(data2)
if err != nil {
t.Fatalf("cannot write %q: %s", data2, err)
}
if n != len(data2) {
t.Fatalf("unexpected n when writing %q; got %d; want %d", data2, n, len(data2))
}
if string(bb.B) != string(data1)+string(data2) {
t.Fatalf("unexpected bb.B; got %q; want %q", bb.B, string(data1)+string(data2))
}
bb.Reset()
if string(bb.B) != "" {
t.Fatalf("unexpected bb.B after reset; got %q; want %q", bb.B, "")
}
r := bb.NewReader().(*reader)
if r.readOffset != 0 {
t.Fatalf("unexpected r.readOffset after reset; got %d; want %d", r.readOffset, 0)
}
}
func TestByteBufferReadFrom(t *testing.T) {
var bbPool ByteBufferPool
t.Run("zero_bytes", func(t *testing.T) {
t.Parallel()
bb := bbPool.Get()
defer bbPool.Put(bb)
src := bytes.NewBufferString("")
n, err := bb.ReadFrom(src)
if err != nil {
t.Fatalf("error when reading empty string: %s", err)
}
if n != 0 {
t.Fatalf("unexpected number of bytes read; got %d; want %d", n, 0)
}
if len(bb.B) != 0 {
t.Fatalf("unexpejcted len(bb.B); got %d; want %d", len(bb.B), 0)
}
})
t.Run("non_zero_bytes", func(t *testing.T) {
t.Parallel()
bb := bbPool.Get()
defer bbPool.Put(bb)
s := "foobarbaz"
src := bytes.NewBufferString(s)
n, err := bb.ReadFrom(src)
if err != nil {
t.Fatalf("error when reading non-empty string: %s", err)
}
if n != int64(len(s)) {
t.Fatalf("unexpected number of bytes read; got %d; want %d", n, len(s))
}
if string(bb.B) != s {
t.Fatalf("unexpected value read; got %q; want %q", bb.B, s)
}
})
t.Run("big_number_of_bytes", func(t *testing.T) {
t.Parallel()
bb := bbPool.Get()
defer bbPool.Put(bb)
b := make([]byte, 1024*1024+234)
for i := range b {
b[i] = byte(i)
}
src := bytes.NewBuffer(b)
n, err := bb.ReadFrom(src)
if err != nil {
t.Fatalf("cannot read big value: %s", err)
}
if n != int64(len(b)) {
t.Fatalf("unexpected number of bytes read; got %d; want %d", n, len(b))
}
if string(bb.B) != string(b) {
t.Fatalf("unexpected value read; got %q; want %q", bb.B, b)
}
})
t.Run("non_empty_bb", func(t *testing.T) {
t.Parallel()
bb := bbPool.Get()
defer bbPool.Put(bb)
prefix := []byte("prefix")
bb.B = append(bb.B[:0], prefix...)
s := "aosdfdsafdjsf"
src := bytes.NewBufferString(s)
n, err := bb.ReadFrom(src)
if err != nil {
t.Fatalf("cannot read to non-empty bb: %s", err)
}
if n != int64(len(s)) {
t.Fatalf("unexpected number of bytes read; got %d; want %d", n, len(s))
}
if len(bb.B) != len(prefix)+len(s) {
t.Fatalf("unexpected bb.B len; got %d; want %d", len(bb.B), len(prefix)+len(s))
}
if string(bb.B[:len(prefix)]) != string(prefix) {
t.Fatalf("unexpected prefix; got %q; want %q", bb.B[:len(prefix)], prefix)
}
if string(bb.B[len(prefix):]) != s {
t.Fatalf("unexpected data read; got %q; want %q", bb.B[len(prefix):], s)
}
})
}
func TestByteBufferRead(t *testing.T) {
var bb ByteBuffer
n, err := fmt.Fprintf(&bb, "foo, %s, baz", "bar")
if err != nil {
t.Fatalf("unexpected error after fmt.Fprintf: %s", err)
}
if n != len(bb.B) {
t.Fatalf("unexpected len(bb.B); got %d; want %d", len(bb.B), n)
}
if string(bb.B) != "foo, bar, baz" {
t.Fatalf("unexpected bb.B; got %q; want %q", bb.B, "foo, bar, baz")
}
r := bb.NewReader().(*reader)
if r.readOffset != 0 {
t.Fatalf("unexpected r.readOffset; got %d; want %q", r.readOffset, 0)
}
rCopy := bb.NewReader().(*reader)
var bb1 ByteBuffer
n1, err := io.Copy(&bb1, r)
if err != nil {
t.Fatalf("unexpected error after io.Copy: %s", err)
}
if int64(r.readOffset) != n1 {
t.Fatalf("unexpected r.readOffset after io.Copy; got %d; want %d", r.readOffset, n1)
}
if n1 != int64(n) {
t.Fatalf("unexpected number of bytes copied; got %d; want %d", n1, n)
}
if string(bb1.B) != "foo, bar, baz" {
t.Fatalf("unexpected bb1.B; got %q; want %q", bb1.B, "foo, bar, baz")
}
// Make read returns io.EOF
buf := make([]byte, n)
n2, err := r.Read(buf)
if err != io.EOF {
t.Fatalf("unexpected error returned: got %q; want %q", err, io.EOF)
}
if n2 != 0 {
t.Fatalf("unexpected n1 returned; got %d; want %d", n2, 0)
}
// Read data from rCopy
if rCopy.readOffset != 0 {
t.Fatalf("unexpected rCopy.readOffset; got %d; want %d", rCopy.readOffset, 0)
}
buf = make([]byte, n+13)
n2, err = rCopy.Read(buf)
if err != io.EOF {
t.Fatalf("unexpected error when reading from rCopy: got %q; want %q", err, io.EOF)
}
if n2 != n {
t.Fatalf("unexpected number of bytes read from rCopy; got %d; want %d", n2, n)
}
if string(buf[:n2]) != "foo, bar, baz" {
t.Fatalf("unexpected data read: got %q; want %q", buf[:n2], "foo, bar, baz")
}
if rCopy.readOffset != n2 {
t.Fatalf("unexpected rCopy.readOffset; got %d; want %d", rCopy.readOffset, n2)
}
}
func TestByteBufferMustReadAt(t *testing.T) {
testStr := "foobar baz"
var bb ByteBuffer
bb.B = append(bb.B, testStr...)
// Try reading at negative offset
p := make([]byte, 1)
func() {
defer func() {
if r := recover(); r == nil {
t.Fatalf("expecting non-nil error when reading at negative offset")
}
}()
bb.MustReadAt(p, -1)
}()
// Try reading past the end of buffer
func() {
defer func() {
if r := recover(); r == nil {
t.Fatalf("expecting non-nil error when reading past the end of buffer")
}
}()
bb.MustReadAt(p, int64(len(testStr))+1)
}()
// Try reading the first byte
n := len(p)
bb.MustReadAt(p, 0)
if string(p) != testStr[:n] {
t.Fatalf("unexpected value read: %q; want %q", p, testStr[:n])
}
// Try reading the last byte
bb.MustReadAt(p, int64(len(testStr))-1)
if string(p) != testStr[len(testStr)-1:] {
t.Fatalf("unexpected value read: %q; want %q", p, testStr[len(testStr)-1:])
}
// Try reading non-full p
func() {
defer func() {
if r := recover(); r == nil {
t.Fatalf("expecting non-nil error when reading non-full p")
}
}()
p := make([]byte, 10)
bb.MustReadAt(p, int64(len(testStr))-3)
}()
// Try reading multiple bytes from the middle
p = make([]byte, 3)
bb.MustReadAt(p, 2)
if string(p) != testStr[2:2+len(p)] {
t.Fatalf("unexpected value read: %q; want %q", p, testStr[2:2+len(p)])
}
}
func TestByteBufferMustReadAtParallel(t *testing.T) {
ch := make(chan error, 10)
var bb ByteBuffer
bb.B = []byte("foo bar baz adsf adsf dsakjlkjlkj2l34324")
for i := 0; i < cap(ch); i++ {
go func() {
p := make([]byte, 3)
for i := 0; i < len(bb.B)-len(p); i++ {
bb.MustReadAt(p, int64(i))
}
ch <- nil
}()
}
for i := 0; i < cap(ch); i++ {
select {
case err := <-ch:
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
case <-time.After(3 * time.Second):
t.Fatalf("timeout")
}
}
}