suite.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package integration
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "net/http"
  7. "github.com/imgproxy/imgproxy/v3"
  8. "github.com/imgproxy/imgproxy/v3/httpheaders"
  9. "github.com/imgproxy/imgproxy/v3/logger"
  10. "github.com/imgproxy/imgproxy/v3/testutil"
  11. )
  12. type TestServer struct {
  13. Addr net.Addr
  14. Shutdown context.CancelFunc
  15. }
  16. // Suite is a test suite for integration tests.
  17. //
  18. // It lazily initializes [imgproxy.Config] and [imgproxy.Imgproxy] when they are accessed.
  19. //
  20. // It provides the [Suite.GET] method that lazily initializes a test imgproxy server
  21. // and performs a GET request against it.
  22. //
  23. // Take note that Suite utilizes SetupSuite and TearDownSuite for setup and cleanup.
  24. // If you define them for your test suite, make sure to call the base methods.
  25. type Suite struct {
  26. testutil.LazySuite
  27. TestData *testutil.TestDataProvider
  28. Config testutil.LazyObj[*imgproxy.Config]
  29. Imgproxy testutil.LazyObj[*imgproxy.Imgproxy]
  30. Server testutil.LazyObj[*TestServer]
  31. }
  32. func (s *Suite) SetupSuite() {
  33. // Silence all the logs
  34. logger.Mute()
  35. // Initialize test data provider (local test files)
  36. s.TestData = testutil.NewTestDataProvider(s.T)
  37. s.Config, _ = testutil.NewLazySuiteObj(s, func() (*imgproxy.Config, error) {
  38. c := imgproxy.NewDefaultConfig()
  39. c.Server.Bind = ":0"
  40. c.Fetcher.Transport.Local.Root = s.TestData.Root()
  41. c.Fetcher.Transport.HTTP.ClientKeepAliveTimeout = 0
  42. return &c, nil
  43. })
  44. s.Imgproxy, _ = testutil.NewLazySuiteObj(s, func() (*imgproxy.Imgproxy, error) {
  45. return imgproxy.New(s.T().Context(), s.Config())
  46. })
  47. // NOTE: if we used s.T().Context() in startServer, server would have been stopped
  48. // after the first subtest because s.T().Context() is cancelled after subtest.
  49. //
  50. // If resetLazyObjs is not called in SetupSubTest, the server would shutdown
  51. // and won't restart in the second subtest because lazy obj would not be nil.
  52. ctx := s.T().Context()
  53. s.Server, _ = testutil.NewLazySuiteObj(
  54. s,
  55. func() (*TestServer, error) {
  56. return s.startServer(ctx, s.Imgproxy()), nil
  57. },
  58. func(s *TestServer) error {
  59. s.Shutdown()
  60. return nil
  61. },
  62. )
  63. }
  64. func (s *Suite) TearDownSuite() {
  65. logger.Unmute()
  66. }
  67. // startServer starts imgproxy instance's server for the tests.
  68. // Returns [TestServer] that contains the server address and shutdown function
  69. func (s *Suite) startServer(ctx context.Context, i *imgproxy.Imgproxy) *TestServer {
  70. ctx, cancel := context.WithCancel(ctx)
  71. addrCh := make(chan net.Addr)
  72. go func() {
  73. err := i.StartServer(ctx, addrCh)
  74. if err != nil {
  75. s.T().Errorf("Imgproxy stopped with error: %v", err)
  76. }
  77. }()
  78. return &TestServer{
  79. Addr: <-addrCh,
  80. Shutdown: cancel,
  81. }
  82. }
  83. // GET performs a GET request to the imageproxy real server
  84. func (s *Suite) GET(path string, header ...http.Header) *http.Response {
  85. url := fmt.Sprintf("http://%s%s", s.Server().Addr, path)
  86. // Perform GET request to an url
  87. req, err := http.NewRequest("GET", url, nil)
  88. s.Require().NoError(err)
  89. // Copy headers from the provided http.Header to the request
  90. for _, h := range header {
  91. httpheaders.CopyAll(h, req.Header, true)
  92. }
  93. // Do the request
  94. resp, err := http.DefaultClient.Do(req)
  95. s.Require().NoError(err)
  96. return resp
  97. }