package repro

import (
	"crypto/tls"
	"net/http"
	"net/http/httptest"
	"sync/atomic"
	"testing"
)

func TestHTTPTestHTTP2(t *testing.T) {
	t.Run("basic", func(t *testing.T) {
		var calls int64
		s := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			atomic.AddInt64(&calls, 1)
			if !r.ProtoAtLeast(2, 0) {
				t.Errorf("Request is not http/2: %q", r.Proto)
			}
		}))
		defer s.Close()

		resp, err := s.Client().Get(s.URL)
		if err != nil {
			t.Fatalf("HTTP GET: %v", err)
		}
		resp.Body.Close()
		if have, want := atomic.LoadInt64(&calls), int64(1); have != want {
			t.Errorf("HTTP handler called %d times, expected %d times", have, want)
		}
	})

	t.Run("advertise-h2", func(t *testing.T) {
		var calls int64
		s := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			atomic.AddInt64(&calls, 1)
			if !r.ProtoAtLeast(2, 0) {
				t.Errorf("Request is not http/2: %q", r.Proto)
			}
		}))
		s.TLS = &tls.Config{
			NextProtos: []string{"h2"},
		}
		s.StartTLS()
		defer s.Close()

		resp, err := s.Client().Get(s.URL)
		if err != nil {
			t.Fatalf("HTTP GET: %v", err)
		}
		resp.Body.Close()
		if have, want := atomic.LoadInt64(&calls), int64(1); have != want {
			t.Errorf("HTTP handler called %d times, expected %d times", have, want)
		}
	})

	t.Run("transport-hacks", func(t *testing.T) {
		var calls int64
		s := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			atomic.AddInt64(&calls, 1)
			if !r.ProtoAtLeast(2, 0) {
				t.Errorf("Request is not http/2: %q", r.Proto)
			}
		}))
		s.TLS = &tls.Config{
			NextProtos: []string{"h2"},
		}
		s.StartTLS()
		defer s.Close()

		transport := s.Client().Transport.(*http.Transport)
		clientConfig := transport.TLSClientConfig
		transport.TLSClientConfig = nil

		// make a request to trigger HTTP/2 autoconfiguration
		resp, err := s.Client().Get(s.URL)
		if err == nil {
			t.Errorf(`Expected harmless "certificate signed by unknown authority" error`)
			resp.Body.Close()
		}
		// now allow the client to connect to the ad-hoc test server
		transport.TLSClientConfig.RootCAs = clientConfig.RootCAs

		resp, err = s.Client().Get(s.URL)
		if err != nil {
			t.Fatalf("HTTP GET: %v", err)
		}
		resp.Body.Close()
		if have, want := atomic.LoadInt64(&calls), int64(1); have != want {
			t.Errorf("HTTP handler called %d times, expected %d times", have, want)
		}
	})
}
