internal/parser/http1/chunked_test.go

package http1

import (
	"bufio"
	"bytes"
	"strings"
	"testing"
)

func TestReadChunked(t *testing.T) {
	cases := []struct {
		name string
		raw  string
		want string
	}{
		{
			name: "two_chunks",
			raw:  "5\r\nhello\r\n6\r\n world\r\n0\r\n\r\n",
			want: "hello world",
		},
		{
			name: "single_big_chunk",
			raw:  "a\r\n0123456789\r\n0\r\n\r\n",
			want: "0123456789",
		},
		{
			name: "with_extension",
			raw:  "5;foo=bar\r\nhello\r\n0\r\n\r\n",
			want: "hello",
		},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			r := bufio.NewReader(strings.NewReader(tc.raw))
			body, _, err := readChunked(r)
			if err != nil {
				t.Fatalf("readChunked: %v", err)
			}
			if string(body) != tc.want {
				t.Errorf("body=%q want %q", body, tc.want)
			}
		})
	}
}

func TestReadChunkedTrailers(t *testing.T) {
	raw := "5\r\nhello\r\n0\r\nX-Check: yes\r\n\r\n"
	_, trailers, err := readChunked(bufio.NewReader(strings.NewReader(raw)))
	if err != nil {
		t.Fatal(err)
	}
	if len(trailers) != 1 || trailers[0][0] != "X-Check" || trailers[0][1] != "yes" {
		t.Fatalf("trailers = %+v", trailers)
	}
}

func TestEncodeChunkedRoundTrip(t *testing.T) {
	payloads := [][]byte{
		[]byte("short"),
		bytes.Repeat([]byte("a"), 8000),
		nil,
	}
	for i, p := range payloads {
		enc := EncodeChunked(p)
		got, _, err := readChunked(bufio.NewReader(bytes.NewReader(enc)))
		if err != nil {
			t.Fatalf("case %d: %v", i, err)
		}
		if !bytes.Equal(got, p) {
			t.Errorf("case %d: roundtrip mismatch", i)
		}
	}
}

func TestChunkTooLarge(t *testing.T) {
	raw := "ffffffff\r\n"
	r := bufio.NewReader(strings.NewReader(raw))
	if _, _, err := readChunked(r); err == nil {
		t.Fatal("expected ErrChunkTooLarge")
	}
}