package imageprocessor import ( "bytes" "errors" "testing" ) // TestImageProcessor_RefusesAVIFAboveMaxPixels verifies that an AVIF output // of more than MaxAVIFOutputPixels is refused with ErrAVIFOutputTooLarge // before anything is decoded, whatever size and fit give it, and that an AVIF // output of at most that many pixels, or one in another format, is not. The // input is a 64x32 PNG cut off in its pixel data: libvips reads its size from // its header but fails when it decodes it, so a request that gets that failure // was not refused, and a refusal came before any decoding. func TestImageProcessor_RefusesAVIFAboveMaxPixels(t *testing.T) { t.Parallel() whole := createTestPNG(t, 64, 32) cutOff := whole[:len(whole)/2] tests := []struct { name string format Format width, height int fit FitMode refused bool }{ {"AVIF at the limit", FormatAVIF, 4096, 4096, FitCover, false}, {"AVIF above the limit", FormatAVIF, 4096, 4097, FitCover, true}, {"WebP above the AVIF limit", FormatWebP, 4096, 4097, FitCover, false}, // FitInside does not enlarge, so the output stays 64x32 {"AVIF inside a larger size", FormatAVIF, 8192, 8192, FitInside, false}, // FitOutside scales 64x32 by 128 to cover 8192x1: 8192x4096 {"AVIF outside a smaller size", FormatAVIF, 8192, 1, FitOutside, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() _, err := New(Params{}).Process(t.Context(), bytes.NewReader(cutOff), &Request{ Size: Size{Width: tt.width, Height: tt.height}, Format: tt.format, FitMode: tt.fit, }) t.Logf("Process() error = %v", err) if tt.refused { if !errors.Is(err, ErrAVIFOutputTooLarge) { t.Errorf("Process() error = %v, want %v", err, ErrAVIFOutputTooLarge) } return } if err == nil || errors.Is(err, ErrAVIFOutputTooLarge) { t.Errorf("Process() error = %v, want the failure to decode "+ "the cut-off input", err) } }) } }