inprocess_transport_test.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. package repository
  2. import (
  3. "bytes"
  4. "io"
  5. "net"
  6. "net/http"
  7. "net/http/httptest"
  8. "sync"
  9. "testing"
  10. )
  11. type roundTripFunc func(*http.Request) (*http.Response, error)
  12. func (f roundTripFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) }
  13. // newInProcessTransport adapts an http.HandlerFunc into an http.RoundTripper without opening sockets.
  14. // It captures the request body (if any) and then rewinds it before invoking the handler.
  15. func newInProcessTransport(handler http.HandlerFunc, capture func(r *http.Request, body []byte)) http.RoundTripper {
  16. return roundTripFunc(func(r *http.Request) (*http.Response, error) {
  17. var body []byte
  18. if r.Body != nil {
  19. body, _ = io.ReadAll(r.Body)
  20. _ = r.Body.Close()
  21. r.Body = io.NopCloser(bytes.NewReader(body))
  22. }
  23. if capture != nil {
  24. capture(r, body)
  25. }
  26. rec := httptest.NewRecorder()
  27. handler(rec, r)
  28. return rec.Result(), nil
  29. })
  30. }
  31. var (
  32. canListenOnce sync.Once
  33. canListen bool
  34. canListenErr error
  35. )
  36. func localListenerAvailable() bool {
  37. canListenOnce.Do(func() {
  38. ln, err := net.Listen("tcp", "127.0.0.1:0")
  39. if err != nil {
  40. canListenErr = err
  41. canListen = false
  42. return
  43. }
  44. _ = ln.Close()
  45. canListen = true
  46. })
  47. return canListen
  48. }
  49. func newLocalTestServer(tb testing.TB, handler http.Handler) *httptest.Server {
  50. tb.Helper()
  51. if !localListenerAvailable() {
  52. tb.Skipf("local listeners are not permitted in this environment: %v", canListenErr)
  53. }
  54. return httptest.NewServer(handler)
  55. }