internal/parser/http1/response_test.go

package http1

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

func TestReadResponse(t *testing.T) {
	cases := []struct {
		name       string
		raw        string
		wantStatus int
		wantBody   string
	}{
		{
			name:       "200_with_body",
			raw:        "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello",
			wantStatus: 200,
			wantBody:   "hello",
		},
		{
			name:       "204_empty",
			raw:        "HTTP/1.1 204 No Content\r\n\r\n",
			wantStatus: 204,
			wantBody:   "",
		},
		{
			name:       "404_notfound",
			raw:        "HTTP/1.1 404 Not Found\r\nContent-Length: 9\r\n\r\nnot found",
			wantStatus: 404,
			wantBody:   "not found",
		},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			r := bufio.NewReader(strings.NewReader(tc.raw))
			got, err := ReadResponse(r)
			if err != nil {
				t.Fatalf("ReadResponse: %v", err)
			}
			if got.Status != tc.wantStatus {
				t.Errorf("status = %d, want %d", got.Status, tc.wantStatus)
			}
			if string(got.Body) != tc.wantBody {
				t.Errorf("body = %q, want %q", got.Body, tc.wantBody)
			}
		})
	}
}

func TestParseStatusLineErrors(t *testing.T) {
	for _, bad := range []string{
		"",
		"HTTP/0.9 200 OK",
		"HTTP/1.1 abc OK",
		"HTTP/1.1 999 Beyond",
		"HTTP/1.1 50 Under",
	} {
		t.Run(bad, func(t *testing.T) {
			if _, err := parseStatusLine(bad); err == nil {
				t.Fatalf("expected error for %q", bad)
			}
		})
	}
}

func TestStatusClass(t *testing.T) {
	tests := map[int]string{
		100: "informational",
		204: "success",
		301: "redirect",
		404: "client-error",
		502: "server-error",
	}
	for code, want := range tests {
		if got := StatusClass(code); got != want {
			t.Errorf("StatusClass(%d)=%q want %q", code, got, want)
		}
	}
}