1
0
Fork 0
golang-github-djherbis-buffer/buffer_test.go
Daniel Baumann 82a6c39bcf
Adding upstream version 1.2.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-05-18 16:42:16 +02:00

915 lines
20 KiB
Go

package buffer
import (
"bytes"
"crypto/rand"
"encoding/gob"
"errors"
"io"
"io/ioutil"
"math"
"os"
"testing"
)
func BenchmarkMemory(b *testing.B) {
buf := New(32 * 1024)
for i := 0; i < b.N; i++ {
io.Copy(buf, io.LimitReader(rand.Reader, 32*1024))
io.Copy(ioutil.Discard, buf)
}
}
func TestPool(t *testing.T) {
pool := NewPool(func() Buffer { return New(10) })
buf, err := pool.Get()
if err != nil {
t.Error(err)
}
buf.Write([]byte("hello world"))
pool.Put(buf)
}
func TestMemPool(t *testing.T) {
p := NewMemPool(10)
poolTest(p, t)
b := bytes.NewBuffer(nil)
enc := gob.NewEncoder(b)
if err := enc.Encode(&p); err != nil {
t.Error(err)
}
var pool Pool
dec := gob.NewDecoder(b)
if err := dec.Decode(&pool); err != nil {
t.Error(err)
}
poolTest(pool, t)
}
func poolTest(pool Pool, t *testing.T) {
buf, err := pool.Get()
if err != nil {
t.Error(err)
}
if n, err := buf.Write([]byte("hello world")); n != 10 {
t.Errorf("wrote incorrect amount")
} else if err == nil {
t.Errorf("should have been a shortwrite error here")
}
pool.Put(buf)
if buf.Len() > 0 {
t.Errorf("should have emptied the buffer")
}
}
func TestFilePool(t *testing.T) {
pool := NewFilePool(1024, "::~_bad_dir_~::")
buf := NewPartition(pool)
_, err := buf.Write([]byte("hello"))
if err == nil {
t.Error("an error was expected here")
}
}
func TestFilePool2(t *testing.T) {
pool := NewFilePool(1024, "::~_bad_dir_~::")
buf := NewPartition(pool, New(0))
_, err := buf.Write([]byte("hello"))
if err == nil {
t.Error("an error was expected here")
}
}
func TestOverflow(t *testing.T) {
buf := NewMulti(New(5), Discard)
buf.Write([]byte("Hello World"))
b := bytes.NewBuffer(nil)
enc := gob.NewEncoder(b)
if err := enc.Encode(&buf); err != nil {
t.Error(err)
}
var buf2 Buffer
dec := gob.NewDecoder(b)
if err := dec.Decode(&buf2); err != nil {
t.Error(err)
}
buf = buf2
data, err := ioutil.ReadAll(buf)
if err != nil {
t.Error(err.Error())
}
if !bytes.Equal(data, []byte("Hello")) {
t.Errorf("Expected Hello got %s", string(data))
}
}
func TestWriteAt(t *testing.T) {
var b BufferAt
b = New(5)
BufferAtTester(t, b)
file, err := ioutil.TempFile("", "buffer")
if err != nil {
t.Error(err.Error())
}
defer os.Remove(file.Name())
defer file.Close()
b = NewFile(5, file)
BufferAtTester(t, b)
b = NewMultiAt(New(1), NewFile(4, file))
BufferAtTester(t, b)
b = NewMultiAt(New(2), NewFile(3, file))
BufferAtTester(t, b)
b = NewMultiAt(New(3), NewFile(2, file))
BufferAtTester(t, b)
b = NewMultiAt(New(4), NewFile(1, file))
BufferAtTester(t, b)
b = NewSwapAt(New(1), New(5))
BufferAtTester(t, b)
b = NewSwapAt(New(2), New(5))
BufferAtTester(t, b)
b = NewSwapAt(New(3), New(5))
BufferAtTester(t, b)
b = NewSwapAt(New(4), New(5))
BufferAtTester(t, b)
b = NewPartitionAt(NewMemPoolAt(3))
BufferAtTester(t, b)
b = NewPartitionAt(NewFilePoolAt(3, os.TempDir()))
BufferAtTester(t, b)
b = NewPartitionAt(NewMemPoolAt(1))
BufferAtTester(t, b)
b = NewPartitionAt(NewFilePoolAt(1, os.TempDir()))
BufferAtTester(t, b)
b = NewPartitionAt(NewMemPoolAt(5))
BufferAtTester(t, b)
b = NewPartitionAt(NewFilePoolAt(5, os.TempDir()))
BufferAtTester(t, b)
}
func BufferAtTester(t *testing.T, b BufferAt) {
t.Helper()
b.WriteAt([]byte("abc"), 0)
Compare(t, b, "abc")
b.WriteAt([]byte("abc"), 1)
Compare(t, b, "aabc")
b.WriteAt([]byte("abc"), 2)
Compare(t, b, "aaabc")
b.WriteAt([]byte("def"), 3)
switch {
case b.Cap() > 5:
Compare(t, b, "aaadef")
default:
Compare(t, b, "aaade")
}
b.Read(make([]byte, 2))
switch {
case b.Cap() > 5:
Compare(t, b, "adef")
default:
Compare(t, b, "ade")
}
b.WriteAt([]byte("ab"), 3)
Compare(t, b, "adeab")
b.Reset()
}
func Compare(t *testing.T, b BufferAt, s string) {
t.Helper()
data := make([]byte, b.Len())
n, _ := b.ReadAt(data, 0)
if string(data[:n]) != s {
t.Errorf("Mismatch: got %q want %q", string(data[:n]), s)
}
off := int64(len(s) / 2)
n, _ = b.ReadAt(data, off)
if string(data[:n]) != s[off:] {
t.Errorf("Mismatch: got %q want %q", string(data[:n]), s[off:])
}
}
func TestRingComplex(t *testing.T) {
ringSize := 10
data := []byte("hello!")
ring := NewRing(New(int64(ringSize)))
buf := make([]byte, ringSize)
for i := 0; i < 10; i++ {
ring.Write(data)
n, err := ring.Read(buf)
if err != nil {
t.Errorf("unexpected error %s", err)
} else if !bytes.Equal(buf[:n], data) {
t.Errorf("expected %s got %s", data, buf[:n])
}
}
// we are going to overflow the buffer here, we expect the last 10 bytes to remain
repData := bytes.Repeat(data, 3)
leftover := repData[len(repData)-ringSize:]
for i := 0; i < 10; i++ {
ring.Write(repData)
n, err := ring.Read(buf)
if err != nil {
t.Errorf("unexpected error %s", err)
} else if !bytes.Equal(buf[:n], leftover) {
t.Errorf("expected %s got %s", leftover, buf[:n])
}
}
}
func TestRing(t *testing.T) {
ring := NewRing(New(3))
if ring.Len() != 0 {
t.Errorf("Ring non-empty start!")
}
if ring.Cap() != math.MaxInt64 {
t.Errorf("Ring has < max capacity")
}
ring.Write([]byte("abc"))
if ring.Len() != 3 {
t.Errorf("expected ring len == 3")
}
ring.Write([]byte("de"))
if ring.Len() != 3 {
t.Errorf("expected ring len == 3")
}
data := make([]byte, 12)
if n, err := ring.Read(data); err != nil {
t.Error(err.Error())
} else {
if !bytes.Equal(data[:n], []byte("cde")) {
t.Errorf("expected cde, got %s", data[:n])
}
}
if ring.Len() != 0 {
t.Errorf("ring should now be empty")
}
ring.Write([]byte("hello"))
ring.Reset()
if ring.Len() != 0 {
t.Errorf("ring should still be empty")
}
}
func TestGob(t *testing.T) {
str := "HelloWorld"
buf := NewUnboundedBuffer(2, 2)
buf.Write([]byte(str))
b := bytes.NewBuffer(nil)
if err := gob.NewEncoder(b).Encode(&buf); err != nil {
t.Error(err.Error())
return
}
var buffer Buffer
if err := gob.NewDecoder(b).Decode(&buffer); err != nil {
t.Error(err.Error())
return
}
data := make([]byte, len(str))
if _, err := buffer.Read(data); err != nil && err != io.EOF {
t.Error(err.Error())
}
if !bytes.Equal(data, []byte(str)) {
t.Error("Gob Recover Failed... " + string(data))
}
buffer.Reset()
}
func TestDiscard(t *testing.T) {
buf := Discard
if buf.Cap() != math.MaxInt64 {
t.Errorf("cap isn't infinite")
}
buf.Write([]byte("hello"))
if buf.Len() != 0 {
t.Errorf("buf should always be empty")
}
}
func TestList(t *testing.T) {
mem := New(10)
ory := New(10)
mem.Write([]byte("Hello"))
ory.Write([]byte("world"))
buf := List([]Buffer{mem, ory, Discard})
if buf.Len() != 10 {
t.Errorf("incorrect sum of lengths")
}
if buf.Cap() != math.MaxInt64 {
t.Errorf("incorrect sum of caps")
}
buf.Reset()
if buf.Len() != 0 {
t.Errorf("buffer should be empty")
}
}
func TestList2(t *testing.T) {
mem := New(10)
ory := New(10)
mem.Write([]byte("Hello"))
ory.Write([]byte("world"))
buf := List([]Buffer{mem, ory})
if buf.Len() != 10 {
t.Errorf("incorrect sum of lengths")
}
if buf.Cap() != 20 {
t.Errorf("incorrect sum of caps")
}
buf.Reset()
if buf.Len() != 0 {
t.Errorf("buffer should be empty")
}
}
func TestSpill(t *testing.T) {
buf := NewSpill(New(5), Discard)
buf.Write([]byte("Hello World"))
data := make([]byte, 12)
n, _ := buf.Read(data)
if !bytes.Equal(data[:n], []byte("Hello")) {
t.Error("ReadAt Failed. " + string(data[:n]))
}
}
func TestSpill2(t *testing.T) {
buf := NewSpill(New(5), nil)
if buf.Cap() != math.MaxInt64 {
t.Errorf("cap isn't infinite")
}
towrite := []byte("Hello World")
m, _ := buf.Write(towrite)
if m != len(towrite) {
t.Errorf("failed to write all data: %d != %d", m, len(towrite))
}
data := make([]byte, 12)
n, _ := buf.Read(data)
if !bytes.Equal(data[:n], []byte("Hello")) {
t.Error("Read Failed. " + string(data[:n]))
}
}
func TestNoSpill(t *testing.T) {
buf := NewSpill(New(1024), nil)
buf.Write([]byte("Hello World"))
data := make([]byte, 12)
n, _ := buf.Read(data)
if !bytes.Equal(data[:n], []byte("Hello World")) {
t.Error("Read Failed. " + string(data[:n]))
}
}
func TestFile(t *testing.T) {
file, err := ioutil.TempFile("", "buffer")
if err != nil {
t.Error(err.Error())
}
defer os.Remove(file.Name())
defer file.Close()
buf := NewFile(1024, file)
checkCap(t, buf, 1024)
runPerfectSeries(t, buf)
buf.Reset()
buf = NewFile(3, file)
buf.Write([]byte("abc"))
buf.Read(make([]byte, 1))
buf.Write([]byte("a"))
d, _ := ioutil.ReadAll(buf)
if !bytes.Equal(d, []byte("bca")) {
t.Error("back and forth error!")
}
}
func TestMem(t *testing.T) {
buf := New(1024)
checkCap(t, buf, 1024)
runPerfectSeries(t, buf)
buf.Reset()
if n, err := buf.WriteAt([]byte("hello"), 1); err == nil || n != 0 {
t.Errorf("write should have failed")
}
}
func TestFilePartition(t *testing.T) {
buf := NewPartition(NewFilePool(1024, ""))
checkCap(t, buf, math.MaxInt64)
runPerfectSeries(t, buf)
buf.Reset()
}
func TestSmallMulti(t *testing.T) {
if empty := NewMulti(); empty != nil {
t.Errorf("the empty buffer should return nil")
}
one := NewMulti(New(10))
if one.Len() != 0 {
t.Errorf("singleton multi doesn't match inner buffer len")
}
if one.Cap() != 10 {
t.Errorf("singleton multi doesn't match inner buffer cap")
}
}
func TestMulti(t *testing.T) {
file, err := ioutil.TempFile("", "buffer")
if err != nil {
t.Error(err.Error())
}
defer os.Remove(file.Name())
defer file.Close()
buf := NewMulti(New(5), New(5), NewFile(500, file), NewPartition(NewFilePool(1024, "")))
checkCap(t, buf, math.MaxInt64)
runPerfectSeries(t, buf)
isPerfectMatch(t, buf, 1024*1024)
buf.Reset()
}
func TestMulti2(t *testing.T) {
file, err := ioutil.TempFile("", "buffer")
if err != nil {
t.Error(err.Error())
}
defer os.Remove(file.Name())
defer file.Close()
buf := NewMulti(New(5), New(5), NewFile(500, file))
checkCap(t, buf, 510)
runPerfectSeries(t, buf)
isPerfectMatch(t, buf, 1024*1024)
buf.Reset()
}
func runPerfectSeries(t *testing.T, buf Buffer) {
checkEmpty(t, buf)
simple(t, buf)
max := int64(1024)
isPerfectMatch(t, buf, 0)
for i := int64(1); i < max; i *= 2 {
isPerfectMatch(t, buf, i)
}
isPerfectMatch(t, buf, max)
}
func simple(t *testing.T, buf Buffer) {
buf.Write([]byte("hello world"))
data, err := ioutil.ReadAll(buf)
if err != nil {
t.Error(err.Error())
}
if !bytes.Equal([]byte("hello world"), data) {
t.Error("Hello world failed.")
}
buf.Write([]byte("hello world"))
data = make([]byte, 3)
buf.Read(data)
buf.Write([]byte(" yolo"))
data, err = ioutil.ReadAll(buf)
if err != nil {
t.Error(err.Error())
}
if !bytes.Equal([]byte("lo world yolo"), data) {
t.Error("Buffer crossing error :(", string(data))
}
}
func buildOutputs(t *testing.T, buf Buffer, size int64) (wrote []byte, read []byte) {
r := io.LimitReader(rand.Reader, size)
tee := io.TeeReader(r, buf)
wrote, _ = ioutil.ReadAll(tee)
read, _ = ioutil.ReadAll(buf)
return wrote, read
}
func isPerfectMatch(t *testing.T, buf Buffer, size int64) {
wrote, read := buildOutputs(t, buf, size)
if !bytes.Equal(wrote, read) {
t.Error("Buffer should have matched")
}
}
func checkEmpty(t *testing.T, buf Buffer) {
if !Empty(buf) {
t.Error("Buffer should start empty!")
}
}
func checkCap(t *testing.T, buf Buffer, correctCap int64) {
if buf.Cap() != correctCap {
t.Error("Buffer cap is incorrect", buf.Cap(), correctCap)
}
}
type bigBuffer struct{}
func (b bigBuffer) Len() int64 { return math.MaxInt64 }
func (b bigBuffer) Cap() int64 { return math.MaxInt64 }
func (b bigBuffer) Read(p []byte) (int, error) { return 0, io.ErrUnexpectedEOF }
func (b bigBuffer) Write(p []byte) (int, error) { return 0, io.ErrShortBuffer }
func (b bigBuffer) Reset() {}
func TestBigList(t *testing.T) {
l := List([]Buffer{bigBuffer{}, bigBuffer{}})
if l.Len() != math.MaxInt64 {
t.Errorf("expected list to be max-size: %d", l.Len())
}
}
func TestBigMulti(t *testing.T) {
single := NewMulti(bigBuffer{})
if single.Len() != math.MaxInt64 {
t.Errorf("expected len to be max-size: %d", single.Len())
}
if single.Cap() != math.MaxInt64 {
t.Errorf("expected cap to be max-size: %d", single.Cap())
}
buf := NewMulti(bigBuffer{}, bigBuffer{})
if buf.Len() != math.MaxInt64 {
t.Errorf("expected len to be max-size: %d", buf.Len())
}
if buf.Cap() != math.MaxInt64 {
t.Errorf("expected cap to be max-size: %d", buf.Cap())
}
// test defrag failure
NewMulti(badBuffer{}, badBuffer{})
}
type badBuffer struct{}
func (b badBuffer) Len() int64 { return 1024 }
func (b badBuffer) Cap() int64 { return 10 * 1024 }
func (b badBuffer) Read(p []byte) (int, error) { return 0, io.ErrUnexpectedEOF }
func (b badBuffer) Write(p []byte) (int, error) { return 0, io.ErrShortBuffer }
func (b badBuffer) Reset() {}
func (b badBuffer) MarshalBinary() ([]byte, error) {
return nil, errors.New("no data")
}
func TestBadPartition(t *testing.T) {
p := NewPool(func() Buffer { return badBuffer{} })
buf := NewPartition(p)
_, err := buf.Write([]byte("bad write"))
if err != io.ErrShortBuffer {
t.Errorf("wrong read error was returned! %v", err)
}
b := make([]byte, 1024)
_, err = buf.Read(b)
if err != io.ErrUnexpectedEOF {
t.Errorf("wrong write error was returned! %v", err)
}
}
type fakeFile struct {
name string
}
func (f *fakeFile) Name() string {
return f.name
}
func (f *fakeFile) Stat() (fi os.FileInfo, err error) {
return nil, nil
}
func (f *fakeFile) ReadAt(p []byte, off int64) (int, error) {
return 0, io.EOF
}
func (f *fakeFile) WriteAt(p []byte, off int64) (int, error) {
return 0, io.ErrShortWrite
}
func (f *fakeFile) Close() error { return nil }
func TestBadGobFile(t *testing.T) {
b := NewFile(10, &fakeFile{name: "test"})
b2 := NewFile(10, &fakeFile{name: "test2"})
b3 := NewMulti(b, b2)
buf := bytes.NewBuffer(nil)
enc := gob.NewEncoder(buf)
if err := enc.Encode(&b3); err != nil {
t.Error(err)
}
var buffer Buffer
dec := gob.NewDecoder(buf)
if err := dec.Decode(&buffer); err == nil {
t.Error("expected an error here, file does not exist")
}
}
func TestBadGobFile2(t *testing.T) {
b := New(10)
b2 := NewFile(10, &fakeFile{name: "test2"})
b3 := NewMulti(b, b2)
buf := bytes.NewBuffer(nil)
enc := gob.NewEncoder(buf)
if err := enc.Encode(&b3); err != nil {
t.Error(err)
}
var buffer Buffer
dec := gob.NewDecoder(buf)
if err := dec.Decode(&buffer); err == nil {
t.Error("expected an error here, file does not exist")
}
}
func TestBadMultiGob(t *testing.T) {
var b Buffer = badBuffer{}
var b2 Buffer = badBuffer{}
var b3 Buffer = New(10)
b4 := NewMulti(b, b3)
b5 := NewMulti(b3, b2)
enc := gob.NewEncoder(ioutil.Discard)
if err := enc.Encode(&b4); err == nil {
t.Error("expected an error here, bad buffer can't be gobbed")
}
if err := enc.Encode(&b5); err == nil {
t.Error("expected an error here, bad buffer can't be gobbed")
}
}
func TestSwapAt(t *testing.T) {
buf := NewSwapAt(New(5), New(10))
buf.WriteAt([]byte("hey"), 0)
data := make([]byte, 10)
n, _ := buf.ReadAt(data, 0)
if string(data[:n]) != "hey" {
t.Error("expected hey got", string(data[:n]))
}
buf.WriteAt([]byte("hey"), 3)
n, _ = buf.ReadAt(data, 1)
if string(data[:n]) != "eyhey" {
t.Error("expected eyhey got", string(data[:n]))
}
buf.WriteAt([]byte("hey"), 5)
n, _ = buf.ReadAt(data, 1)
if string(data[:n]) != "eyhehey" {
t.Error("expected eyhehey got", string(data[:n]))
}
}
func TestSwap(t *testing.T) {
defer func() {
recover()
}()
buf := NewSwap(New(5), New(10))
if buf.Len() != 0 {
t.Error("buffer should start empty got", buf.Len())
}
if buf.Cap() != 10 {
t.Error("cap should be second buffer size (10) got", buf.Cap())
}
io.WriteString(buf, "hey")
data, _ := ioutil.ReadAll(buf)
if string(data) != "hey" {
t.Error("expected hey got", string(data))
}
io.WriteString(buf, "hey")
io.WriteString(buf, "hey")
io.WriteString(buf, "hey")
data, _ = ioutil.ReadAll(buf)
if string(data) != "heyheyhey" {
t.Error("expected heyheyhey got", string(data))
}
io.WriteString(buf, "hey")
if buf.Len() != 3 {
t.Error("should have data")
}
buf.Reset()
if buf.Len() != 0 {
t.Error("should be empty")
}
runPerfectSeries(t, NewSwap(New(512), New(1024)))
NewSwap(New(1), New(0))
t.Error("expected panic")
}
func TestPanicReadAt(t *testing.T) {
defer func() {
recover()
}()
buf := toBufferAt(New(5))
buf.ReadAt(nil, 0)
t.Error("expected a panic!")
}
func TestPanicWriteAt(t *testing.T) {
defer func() {
recover()
}()
buf := toBufferAt(New(5))
buf.WriteAt(nil, 0)
t.Error("expected a panic!")
}
type badFile struct{}
func (b badFile) Name() string { return "" }
func (b badFile) Stat() (os.FileInfo, error) { return nil, errors.New("unsupported") }
func (b badFile) ReadAt(p []byte, off int64) (int, error) { return 0, nil }
func (b badFile) WriteAt(p []byte, off int64) (int, error) { return len(p), nil }
func (b badFile) Close() error { return nil }
func TestWrapioBreakout(t *testing.T) {
buf := NewFile(10, badFile{})
io.WriteString(buf, "hello world")
if _, err := ioutil.ReadAll(buf); err != io.ErrNoProgress {
t.Error("expected no progress to be made")
t.FailNow()
}
}
func TestListAt(t *testing.T) {
mem := New(10)
ory := New(10)
mem.Write([]byte("Hello"))
ory.Write([]byte("world"))
buf := ListAt([]BufferAt{mem, ory})
if buf.Len() != 10 {
t.Errorf("incorrect sum of lengths")
}
if buf.Cap() != 20 {
t.Errorf("incorrect sum of caps")
}
buf.Reset()
if buf.Len() != 0 {
t.Errorf("buffer should be empty")
}
}
func TestPoolAt(t *testing.T) {
pool := NewPoolAt(func() BufferAt { return New(10) })
buf, err := pool.Get()
if err != nil {
t.Error(err)
}
buf.Write([]byte("hello world"))
pool.Put(buf)
}
func TestMemPoolAt(t *testing.T) {
p := NewMemPoolAt(10)
poolAtTest(p, t)
b := bytes.NewBuffer(nil)
enc := gob.NewEncoder(b)
if err := enc.Encode(&p); err != nil {
t.Error(err)
}
var pool PoolAt
dec := gob.NewDecoder(b)
if err := dec.Decode(&pool); err != nil {
t.Error(err)
}
poolAtTest(pool, t)
}
func poolAtTest(pool PoolAt, t *testing.T) {
buf, err := pool.Get()
if err != nil {
t.Error(err)
}
if n, err := buf.Write([]byte("hello world")); n != 10 {
t.Errorf("wrote incorrect amount")
} else if err == nil {
t.Errorf("should have been a shortwrite error here")
}
pool.Put(buf)
if buf.Len() > 0 {
t.Errorf("should have emptied the buffer")
}
}
func TestPartitionAt(t *testing.T) {
buf := NewPartitionAt(NewMemPoolAt(5))
buf.Write([]byte("Hello World"))
data := make([]byte, 12)
n, _ := buf.Read(data)
if !bytes.Equal(data[:n], []byte("Hello World")) {
t.Error("Read Failed. " + string(data[:n]))
}
checkCap(t, buf, math.MaxInt64)
runPerfectSeries(t, buf)
}
// TestPartitionAt2 tests ability to read at various offsets from buffer previously written.
func TestPartitionAt2(t *testing.T) {
buf := NewPartitionAt(NewMemPoolAt(5))
buf.Write([]byte("Hello World"))
data := make([]byte, 2)
n, _ := buf.ReadAt(data, 2)
if !bytes.Equal(data[:n], []byte("ll")) {
t.Error("Read Failed. " + string(data[:n]))
}
n, _ = buf.ReadAt(data, 4)
if !bytes.Equal(data[:n], []byte("o ")) {
t.Error("Read Failed. " + string(data[:n]))
}
n, _ = buf.ReadAt(data, 10)
if !bytes.Equal(data[:n], []byte("d")) {
t.Error("Read Failed. " + string(data[:n]))
}
n, _ = buf.ReadAt(data, 100)
if !bytes.Equal(data[:n], []byte{}) {
t.Error("Read Failed. " + string(data[:n]))
}
buf.Reset()
checkCap(t, buf, math.MaxInt64)
runPerfectSeries(t, buf)
}
// TestPartitionAt3 tests ability to overwrite buffer previously written.
func TestPartitionAt3(t *testing.T) {
buf := NewPartitionAt(NewMemPoolAt(5))
buf.Write(make([]byte, 15, 15)) // allocates 3 membuffers
buf.WriteAt([]byte("hey"), 0)
data := make([]byte, 10)
data = data[:3]
buf.ReadAt(data, 0)
if string(data) != "hey" {
t.Error("expected hey got", string(data))
}
buf.WriteAt([]byte("hey"), 3)
data = data[:5]
buf.ReadAt(data, 1)
if string(data) != "eyhey" {
t.Error("expected eyhey got", string(data))
}
buf.WriteAt([]byte("hey"), 5)
data = data[:7]
buf.ReadAt(data, 1)
if string(data) != "eyhehey" {
t.Error("expected eyhehey got", string(data))
}
}