package test

import (
	"context"
	"crypto/tls"
	"io"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"
)

// TestH2Calls attempts to reproduce an http/2 flow control bug that was
// present in gRPC. It did not affect the standard library's http/2
// implementation.
func TestH2Calls(t *testing.T) {
	const itemCount = 100
	const itemSize = 1 << 10

	srv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		for i := 0; i < itemCount; i++ {
			w.Write(make([]byte, itemSize))
		}
		// t.Logf("remote %s", r.RemoteAddr)
	}))

	srv.TLS = &tls.Config{
		NextProtos: []string{"h2", "http/1.1"},
	}
	srv.StartTLS()
	defer srv.Close()

	cl := srv.Client()

	prev := func() {}
	for i := 0; i < 10000; i++ {
		req, err := http.NewRequest("GET", srv.URL, nil)
		if err != nil {
			t.Fatalf("http.NewRequest; err = %q", err)
		}
		ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
		resp, err := cl.Do(req.WithContext(ctx))
		if err != nil {
			t.Errorf("http.(*Client).Get; i = %d, err = %q", i, err)
			cancel()
			return
		}
		// read only part of the response
		for j := 0; j < 2; j++ {
			_, err := io.ReadFull(resp.Body, make([]byte, itemSize))
			if err != nil && err != io.EOF {
				t.Fatalf("io.ReadFull(resp.Body, ...); err = %q", err)
			}
		}

		resp.Body.Close()
		prev()
		prev = func() {
			cancel()
		}
	}
	prev()
}
