1
0
buffer/content_test.go

342 lines
6.8 KiB
Go

package buffer
import (
"testing"
"io"
"errors"
)
type testPool struct {
size int
failAfter []int
count int
}
var (
errTest = errors.New("test error")
errTest2 = errors.New("test error 2")
)
func (p *testPool) Get() ([]byte, error) {
defer func() {
p.count++
}()
if len(p.failAfter) > 0 && p.count == p.failAfter[0] {
p.failAfter = p.failAfter[1:]
return nil, errTest
}
return make([]byte, p.size), nil
}
func (p *testPool) Put([]byte) {}
func TestContent(t *testing.T) {
t.Run("eof", func(t *testing.T) {
c := ContentFunc(func(w io.Writer) (int64, error) {
var n int64
for i := 0; i < 3; i++ {
ni, err := w.Write([]byte("123456789")[i * 3:i * 3 + 3])
n += int64(ni)
if err != nil {
return n, err
}
}
return n, nil
})
p := &testPool{size: 2}
o := Options{Pool: p}
r := BufferedContent(c, o)
b := make([]byte, 3)
for i := 0; i < 3; i++ {
n, err := r.Read(b)
if n != 3 || err != nil {
t.Fatal(n, err)
}
if string(b) != "123456789"[i * 3:i * 3 + 3] {
t.Fatal(string(b))
}
}
n, err := r.Read(b)
if n != 0 || !errors.Is(err, io.EOF) {
t.Fatal(n, err)
}
})
t.Run("eof right away", func(t *testing.T) {
c := ContentFunc(func(w io.Writer) (int64, error) {
return 0, nil
})
p := &testPool{size: 2}
o := Options{Pool: p}
r := BufferedContent(c, o)
b := make([]byte, 3)
n, err := r.Read(b)
if n != 0 || !errors.Is(err, io.EOF) {
t.Fatal(n, err)
}
})
t.Run("writer error", func(t *testing.T) {
c := ContentFunc(func(w io.Writer) (int64, error) {
var n int64
for i := 0; i < 3; i++ {
ni, err := w.Write([]byte("123456789")[i * 3:i * 3 + 3])
n += int64(ni)
if err != nil {
return n, err
}
}
return n, errTest
})
p := &testPool{size: 2}
o := Options{Pool: p}
r := BufferedContent(c, o)
b := make([]byte, 3)
for i := 0; i < 3; i++ {
n, err := r.Read(b)
if n != 3 || err != nil {
t.Fatal(n, err)
}
if string(b) != "123456789"[i * 3:i * 3 + 3] {
t.Fatal(string(b))
}
}
n, err := r.Read(b)
if n != 0 || !errors.Is(err, errTest) {
t.Fatal(n, err)
}
})
t.Run("writer error right away", func(t *testing.T) {
c := ContentFunc(func(w io.Writer) (int64, error) {
return 0, errTest
})
p := &testPool{size: 2}
o := Options{Pool: p}
r := BufferedContent(c, o)
b := make([]byte, 3)
n, err := r.Read(b)
if n != 0 || !errors.Is(err, errTest) {
t.Fatal(n, err)
}
})
t.Run("abort", func(t *testing.T) {
c := ContentFunc(func(w io.Writer) (int64, error) {
var n int64
for i := 0; i < 3; i++ {
ni, err := w.Write([]byte("123456789")[i * 3:i * 3 + 3])
n += int64(ni)
if err != nil {
return n, err
}
}
return n, nil
})
p := &testPool{
size: 2,
failAfter: []int{1},
}
o := Options{Pool: p}
r := BufferedContent(c, o)
b, ok, err := r.ReadBytes([]byte("67"), 12)
if string(b) != "12" /* segment size og 2 by the pool */ || ok || err != nil {
t.Fatal(string(b), ok, err)
}
b, ok, err = r.ReadBytes([]byte("67"), 12)
if len(b) != 0 || ok || !errors.Is(err, errTest) {
t.Fatal(string(b), ok, err)
}
})
t.Run("abort right away", func(t *testing.T) {
c := ContentFunc(func(w io.Writer) (int64, error) {
var n int64
for i := 0; i < 3; i++ {
ni, err := w.Write([]byte("123456789")[i * 3:i * 3 + 3])
n += int64(ni)
if err != nil {
return n, err
}
}
return n, nil
})
p := &testPool{
size: 2,
failAfter: []int{0},
}
o := Options{Pool: p}
r := BufferedContent(c, o)
b, ok, err := r.ReadBytes([]byte("67"), 12)
if len(b) != 0 || ok || !errors.Is(err, errTest) {
t.Fatal(string(b), ok, err)
}
})
t.Run("close when implementation ignores writer errors", func(t *testing.T) {
c := ContentFunc(func(w io.Writer) (int64, error) {
w.Write([]byte("123"))
w.Write([]byte("456"))
w.Write([]byte("123"))
return 0, nil
})
p := &testPool{
size: 2,
failAfter: []int{1},
}
o := Options{Pool: p}
r := BufferedContent(c, o)
b, ok, err := r.ReadBytes([]byte("67"), 12)
if string(b) != "12" /* segment size og 2 by the pool */ || ok || err != nil {
t.Fatal(string(b), ok, err)
}
b, ok, err = r.ReadBytes([]byte("67"), 12)
if len(b) != 0 || ok || !errors.Is(err, errTest) {
t.Fatal(string(b), ok, err)
}
})
t.Run("zero write", func(t *testing.T) {
c := ContentFunc(func(w io.Writer) (int64, error) {
w.Write([]byte("123"))
w.Write(nil)
w.Write([]byte("456"))
w.Write([]byte("789"))
return 0, nil
})
p := &testPool{size: 2}
o := Options{Pool: p}
r := BufferedContent(c, o)
b := make([]byte, 3)
for i := 0; i < 3; i++ {
n, err := r.Read(b)
if n != 3 || err != nil {
t.Fatal(n, err)
}
if string(b) != "123456789"[i * 3:i * 3 + 3] {
t.Fatal(string(b))
}
}
n, err := r.Read(b)
if n != 0 || !errors.Is(err, io.EOF) {
t.Fatal(n, err)
}
})
t.Run("zero write right away", func(t *testing.T) {
c := ContentFunc(func(w io.Writer) (int64, error) {
w.Write(nil)
w.Write([]byte("123"))
w.Write([]byte("456"))
w.Write([]byte("789"))
return 0, nil
})
p := &testPool{size: 2}
o := Options{Pool: p}
r := BufferedContent(c, o)
b := make([]byte, 3)
for i := 0; i < 3; i++ {
n, err := r.Read(b)
if n != 3 || err != nil {
t.Fatal(n, err)
}
if string(b) != "123456789"[i * 3:i * 3 + 3] {
t.Fatal(string(b))
}
}
n, err := r.Read(b)
if n != 0 || !errors.Is(err, io.EOF) {
t.Fatal(n, err)
}
})
t.Run("custom error", func(t *testing.T) {
c := ContentFunc(func(w io.Writer) (int64, error) {
var n int64
for i := 0; i < 3; i++ {
ni, err := w.Write([]byte("123456789")[i * 3:i * 3 + 3])
n += int64(ni)
if err != nil {
return n, err
}
}
return n, errTest
})
p := &testPool{size: 3}
o := Options{Pool: p}
r := BufferedContent(c, o)
b := make([]byte, 3)
for i := 0; i < 3; i++ {
n, err := r.Read(b)
if n != 3 || err != nil {
t.Fatal(n, err)
}
if string(b) != "123456789"[i * 3:i * 3 + 3] {
t.Fatal(string(b))
}
}
n, err := r.Read(b)
if n != 0 || !errors.Is(err, errTest) {
t.Fatal(n, err)
}
})
t.Run("custom error with pool error", func(t *testing.T) {
c := ContentFunc(func(w io.Writer) (int64, error) {
w.Write([]byte("123"))
w.Write([]byte("456"))
w.Write([]byte("123"))
return 0, errTest2
})
p := &testPool{
size: 2,
failAfter: []int{1},
}
o := Options{Pool: p}
r := BufferedContent(c, o)
b, ok, err := r.ReadBytes([]byte("67"), 12)
if string(b) != "12" /* segment size og 2 by the pool */ || ok || err != nil {
t.Fatal(string(b), ok, err)
}
b, ok, err = r.ReadBytes([]byte("67"), 12)
if len(b) != 0 || ok || !errors.Is(err, errTest) || !errors.Is(err, errTest2) {
t.Fatal(string(b), ok, err)
}
})
}