package buffer_test import ( "bufio" "bytes" "code.squareroundforest.org/arpio/buffer" "errors" "io" "testing" ) func TestLib(t *testing.T) { t.Run("default pool", func(t *testing.T) { t.Run("buffered reader", func(t *testing.T) { g := &gen{max: 1 << 18} r := buffer.BufferedReader(g, buffer.Options{}) b, err := io.ReadAll(r) if err != nil { t.Fatal(err) } if !bytes.Equal(b, generate(1<<18)) { t.Fatal("output does not match", len(b)) } }) t.Run("buffered content", func(t *testing.T) { c := buffer.ContentFunc(func(w io.Writer) (int64, error) { g := &gen{max: 1 << 18} return io.Copy(w, g) }) r := buffer.BufferedContent(c, buffer.Options{}) b, err := io.ReadAll(r) if err != nil { t.Fatal(err) } if !bytes.Equal(b, generate(1<<18)) { t.Fatal("output does not match", len(b)) } }) }) t.Run("zero reader", func(t *testing.T) { t.Run("buffered reader", func(t *testing.T) { r := buffer.BufferedReader(nil, buffer.Options{}) b, err := io.ReadAll(r) if err != nil { t.Fatal(err) } if len(b) != 0 { t.Fatal("output does not match", len(b)) } }) t.Run("buffered content", func(t *testing.T) { r := buffer.BufferedContent(nil, buffer.Options{}) b, err := io.ReadAll(r) if err != nil { t.Fatal(err) } if len(b) != 0 { t.Fatal("output does not match", len(b)) } }) }) t.Run("uninitialized reader", func(t *testing.T) { t.Run("read", func(t *testing.T) { var r buffer.Reader p := make([]byte, 512) n, err := r.Read(p) if !errors.Is(err, io.EOF) { t.Fatal(err) } if n != 0 { t.Fatal(n) } }) t.Run("read bytes", func(t *testing.T) { var r buffer.Reader b, ok, err := r.ReadBytes([]byte("123"), 512) if !errors.Is(err, io.EOF) { t.Fatal(err) } if ok { t.Fatal(ok) } if len(b) != 0 { t.Fatal(len(b)) } }) t.Run("read utf8", func(t *testing.T) { var r buffer.Reader runes, n, err := r.ReadUTF8(512) if !errors.Is(err, io.EOF) { t.Fatal(err) } if n != 0 { t.Fatal(n) } if len(runes) != 0 { t.Fatal(len(runes)) } }) t.Run("peek", func(t *testing.T) { var r buffer.Reader b, err := r.Peek(512) if !errors.Is(err, io.EOF) { t.Fatal(err) } if len(b) != 0 { t.Fatal(len(b)) } }) t.Run("buffered", func(t *testing.T) { var r buffer.Reader b := r.Buffered() if len(b) != 0 { t.Fatal(len(b)) } }) t.Run("write to", func(t *testing.T) { var ( r buffer.Reader b bytes.Buffer ) n, err := r.WriteTo(&b) if err != nil { t.Fatal(err) } if n != 0 { t.Fatal(n) } }) }) } // -- bench type readerOnly struct { in io.Reader } type writerOnly struct { in io.Writer } func (r readerOnly) Read(p []byte) (int, error) { return r.in.Read(p) } func (w writerOnly) Write(p []byte) (int, error) { return w.in.Write(p) } func BenchmarkThroughput(b *testing.B) { p := buffer.DefaultPool(0) dst := bytes.NewBuffer(nil) wo := writerOnly{dst} for i := 0; i < b.N; i++ { src := bytes.NewBuffer(make([]byte, 1<<18)) r := buffer.BufferedReader(src, buffer.Options{Pool: p}) ro := readerOnly{r} dst.Reset() io.Copy(wo, ro) } } func BenchmarkCompare(b *testing.B) { dstBuf := bytes.NewBuffer(nil) dst := writerOnly{dstBuf} for i := 0; i < b.N; i++ { srcBuf := bytes.NewBuffer(make([]byte, 1<<18)) srcReader := bufio.NewReader(srcBuf) src := readerOnly{srcReader} dstBuf.Reset() io.Copy(dst, src) } }