matrix_test.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package integration
  2. import (
  3. "fmt"
  4. "net/http"
  5. "os"
  6. "path"
  7. "path/filepath"
  8. "testing"
  9. "github.com/imgproxy/imgproxy/v3/imagetype"
  10. "github.com/imgproxy/imgproxy/v3/testutil"
  11. "github.com/imgproxy/imgproxy/v3/vips"
  12. "github.com/stretchr/testify/suite"
  13. )
  14. const (
  15. // maximum Hamming distance between the source and destination hash
  16. // NOTE: 2 here is because HEIC works a bit differently over the platforms, investigate
  17. maxDistance = 2
  18. )
  19. // formats to test
  20. var formats = []imagetype.Type{
  21. imagetype.GIF,
  22. imagetype.JPEG,
  23. imagetype.HEIC,
  24. imagetype.JXL,
  25. imagetype.SVG,
  26. imagetype.TIFF,
  27. imagetype.WEBP,
  28. imagetype.BMP,
  29. imagetype.ICO,
  30. }
  31. type MatrixTestSuite struct {
  32. Suite
  33. matcher *testutil.ImageHashMatcher
  34. testImagesPath string
  35. }
  36. func (s *MatrixTestSuite) SetupTest() {
  37. s.testImagesPath = s.TestData.Path("test-images")
  38. s.matcher = testutil.NewImageHashMatcher(s.TestData)
  39. s.Config().Security.DefaultOptions.MaxAnimationFrames = 999
  40. s.Config().Server.DevelopmentErrorsMode = true
  41. s.Config().Fetcher.Transport.Local.Root = s.testImagesPath
  42. }
  43. // testLoadFolder fetches images iterates over images in the specified folder,
  44. // runs imgproxy on each image, and compares the result with the reference image
  45. // which is expected to be in the `integration` folder with the same name
  46. // but with `.png` extension.
  47. func (s *MatrixTestSuite) testFormat(source, target imagetype.Type) {
  48. folder := source.String()
  49. // TODO: rename the folders in test-images repo
  50. if folder == "heic" {
  51. folder = "heif"
  52. }
  53. if folder == "jpeg" {
  54. folder = "jpg"
  55. }
  56. walkPath := path.Join(s.testImagesPath, folder)
  57. // Iterate over the files in the source folder
  58. err := filepath.Walk(walkPath, func(path string, info os.FileInfo, err error) error {
  59. s.Require().NoError(err)
  60. // Skip directories
  61. if info.IsDir() {
  62. return nil
  63. }
  64. // get the base name of the file (8-bpp.png)
  65. baseName := filepath.Base(path)
  66. // Construct the source URL for imgproxy (no processing)
  67. sourceUrl := fmt.Sprintf("/insecure/plain/local:///%s/%s@%s", folder, baseName, target.String())
  68. // Read source image from imgproxy
  69. resp := s.GET(sourceUrl)
  70. defer resp.Body.Close()
  71. s.Require().Equal(http.StatusOK, resp.StatusCode, "expected status code 200 OK, got %d, url: %s", resp.StatusCode, sourceUrl)
  72. // Match image to precalculated hash
  73. s.matcher.ImageMatches(s.T(), resp.Body, baseName, maxDistance)
  74. return nil
  75. })
  76. s.Require().NoError(err)
  77. }
  78. func (s *MatrixTestSuite) TestMatrix() {
  79. for _, source := range formats {
  80. for _, target := range formats {
  81. s.Run(fmt.Sprintf("%s/%s", source.String(), target.String()), func() {
  82. if !target.IsVector() && source.IsVector() {
  83. // we can not vectorize a raster image
  84. s.T().Logf("Skipping %s -> %s conversion: we can not vectorize raster image", source.String(), target.String())
  85. return
  86. }
  87. if !vips.SupportsLoad(source) {
  88. s.T().Logf("Skipping %s -> %s conversion: source format not supported by VIPS", source.String(), target.String())
  89. return
  90. }
  91. if !vips.SupportsSave(target) {
  92. s.T().Logf("Skipping %s -> %s conversion: target format not supported by VIPS", source.String(), target.String())
  93. return
  94. }
  95. s.testFormat(source, target)
  96. })
  97. }
  98. }
  99. }
  100. func TestMatrix(t *testing.T) {
  101. suite.Run(t, new(MatrixTestSuite))
  102. }