Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
989da78681 |
@@ -2,44 +2,64 @@ package imageprocessor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestImageProcessor_RefusesAVIFAboveMaxPixels verifies that an AVIF output
|
// TestImageProcessor_RefusesAVIFAboveMaxPixels verifies that an AVIF output
|
||||||
// of more than MaxAVIFOutputPixels is refused with ErrAVIFOutputTooLarge
|
// of more than MaxAVIFOutputPixels is refused with ErrAVIFOutputTooLarge
|
||||||
// before anything is decoded, whatever size and fit give it, and that an AVIF
|
// before anything is decoded, whatever size and fit give it, the source's own
|
||||||
// output of at most that many pixels, or one in another format, is not. The
|
// size included, and that an AVIF output of at most that many pixels, or one
|
||||||
// input is a 64x32 PNG cut off in its pixel data: libvips reads its size from
|
// in another format, is not. One input is a 64x32 PNG cut off in its pixel
|
||||||
// its header but fails when it decodes it, so a request that gets that failure
|
// data. The other is testdata/red.avif, a 4x4 AVIF, with the size in its
|
||||||
// was not refused, and a refusal came before any decoding.
|
// header changed to 4097x4096. libvips reads each input's size from its
|
||||||
|
// header but fails when it decodes its pixel data, so a request that gets
|
||||||
|
// that failure was not refused, and a refusal came before any decoding.
|
||||||
func TestImageProcessor_RefusesAVIFAboveMaxPixels(t *testing.T) {
|
func TestImageProcessor_RefusesAVIFAboveMaxPixels(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
whole := createTestPNG(t, 64, 32)
|
whole := createTestPNG(t, 64, 32)
|
||||||
cutOff := whole[:len(whole)/2]
|
cutOff := whole[:len(whole)/2]
|
||||||
|
|
||||||
|
largeAVIF, err := os.ReadFile("testdata/red.avif")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to read test AVIF: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ispe box gives the width and then the height, 4 bytes each, after
|
||||||
|
// the box's type and its 4 bytes of version and flags
|
||||||
|
ispe := bytes.Index(largeAVIF, []byte("ispe"))
|
||||||
|
binary.BigEndian.PutUint32(largeAVIF[ispe+8:], 4097)
|
||||||
|
binary.BigEndian.PutUint32(largeAVIF[ispe+12:], 4096)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
input []byte
|
||||||
format Format
|
format Format
|
||||||
width, height int
|
width, height int
|
||||||
fit FitMode
|
fit FitMode
|
||||||
refused bool
|
refused bool
|
||||||
}{
|
}{
|
||||||
{"AVIF at the limit", FormatAVIF, 4096, 4096, FitCover, false},
|
{"AVIF at the limit", cutOff, FormatAVIF, 4096, 4096, FitCover, false},
|
||||||
{"AVIF above the limit", FormatAVIF, 4096, 4097, FitCover, true},
|
{"AVIF above the limit", cutOff, FormatAVIF, 4096, 4097, FitCover, true},
|
||||||
{"WebP above the AVIF limit", FormatWebP, 4096, 4097, FitCover, false},
|
{"WebP above the AVIF limit", cutOff, FormatWebP, 4096, 4097, FitCover, false},
|
||||||
// FitInside does not enlarge, so the output stays 64x32
|
// FitInside does not enlarge, so the output stays 64x32
|
||||||
{"AVIF inside a larger size", FormatAVIF, 8192, 8192, FitInside, false},
|
{"AVIF inside a larger size", cutOff, FormatAVIF, 8192, 8192, FitInside, false},
|
||||||
// FitOutside scales 64x32 by 128 to cover 8192x1: 8192x4096
|
// FitOutside scales 64x32 by 128 to cover 8192x1: 8192x4096
|
||||||
{"AVIF outside a smaller size", FormatAVIF, 8192, 1, FitOutside, true},
|
{"AVIF outside a smaller size", cutOff, FormatAVIF, 8192, 1, FitOutside, true},
|
||||||
|
// With no size, the output keeps the source's 4097x4096
|
||||||
|
{"AVIF of the source's size", largeAVIF, FormatAVIF, 0, 0, FitCover, true},
|
||||||
|
{"orig of an AVIF source", largeAVIF, FormatOriginal, 0, 0, FitCover, true},
|
||||||
|
{"JPEG of the source's size", largeAVIF, FormatJPEG, 0, 0, FitCover, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
_, err := New(Params{}).Process(t.Context(), bytes.NewReader(cutOff),
|
_, err := New(Params{}).Process(t.Context(), bytes.NewReader(tt.input),
|
||||||
&Request{
|
&Request{
|
||||||
Size: Size{Width: tt.width, Height: tt.height},
|
Size: Size{Width: tt.width, Height: tt.height},
|
||||||
Format: tt.format,
|
Format: tt.format,
|
||||||
@@ -57,7 +77,7 @@ func TestImageProcessor_RefusesAVIFAboveMaxPixels(t *testing.T) {
|
|||||||
|
|
||||||
if err == nil || errors.Is(err, ErrAVIFOutputTooLarge) {
|
if err == nil || errors.Is(err, ErrAVIFOutputTooLarge) {
|
||||||
t.Errorf("Process() error = %v, want the failure to decode "+
|
t.Errorf("Process() error = %v, want the failure to decode "+
|
||||||
"the cut-off input", err)
|
"the input", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user