package server import ( "crypto/tls" "fmt" "io" "io/ioutil" "net" "net/http" "sync" "sync/atomic" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/libs/log" ) func TestMaxOpenConnections(t *testing.T) { const max = 5 // max simultaneous connections // Start the server. var open int32 mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if n := atomic.AddInt32(&open, 1); n > int32(max) { t.Errorf("%d open connections, want <= %d", n, max) } defer atomic.AddInt32(&open, -1) time.Sleep(10 * time.Millisecond) fmt.Fprint(w, "some body") }) config := DefaultConfig() config.MaxOpenConnections = max l, err := Listen("tcp://127.0.0.1:0", config) require.NoError(t, err) defer l.Close() go Serve(l, mux, log.TestingLogger(), config) //nolint:errcheck // ignore for tests // Make N GET calls to the server. attempts := max * 2 var wg sync.WaitGroup var failed int32 for i := 0; i < attempts; i++ { wg.Add(1) go func() { defer wg.Done() c := http.Client{Timeout: 3 * time.Second} r, err := c.Get("http://" + l.Addr().String()) if err != nil { t.Log(err) atomic.AddInt32(&failed, 1) return } defer r.Body.Close() _, err = io.Copy(ioutil.Discard, r.Body) require.NoError(t, err) }() } wg.Wait() // We expect some Gets to fail as the server's accept queue is filled, // but most should succeed. if int(failed) >= attempts/2 { t.Errorf("%d requests failed within %d attempts", failed, attempts) } } func TestServeTLS(t *testing.T) { ln, err := net.Listen("tcp", "localhost:0") require.NoError(t, err) defer ln.Close() mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "some body") }) go ServeTLS(ln, mux, "test.crt", "test.key", log.TestingLogger(), DefaultConfig()) tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // nolint: gosec } c := &http.Client{Transport: tr} res, err := c.Get("https://" + ln.Addr().String()) require.NoError(t, err) defer res.Body.Close() assert.Equal(t, http.StatusOK, res.StatusCode) body, err := ioutil.ReadAll(res.Body) require.NoError(t, err) assert.Equal(t, []byte("some body"), body) }