You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
1.4 KiB

  1. package rpcserver
  2. import (
  3. "fmt"
  4. "io"
  5. "io/ioutil"
  6. "net/http"
  7. "sync"
  8. "sync/atomic"
  9. "testing"
  10. "time"
  11. "github.com/tendermint/tmlibs/log"
  12. )
  13. func TestMaxOpenConnections(t *testing.T) {
  14. const max = 5 // max simultaneous connections
  15. // Start the server.
  16. var open int32
  17. mux := http.NewServeMux()
  18. mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  19. if n := atomic.AddInt32(&open, 1); n > int32(max) {
  20. t.Errorf("%d open connections, want <= %d", n, max)
  21. }
  22. defer atomic.AddInt32(&open, -1)
  23. time.Sleep(10 * time.Millisecond)
  24. fmt.Fprint(w, "some body")
  25. })
  26. l, err := StartHTTPServer("tcp://127.0.0.1:0", mux, log.TestingLogger(), Config{MaxOpenConnections: max})
  27. if err != nil {
  28. t.Fatal(err)
  29. }
  30. defer l.Close()
  31. // Make N GET calls to the server.
  32. attempts := max * 2
  33. var wg sync.WaitGroup
  34. var failed int32
  35. for i := 0; i < attempts; i++ {
  36. wg.Add(1)
  37. go func() {
  38. defer wg.Done()
  39. c := http.Client{Timeout: 3 * time.Second}
  40. r, err := c.Get("http://" + l.Addr().String())
  41. if err != nil {
  42. t.Log(err)
  43. atomic.AddInt32(&failed, 1)
  44. return
  45. }
  46. defer r.Body.Close()
  47. io.Copy(ioutil.Discard, r.Body)
  48. }()
  49. }
  50. wg.Wait()
  51. // We expect some Gets to fail as the server's accept queue is filled,
  52. // but most should succeed.
  53. if int(failed) >= attempts/2 {
  54. t.Errorf("%d requests failed within %d attempts", failed, attempts)
  55. }
  56. }