check / check (push) Waiting to run
WebP is saved at effort 2 and JPEG XL at effort 4, and an AVIF output of more than 16,777,216 pixels is refused with 400 before anything is decoded, as AVIF is already at the lowest effort govips can set. With one libvips thread, at any quality, 8192x8192 random pixels with an alpha channel take up to about 23 seconds as WebP and 27 as JPEG XL, and 4096x4096, 8192x2048 or 2048x8192 up to about 34 as AVIF. Resizing with fit=cover already decodes the input, so the output's dimensions are now worked out before resizing, in outputDimensions. Reading the input moves into readInput to keep Process within the linter's limits. TestImageProcessor_WebPAtDefaultEffort becomes TestImageProcessor_WebPAtEffort2, as #280 (comment) allows. Model: opus-5-5
50 lines
1.5 KiB
Go
50 lines
1.5 KiB
Go
package handlers
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"sneak.berlin/go/pixa/internal/imageprocessor"
|
|
"sneak.berlin/go/pixa/internal/imgcache"
|
|
)
|
|
|
|
// TestAVIFOutputTooLargeAnswers400 checks that respondImageError and
|
|
// handleImageError, which answer the errors of the two image routes, answer
|
|
// 400 naming the AVIF pixel limit when the image processor refuses an AVIF
|
|
// output above it, wrapped as the service wraps it. The request's source only
|
|
// goes into a log line, so it is left empty.
|
|
func TestAVIFOutputTooLargeAnswers400(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
h := &Handlers{log: slog.New(slog.DiscardHandler)}
|
|
err := fmt.Errorf("image processing failed: %w: 4097x4096",
|
|
imageprocessor.ErrAVIFOutputTooLarge)
|
|
wantBody := fmt.Sprintf("above %d pixels", imageprocessor.MaxAVIFOutputPixels)
|
|
|
|
plain := httptest.NewRecorder()
|
|
h.respondImageError(plain, &imgcache.ImageRequest{}, err)
|
|
|
|
encrypted := httptest.NewRecorder()
|
|
h.handleImageError(encrypted, err)
|
|
|
|
for name, rec := range map[string]*httptest.ResponseRecorder{
|
|
"respondImageError": plain, "handleImageError": encrypted,
|
|
} {
|
|
t.Logf("%s: status = %d, body = %q", name, rec.Code, rec.Body.String())
|
|
|
|
if rec.Code != http.StatusBadRequest {
|
|
t.Errorf("%s: status = %d, want %d",
|
|
name, rec.Code, http.StatusBadRequest)
|
|
}
|
|
|
|
if !strings.Contains(rec.Body.String(), wantBody) {
|
|
t.Errorf("%s: body = %q, want it to say %q",
|
|
name, rec.Body.String(), wantBody)
|
|
}
|
|
}
|
|
}
|