// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Infrastructure for testing ClientConn.RoundTrip.
// Put actual tests in transport_test.go.

package http2_test

import (
	"bytes"
	"context"
	"crypto/tls"
	"fmt"
	"internal/gate"
	"internal/nettest"
	"io"
	"net"
	"net/http"
	. "net/http/internal/http2"
	"os"
	"reflect"
	"sync/atomic"
	"testing"
	"testing/synctest"
	_ "unsafe" // for go:linkname

	"golang.org/x/net/http2/hpack"
)

// TestTestClientConn demonstrates usage of testClientConn.
func TestTestClientConn(t *testing.T) { synctest.Test(t, testTestClientConn) }
func testTestClientConn(t *testing.T) {
	// newTestClientConn creates a *ClientConn and surrounding test infrastructure.
	tc := newTestClientConn(t)

	// tc.greet reads the client's initial SETTINGS and WINDOW_UPDATE frames,
	// and sends a SETTINGS frame to the client.
	//
	// Additional settings may be provided as optional parameters to greet.
	tc.greet()

	// Request bodies must either be constant (bytes.Buffer, strings.Reader)
	// or created with newRequestBody.
	body := tc.newRequestBody()
	body.writeBytes(10)         // 10 arbitrary bytes...
	body.closeWithError(io.EOF) // ...followed by EOF.

	// tc.roundTrip calls RoundTrip, but does not wait for it to return.
	// It returns a testRoundTrip.
	req, _ := http.NewRequest("PUT", "https://dummy.tld/", body)
	rt := tc.roundTrip(req)

	// tc has a number of methods to check for expected frames sent.
	// Here, we look for headers and the request body.
	tc.wantHeaders(wantHeader{
		streamID:  rt.streamID(),
		endStream: false,
		header: http.Header{
			":authority": []string{"dummy.tld"},
			":method":    []string{"PUT"},
			":path":      []string{"/"},
		},
	})
	// Expect 10 bytes of request body in DATA frames.
	tc.wantData(wantData{
		streamID:  rt.streamID(),
		endStream: true,
		size:      10,
		multiple:  true,
	})

	// tc.writeHeaders sends a HEADERS frame back to the client.
	tc.writeHeaders(HeadersFrameParam{
		StreamID:   rt.streamID(),
		EndHeaders: true,
		EndStream:  true,
		BlockFragment: tc.makeHeaderBlockFragment(
			":status", "200",
		),
	})

	// Now that we've received headers, RoundTrip has finished.
	// testRoundTrip has various methods to examine the response,
	// or to fetch the response and/or error returned by RoundTrip
	rt.wantStatus(200)
	rt.wantBody(nil)
}

// A testClientConn allows testing ClientConn.RoundTrip against a fake server.
//
// A test using testClientConn consists of:
//   - actions on the client (calling RoundTrip, making data available to Request.Body);
//   - validation of frames sent by the client to the server; and
//   - providing frames from the server to the client.
//
// testClientConn manages synchronization, so tests can generally be written as
// a linear sequence of actions and validations without additional synchronization.
type testClientConn struct {
	t *testing.T

	tr *Transport
	fr *Framer
	cc *ClientConn
	testConnFramer

	encbuf bytes.Buffer
	enc    *hpack.Encoder

	roundtrips []*testRoundTrip

	netconn *nettest.Conn
}

func newTestClientConnFromClientConn(t *testing.T, tr *Transport, cc *ClientConn) *testClientConn {
	tc := &testClientConn{
		t:  t,
		tr: tr,
		cc: cc,
	}

	// cli is the conn used by the client under test, srv is the side controlled by the test.
	// We replace the conn being used by the client (possibly a *tls.Conn) with a new one,
	// to avoid dealing with encryption in tests.
	cli, srv := nettest.NewConnPair()
	cc.TestSetNetConn(cli)

	srv.SetReadError(os.ErrDeadlineExceeded) // make conn non-blocking
	tc.netconn = srv
	tc.enc = hpack.NewEncoder(&tc.encbuf)
	tc.fr = NewFramer(srv, srv)
	tc.testConnFramer = testConnFramer{
		t:        t,
		fr:       tc.fr,
		dec:      hpack.NewDecoder(InitialHeaderTableSize, nil),
		testconn: srv,
	}
	tc.fr.SetMaxReadFrameSize(10 << 20)
	t.Cleanup(func() {
		tc.closeWrite()
	})

	return tc
}

func (tc *testClientConn) readClientPreface() {
	tc.t.Helper()
	// Read the client's HTTP/2 preface, sent prior to any HTTP/2 frames.
	synctest.Wait()
	buf := make([]byte, len(ClientPreface))
	if _, err := io.ReadFull(tc.netconn, buf); err != nil {
		tc.t.Fatalf("reading preface: %v", err)
	}
	if !bytes.Equal(buf, []byte(ClientPreface)) {
		tc.t.Fatalf("client preface: %q, want %q", buf, ClientPreface)
	}
}

func newTestClientConn(t *testing.T, opts ...any) *testClientConn {
	t.Helper()

	tt := newTestTransport(t, opts...)
	const singleUse = false
	tr := transportFromH1Transport(tt.tr1).(*Transport)
	_, err := tr.TestNewClientConn(nil, singleUse, nil)
	if err != nil {
		t.Fatalf("newClientConn: %v", err)
	}

	return tt.getConn()
}

// isClosed reports whether the peer has closed the connection.
func (tc *testClientConn) isClosed() bool {
	synctest.Wait()
	return tc.netconn.Peer().IsClosed()
}

// closeWrite causes the net.Conn used by the ClientConn to return an error
// from Read calls.
func (tc *testClientConn) closeWrite() {
	tc.netconn.Close()
}

// closeWriteWithError causes the net.Conn used by the ClientConn to return an error
// from Write calls.
func (tc *testClientConn) closeWriteWithError(err error) {
	tc.netconn.Peer().SetWriteError(err)
}

// testRequestBody is a Request.Body for use in tests.
type testRequestBody struct {
	tc   *testClientConn
	gate gate.Gate

	// At most one of buf or bytes can be set at any given time:
	buf   bytes.Buffer // specific bytes to read from the body
	bytes int          // body contains this many arbitrary bytes

	err error // read error (comes after any available bytes)
}

func (tc *testClientConn) newRequestBody() *testRequestBody {
	b := &testRequestBody{
		tc:   tc,
		gate: gate.New(false),
	}
	return b
}

func (b *testRequestBody) unlock() {
	b.gate.Unlock(b.buf.Len() > 0 || b.bytes > 0 || b.err != nil)
}

// Read is called by the ClientConn to read from a request body.
func (b *testRequestBody) Read(p []byte) (n int, _ error) {
	if err := b.gate.WaitAndLock(context.Background()); err != nil {
		return 0, err
	}
	defer b.unlock()
	switch {
	case b.buf.Len() > 0:
		return b.buf.Read(p)
	case b.bytes > 0:
		if len(p) > b.bytes {
			p = p[:b.bytes]
		}
		b.bytes -= len(p)
		for i := range p {
			p[i] = 'A'
		}
		return len(p), nil
	default:
		return 0, b.err
	}
}

// Close is called by the ClientConn when it is done reading from a request body.
func (b *testRequestBody) Close() error {
	return nil
}

// writeBytes adds n arbitrary bytes to the body.
func (b *testRequestBody) writeBytes(n int) {
	defer synctest.Wait()
	b.gate.Lock()
	defer b.unlock()
	b.bytes += n
	b.checkWrite()
	synctest.Wait()
}

// Write adds bytes to the body.
func (b *testRequestBody) Write(p []byte) (int, error) {
	defer synctest.Wait()
	b.gate.Lock()
	defer b.unlock()
	n, err := b.buf.Write(p)
	b.checkWrite()
	return n, err
}

func (b *testRequestBody) checkWrite() {
	if b.bytes > 0 && b.buf.Len() > 0 {
		b.tc.t.Fatalf("can't interleave Write and writeBytes on request body")
	}
	if b.err != nil {
		b.tc.t.Fatalf("can't write to request body after closeWithError")
	}
}

// closeWithError sets an error which will be returned by Read.
func (b *testRequestBody) closeWithError(err error) {
	defer synctest.Wait()
	b.gate.Lock()
	defer b.unlock()
	b.err = err
}

// roundTrip starts a RoundTrip call.
//
// (Note that the RoundTrip won't complete until response headers are received,
// the request times out, or some other terminal condition is reached.)
func (tc *testClientConn) roundTrip(req *http.Request) *testRoundTrip {
	ctx, cancel := context.WithCancel(req.Context())
	req = req.WithContext(ctx)
	rt := &testRoundTrip{
		t:      tc.t,
		donec:  make(chan struct{}),
		cancel: cancel,
	}
	tc.roundtrips = append(tc.roundtrips, rt)
	go func() {
		// TODO: This duplicates too much of the net/http RoundTrip flow.
		// We need to do that here because many of the http2 Transport tests
		// rely on having a ClientConn to operate on.
		//
		// We should switch to using net/http.Transport.NewClientConn to create
		// single-target client connections, and move any http2 tests which
		// exercise pooling behavior into net/http.
		defer close(rt.donec)
		cresp := &http.Response{}
		creq := &ClientRequest{
			Context:       req.Context(),
			Method:        req.Method,
			URL:           req.URL,
			Header:        Header(req.Header),
			Trailer:       Header(req.Trailer),
			Body:          req.Body,
			Host:          req.Host,
			GetBody:       req.GetBody,
			ContentLength: req.ContentLength,
			Cancel:        req.Cancel,
			Close:         req.Close,
			ResTrailer:    (*Header)(&cresp.Trailer),
		}
		resp, err := tc.cc.TestRoundTrip(creq, func(id uint32) {
			rt.id.Store(id)
		})
		rt.respErr = err
		if resp != nil {
			cresp.Status = resp.Status + " " + http.StatusText(resp.StatusCode)
			cresp.StatusCode = resp.StatusCode
			cresp.Proto = "HTTP/2.0"
			cresp.ProtoMajor = 2
			cresp.ProtoMinor = 0
			cresp.ContentLength = resp.ContentLength
			cresp.Uncompressed = resp.Uncompressed
			cresp.Header = http.Header(resp.Header)
			cresp.Trailer = http.Header(resp.Trailer)
			cresp.Body = resp.Body
			cresp.TLS = resp.TLS
			cresp.Request = req
			rt.resp = cresp
		}
	}()
	synctest.Wait()

	tc.t.Cleanup(func() {
		if !rt.done() {
			return
		}
		res, _ := rt.result()
		if res != nil {
			res.Body.Close()
		}
	})

	return rt
}

func (tc *testClientConn) greet(settings ...Setting) {
	tc.wantFrameType(FrameSettings)
	tc.wantFrameType(FrameWindowUpdate)
	tc.writeSettings(settings...)
	tc.writeSettingsAck()
	tc.wantFrameType(FrameSettings) // acknowledgement
}

// makeHeaderBlockFragment encodes headers in a form suitable for inclusion
// in a HEADERS or CONTINUATION frame.
//
// It takes a list of alternating names and values.
func (tc *testClientConn) makeHeaderBlockFragment(s ...string) []byte {
	if len(s)%2 != 0 {
		tc.t.Fatalf("uneven list of header name/value pairs")
	}
	tc.encbuf.Reset()
	for i := 0; i < len(s); i += 2 {
		tc.enc.WriteField(hpack.HeaderField{Name: s[i], Value: s[i+1]})
	}
	return tc.encbuf.Bytes()
}

// inflowWindow returns the amount of inbound flow control available for a stream,
// or for the connection if streamID is 0.
func (tc *testClientConn) inflowWindow(streamID uint32) int32 {
	w, err := tc.cc.TestInflowWindow(streamID)
	if err != nil {
		tc.t.Error(err)
	}
	return w
}

// testRoundTrip manages a RoundTrip in progress.
type testRoundTrip struct {
	t       *testing.T
	resp    *http.Response
	respErr error
	donec   chan struct{}
	id      atomic.Uint32
	cancel  context.CancelFunc
}

// streamID returns the HTTP/2 stream ID of the request.
func (rt *testRoundTrip) streamID() uint32 {
	id := rt.id.Load()
	if id == 0 {
		panic("stream ID unknown")
	}
	return id
}

// done reports whether RoundTrip has returned.
func (rt *testRoundTrip) done() bool {
	synctest.Wait()
	select {
	case <-rt.donec:
		return true
	default:
		return false
	}
}

// result returns the result of the RoundTrip.
func (rt *testRoundTrip) result() (*http.Response, error) {
	t := rt.t
	t.Helper()
	synctest.Wait()
	select {
	case <-rt.donec:
	default:
		t.Fatalf("RoundTrip is not done; want it to be")
	}
	return rt.resp, rt.respErr
}

// response returns the response of a successful RoundTrip.
// If the RoundTrip unexpectedly failed, it calls t.Fatal.
func (rt *testRoundTrip) response() *http.Response {
	t := rt.t
	t.Helper()
	resp, err := rt.result()
	if err != nil {
		t.Fatalf("RoundTrip returned unexpected error: %v", rt.respErr)
	}
	if resp == nil {
		t.Fatalf("RoundTrip returned nil *Response and nil error")
	}
	return resp
}

// err returns the (possibly nil) error result of RoundTrip.
func (rt *testRoundTrip) err() error {
	t := rt.t
	t.Helper()
	_, err := rt.result()
	return err
}

// wantStatus indicates the expected response StatusCode.
func (rt *testRoundTrip) wantStatus(want int) {
	t := rt.t
	t.Helper()
	if got := rt.response().StatusCode; got != want {
		t.Fatalf("got response status %v, want %v", got, want)
	}
}

// readBody reads the contents of the response body.
func (rt *testRoundTrip) readBody() ([]byte, error) {
	t := rt.t
	t.Helper()
	return io.ReadAll(rt.response().Body)
}

// wantBody indicates the expected response body.
// (Note that this consumes the body.)
func (rt *testRoundTrip) wantBody(want []byte) {
	t := rt.t
	t.Helper()
	got, err := rt.readBody()
	if err != nil {
		t.Fatalf("unexpected error reading response body: %v", err)
	}
	if !bytes.Equal(got, want) {
		t.Fatalf("unexpected response body:\ngot:  %q\nwant: %q", got, want)
	}
}

// wantHeaders indicates the expected response headers.
func (rt *testRoundTrip) wantHeaders(want http.Header) {
	t := rt.t
	t.Helper()
	res := rt.response()
	if diff := diffHeaders(res.Header, want); diff != "" {
		t.Fatalf("unexpected response headers:\n%v", diff)
	}
}

// wantTrailers indicates the expected response trailers.
func (rt *testRoundTrip) wantTrailers(want http.Header) {
	t := rt.t
	t.Helper()
	res := rt.response()
	if diff := diffHeaders(res.Trailer, want); diff != "" {
		t.Fatalf("unexpected response trailers:\n%v", diff)
	}
}

func diffHeaders(got, want http.Header) string {
	// nil and 0-length non-nil are equal.
	if len(got) == 0 && len(want) == 0 {
		return ""
	}
	// We could do a more sophisticated diff here.
	// DeepEqual is good enough for now.
	if reflect.DeepEqual(got, want) {
		return ""
	}
	return fmt.Sprintf("got:  %v\nwant: %v", got, want)
}

// A testTransport allows testing Transport.RoundTrip against fake servers.
// Tests that aren't specifically exercising RoundTrip's retry loop or connection pooling
// should use testClientConn instead.
type testTransport struct {
	t   *testing.T
	tr1 *http.Transport

	ccs []*testClientConn
}

func newTestTransport(t *testing.T, opts ...any) *testTransport {
	t.Helper()
	tt := &testTransport{
		t: t,
	}

	tr1 := &http.Transport{
		DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
			// This connection will be replaced by newTestClientConnFromClientConn.
			// net/http will perform a TLS handshake on it, though.
			//
			// TODO: We can simplify connection handling if we support
			// returning a non-*tls.Conn from Transport.DialTLSContext,
			// in which case we could have a DialTLSContext function that
			// returns an unencrypted conn.
			cli, srv := nettest.NewConnPair()
			go func() {
				tlsSrv := tls.Server(srv, testServerTLSConfig)
				if err := tlsSrv.Handshake(); err != nil {
					t.Errorf("unexpected TLS server handshake error: %v", err)
				}
			}()
			return cli, nil
		},
		Protocols:       protocols("h2"),
		TLSClientConfig: testClientTLSConfig,
	}
	for _, o := range opts {
		switch o := o.(type) {
		case nil:
		case func(*http.Transport):
			o(tr1)
		case func(*http.HTTP2Config):
			if tr1.HTTP2 == nil {
				tr1.HTTP2 = &http.HTTP2Config{}
			}
			o(tr1.HTTP2)
		default:
			t.Fatalf("unknown newTestTransport option type %T", o)
		}
	}
	tt.tr1 = tr1

	tr2 := transportFromH1Transport(tr1).(*Transport)
	tr2.TestSetNewClientConnHook(func(cc *ClientConn) {
		tc := newTestClientConnFromClientConn(t, tr2, cc)
		tt.ccs = append(tt.ccs, tc)
	})

	t.Cleanup(func() {
		synctest.Wait()
		if len(tt.ccs) > 0 {
			t.Fatalf("%v test ClientConns created, but not examined by test", len(tt.ccs))
		}
	})

	return tt
}

func (tt *testTransport) hasConn() bool {
	return len(tt.ccs) > 0
}

func (tt *testTransport) getConn() *testClientConn {
	tt.t.Helper()
	synctest.Wait()
	if len(tt.ccs) == 0 {
		tt.t.Fatalf("no new ClientConns created; wanted one")
	}
	tc := tt.ccs[0]
	tt.ccs = tt.ccs[1:]
	tc.readClientPreface()
	synctest.Wait()
	return tc
}

func (tt *testTransport) roundTrip(req *http.Request) *testRoundTrip {
	ctx, cancel := context.WithCancel(req.Context())
	req = req.WithContext(ctx)
	rt := &testRoundTrip{
		t:      tt.t,
		donec:  make(chan struct{}),
		cancel: cancel,
	}
	go func() {
		defer close(rt.donec)
		rt.resp, rt.respErr = tt.tr1.RoundTrip(req)
	}()
	synctest.Wait()

	tt.t.Cleanup(func() {
		if !rt.done() {
			return
		}
		res, _ := rt.result()
		if res != nil {
			res.Body.Close()
		}
	})

	return rt
}
