Commit 67ab3a29 authored by Nick Thomas's avatar Nick Thomas

Merge branch 'mk/rework-image-scaler-tests' into 'master'

Rework image scaler tests

See merge request gitlab-org/gitlab-workhorse!650
parents e926e51c 22418c0d
---
title: Rework image scaler test suite
merge_request:
author:
type: other
package imageresizer package imageresizer
import ( import (
"bytes"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"image"
"image/png"
"net/http" "net/http"
"net/http/httptest"
"os" "os"
"testing" "testing"
...@@ -17,6 +19,8 @@ import ( ...@@ -17,6 +19,8 @@ import (
"gitlab.com/gitlab-org/gitlab-workhorse/internal/testhelper" "gitlab.com/gitlab-org/gitlab-workhorse/internal/testhelper"
) )
const imagePath = "../../testdata/image.png"
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
if err := testhelper.BuildExecutables(); err != nil { if err := testhelper.BuildExecutables(); err != nil {
log.WithError(err).Fatal() log.WithError(err).Fatal()
...@@ -25,106 +29,81 @@ func TestMain(m *testing.M) { ...@@ -25,106 +29,81 @@ func TestMain(m *testing.M) {
os.Exit(m.Run()) os.Exit(m.Run())
} }
func TestUnpackParametersReturnsParamsInstanceForValidInput(t *testing.T) { func requestScaledImage(t *testing.T, httpHeaders http.Header, params resizeParams, cfg config.ImageResizerConfig) *http.Response {
r := Resizer{} httpRequest := httptest.NewRequest("GET", "/image", nil)
inParams := resizeParams{Location: "/path/to/img", Width: 64, ContentType: "image/png"} responseWriter := httptest.NewRecorder()
paramsJSON := encodeParams(t, &params)
outParams, err := r.unpackParameters(encodeParams(t, &inParams)) NewResizer(config.Config{ImageResizerConfig: cfg}).Inject(responseWriter, httpRequest, paramsJSON)
require.NoError(t, err, "unexpected error when unpacking params") return responseWriter.Result()
require.Equal(t, inParams, *outParams)
} }
func TestUnpackParametersReturnsErrorWhenLocationBlank(t *testing.T) { func TestRequestScaledImageFromPath(t *testing.T) {
r := Resizer{} cfg := config.DefaultImageResizerConfig
inParams := resizeParams{Location: "", Width: 64, ContentType: "image/jpg"} params := resizeParams{Location: imagePath, ContentType: "image/png", Width: 64}
_, err := r.unpackParameters(encodeParams(t, &inParams)) resp := requestScaledImage(t, nil, params, cfg)
require.Equal(t, http.StatusOK, resp.StatusCode)
require.Error(t, err, "expected error when Location is blank") bounds := imageFromResponse(t, resp).Bounds()
require.Equal(t, int(params.Width), bounds.Size().X, "wrong width after resizing")
} }
func TestUnpackParametersReturnsErrorWhenContentTypeBlank(t *testing.T) { func TestServeOriginalImageWhenSourceImageTooLarge(t *testing.T) {
r := Resizer{} originalImage := testImage(t)
inParams := resizeParams{Location: "/path/to/img", Width: 64, ContentType: ""} cfg := config.ImageResizerConfig{MaxScalerProcs: 1, MaxFilesize: 1}
params := resizeParams{Location: imagePath, ContentType: "image/png", Width: 64}
_, err := r.unpackParameters(encodeParams(t, &inParams)) resp := requestScaledImage(t, nil, params, cfg)
require.Equal(t, http.StatusOK, resp.StatusCode)
require.Error(t, err, "expected error when ContentType is blank") img := imageFromResponse(t, resp)
require.Equal(t, originalImage.Bounds(), img.Bounds(), "expected original image size")
} }
func TestTryResizeImageSuccess(t *testing.T) { func TestFailFastOnOpenStreamFailure(t *testing.T) {
r := Resizer{} cfg := config.DefaultImageResizerConfig
inParams := resizeParams{Location: "/path/to/img", Width: 64, ContentType: "image/png"} params := resizeParams{Location: "does_not_exist.png", ContentType: "image/png", Width: 64}
inFile := testImage(t) resp := requestScaledImage(t, nil, params, cfg)
req, err := http.NewRequest("GET", "/foo", nil)
require.NoError(t, err)
reader, cmd, err := r.tryResizeImage( require.Equal(t, http.StatusInternalServerError, resp.StatusCode)
req, }
inFile,
os.Stderr,
&inParams,
int64(config.DefaultImageResizerConfig.MaxFilesize),
config.DefaultImageResizerConfig,
)
require.NoError(t, err) func TestFailFastOnContentTypeMismatch(t *testing.T) {
require.NotNil(t, cmd) cfg := config.DefaultImageResizerConfig
require.NotNil(t, reader) params := resizeParams{Location: imagePath, ContentType: "image/jpeg", Width: 64}
require.NotEqual(t, inFile, reader) resp := requestScaledImage(t, nil, params, cfg)
require.Equal(t, http.StatusInternalServerError, resp.StatusCode)
} }
func TestTryResizeImageSkipsResizeWhenSourceImageTooLarge(t *testing.T) { func TestUnpackParametersReturnsParamsInstanceForValidInput(t *testing.T) {
r := Resizer{} r := Resizer{}
inParams := resizeParams{Location: "/path/to/img", Width: 64, ContentType: "image/png"} inParams := resizeParams{Location: imagePath, Width: 64, ContentType: "image/png"}
inFile := testImage(t)
req, err := http.NewRequest("GET", "/foo", nil) outParams, err := r.unpackParameters(encodeParams(t, &inParams))
require.NoError(t, err)
reader, cmd, err := r.tryResizeImage( require.NoError(t, err, "unexpected error when unpacking params")
req, require.Equal(t, inParams, *outParams)
inFile,
os.Stderr,
&inParams,
int64(config.DefaultImageResizerConfig.MaxFilesize)+1,
config.DefaultImageResizerConfig,
)
require.Error(t, err)
require.Nil(t, cmd)
require.Equal(t, inFile, reader, "Expected output streams to match")
} }
func TestTryResizeImageFailsWhenContentTypeNotMatchingFileContents(t *testing.T) { func TestUnpackParametersReturnsErrorWhenLocationBlank(t *testing.T) {
r := Resizer{} r := Resizer{}
inParams := resizeParams{Location: "/path/to/img", Width: 64, ContentType: "image/jpeg"} inParams := resizeParams{Location: "", Width: 64, ContentType: "image/jpg"}
inFile := testImage(t) // this is a PNG file; the image scaler should fail fast in this case
req, err := http.NewRequest("GET", "/foo", nil)
require.NoError(t, err)
_, cmd, err := r.tryResizeImage( _, err := r.unpackParameters(encodeParams(t, &inParams))
req,
inFile,
os.Stderr,
&inParams,
int64(config.DefaultImageResizerConfig.MaxFilesize),
config.DefaultImageResizerConfig,
)
require.NoError(t, err) require.Error(t, err, "expected error when Location is blank")
require.Error(t, cmd.Wait(), "Expected to fail due to content-type mismatch")
} }
func TestServeImage(t *testing.T) { func TestUnpackParametersReturnsErrorWhenContentTypeBlank(t *testing.T) {
inFile := testImage(t) r := Resizer{}
var writer bytes.Buffer inParams := resizeParams{Location: imagePath, Width: 64, ContentType: ""}
bytesWritten, err := serveImage(inFile, &writer, nil) _, err := r.unpackParameters(encodeParams(t, &inParams))
require.NoError(t, err) require.Error(t, err, "expected error when ContentType is blank")
require.Greater(t, bytesWritten, int64(0))
require.Equal(t, int64(len(writer.Bytes())), bytesWritten)
} }
// The Rails applications sends a Base64 encoded JSON string carrying // The Rails applications sends a Base64 encoded JSON string carrying
...@@ -137,8 +116,18 @@ func encodeParams(t *testing.T, p *resizeParams) string { ...@@ -137,8 +116,18 @@ func encodeParams(t *testing.T, p *resizeParams) string {
return base64.StdEncoding.EncodeToString(json) return base64.StdEncoding.EncodeToString(json)
} }
func testImage(t *testing.T) *os.File { func testImage(t *testing.T) image.Image {
f, err := os.Open("../../testdata/image.png") f, err := os.Open(imagePath)
require.NoError(t, err) require.NoError(t, err)
return f
image, err := png.Decode(f)
require.NoError(t, err, "decode original image")
return image
}
func imageFromResponse(t *testing.T, resp *http.Response) image.Image {
img, err := png.Decode(resp.Body)
require.NoError(t, err, "decode resized image")
return img
} }
...@@ -386,7 +386,7 @@ func TestImageResizing(t *testing.T) { ...@@ -386,7 +386,7 @@ func TestImageResizing(t *testing.T) {
require.NoError(t, err, "decode resized image") require.NoError(t, err, "decode resized image")
bounds := img.Bounds() bounds := img.Bounds()
require.Equal(t, requestedWidth, bounds.Max.X-bounds.Min.X, "width after resizing") require.Equal(t, requestedWidth, bounds.Size().X, "wrong width after resizing")
} }
func TestSendURLForArtifacts(t *testing.T) { func TestSendURLForArtifacts(t *testing.T) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment