Files
sub2api/backend/internal/pkg/httputil/body_memory_test.go
T

68 lines
2.3 KiB
Go

package httputil
import (
"bytes"
"errors"
"fmt"
"io"
"net/http"
"testing"
"testing/iotest"
)
type bodyReaderOnly struct{ io.Reader }
func TestReadRequestBodyChunksPreservesContent(t *testing.T) {
for _, size := range []int{0, 1, 512, 513, 1 << 20, (2 << 20) + 17} {
body := bytes.Repeat([]byte{'x'}, size)
for _, declared := range []int64{-1, 0, 1, int64(size), 1 << 40} {
t.Run(fmt.Sprintf("size_%d_length_%d", size, declared), func(t *testing.T) {
req := &http.Request{Body: io.NopCloser(bodyReaderOnly{bytes.NewReader(body)}), ContentLength: declared, Header: make(http.Header)}
got, err := ReadRequestBodyWithPrealloc(req)
if err != nil || !bytes.Equal(got, body) {
t.Fatalf("body was lost or changed: %v", err)
}
})
}
}
}
func TestReadRequestBodyChunksPreservesReadErrors(t *testing.T) {
for _, readErr := range []error{io.ErrUnexpectedEOF, errors.New("connection reset")} {
reader := io.MultiReader(bytes.NewReader([]byte("partial")), iotest.ErrReader(readErr))
req := &http.Request{Body: io.NopCloser(reader), ContentLength: 100, Header: make(http.Header)}
got, err := ReadRequestBodyWithPrealloc(req)
if !errors.Is(err, readErr) || got != nil {
t.Fatalf("truncated body accepted: body=%q err=%v", got, err)
}
}
}
func TestReadRequestBodyChunksPreservesMaxBytesReader(t *testing.T) {
body := bytes.Repeat([]byte{'x'}, (2<<20)+1)
req := &http.Request{Body: http.MaxBytesReader(nil, io.NopCloser(bytes.NewReader(body)), 2<<20), ContentLength: int64(len(body)), Header: make(http.Header)}
got, err := ReadRequestBodyWithPrealloc(req)
var limitErr *http.MaxBytesError
if !errors.As(err, &limitErr) || limitErr.Limit != 2<<20 || got != nil {
t.Fatalf("body limit changed: len=%d err=%v", len(got), err)
}
}
func BenchmarkReadLargeBody(b *testing.B) {
for _, size := range []int{512 << 10, 69 << 20} {
b.Run(fmt.Sprintf("bytes_%d", size), func(b *testing.B) {
body := bytes.Repeat([]byte{'x'}, size)
b.ReportAllocs()
b.SetBytes(int64(size))
b.ResetTimer()
for i := 0; i < b.N; i++ {
req := &http.Request{Body: io.NopCloser(bodyReaderOnly{bytes.NewReader(body)}), ContentLength: int64(size), Header: make(http.Header)}
got, err := ReadRequestBodyWithPrealloc(req)
if err != nil || !bytes.Equal(got, body) {
b.Fatalf("body changed: %v", err)
}
}
})
}
}