mirror of
https://github.com/willnorris/imageproxy.git
synced 2024-12-30 22:34:18 -05:00
add lots more tests
This commit is contained in:
parent
dd1df4631b
commit
76faab6363
3 changed files with 220 additions and 13 deletions
27
cache_test.go
Normal file
27
cache_test.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright 2014 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package imageproxy
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestNopCache(t *testing.T) {
|
||||||
|
data, ok := NopCache.Get("foo")
|
||||||
|
if data != nil {
|
||||||
|
t.Errorf("NopCache.Get returned non-nil data")
|
||||||
|
}
|
||||||
|
if ok != false {
|
||||||
|
t.Errorf("NopCache.Get returned ok = true, should always be false.")
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,34 +2,45 @@ package imageproxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/png"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAllowed(t *testing.T) {
|
func TestAllowed(t *testing.T) {
|
||||||
p := &Proxy{
|
whitelist := []string{"a.test", "*.b.test", "*c.test"}
|
||||||
Whitelist: []string{"a.test", "*.b.test", "*c.test"},
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
url string
|
url string
|
||||||
allowed bool
|
whitelist []string
|
||||||
|
allowed bool
|
||||||
}{
|
}{
|
||||||
{"http://a.test/image", true},
|
{"http://foo/image", nil, true},
|
||||||
{"http://x.a.test/image", false},
|
{"http://foo/image", []string{}, true},
|
||||||
|
|
||||||
{"http://b.test/image", true},
|
{"http://a.test/image", whitelist, true},
|
||||||
{"http://x.b.test/image", true},
|
{"http://x.a.test/image", whitelist, false},
|
||||||
{"http://x.y.b.test/image", true},
|
|
||||||
|
|
||||||
{"http://c.test/image", false},
|
{"http://b.test/image", whitelist, true},
|
||||||
{"http://xc.test/image", false},
|
{"http://x.b.test/image", whitelist, true},
|
||||||
{"/image", false},
|
{"http://x.y.b.test/image", whitelist, true},
|
||||||
|
|
||||||
|
{"http://c.test/image", whitelist, false},
|
||||||
|
{"http://xc.test/image", whitelist, false},
|
||||||
|
{"/image", whitelist, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
p := NewProxy(nil, nil)
|
||||||
|
p.Whitelist = tt.whitelist
|
||||||
|
|
||||||
u, err := url.Parse(tt.url)
|
u, err := url.Parse(tt.url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("error parsing url %q: %v", tt.url, err)
|
t.Errorf("error parsing url %q: %v", tt.url, err)
|
||||||
|
@ -112,3 +123,121 @@ func TestCheck304(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testTransport is an http.RoundTripper that returns certained canned
|
||||||
|
// responses for particular requests.
|
||||||
|
type testTransport struct{}
|
||||||
|
|
||||||
|
func (t testTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
var raw string
|
||||||
|
|
||||||
|
switch req.URL.Path {
|
||||||
|
case "/ok":
|
||||||
|
raw = "HTTP/1.1 200 OK\n\n"
|
||||||
|
case "/error":
|
||||||
|
return nil, errors.New("http protocol error")
|
||||||
|
case "/nocontent":
|
||||||
|
raw = "HTTP/1.1 204 No Content\n\n"
|
||||||
|
case "/etag":
|
||||||
|
raw = "HTTP/1.1 200 OK\nEtag: \"tag\"\n\n"
|
||||||
|
case "/png":
|
||||||
|
m := image.NewNRGBA(image.Rect(0, 0, 1, 1))
|
||||||
|
img := new(bytes.Buffer)
|
||||||
|
png.Encode(img, m)
|
||||||
|
|
||||||
|
raw = fmt.Sprintf("HTTP/1.1 200 OK\nContent-Length: %d\n\n%v", len(img.Bytes()), img.Bytes())
|
||||||
|
default:
|
||||||
|
raw = "HTTP/1.1 404 Not Found\n\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bufio.NewReader(bytes.NewBufferString(raw))
|
||||||
|
return http.ReadResponse(buf, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProxy_ServeHTTP(t *testing.T) {
|
||||||
|
p := &Proxy{
|
||||||
|
Client: &http.Client{
|
||||||
|
Transport: testTransport{},
|
||||||
|
},
|
||||||
|
Whitelist: []string{"good.test"},
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
url string // request URL
|
||||||
|
code int // expected response status code
|
||||||
|
}{
|
||||||
|
{"/favicon.ico", http.StatusOK},
|
||||||
|
{"//foo", http.StatusBadRequest}, // invalid request URL
|
||||||
|
{"/http://bad.test/", http.StatusBadRequest}, // Disallowed host
|
||||||
|
{"/http://good.test/error", http.StatusInternalServerError}, // HTTP protocol error
|
||||||
|
{"/http://good.test/nocontent", http.StatusNoContent}, // non-OK response
|
||||||
|
|
||||||
|
{"/100/http://good.test/ok", http.StatusOK},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
req, _ := http.NewRequest("GET", "http://localhost"+tt.url, nil)
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
p.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
if got, want := resp.Code, tt.code; got != want {
|
||||||
|
t.Errorf("ServeHTTP(%q) returned status %d, want %d", req, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test that 304 Not Modified responses are returned properly.
|
||||||
|
func TestProxy_ServeHTTP_is304(t *testing.T) {
|
||||||
|
p := &Proxy{
|
||||||
|
Client: &http.Client{
|
||||||
|
Transport: testTransport{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
req, _ := http.NewRequest("GET", "http://localhost/http://good.test/etag", nil)
|
||||||
|
req.Header.Add("If-None-Match", `"tag"`)
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
p.ServeHTTP(resp, req)
|
||||||
|
|
||||||
|
if got, want := resp.Code, http.StatusNotModified; got != want {
|
||||||
|
t.Errorf("ServeHTTP(%q) returned status %d, want %d", req, got, want)
|
||||||
|
}
|
||||||
|
if got, want := resp.Header().Get("Etag"), `"tag"`; got != want {
|
||||||
|
t.Errorf("ServeHTTP(%q) returned etag header %v, want %v", req, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTransformingTransport(t *testing.T) {
|
||||||
|
client := new(http.Client)
|
||||||
|
tr := &TransformingTransport{testTransport{}, client}
|
||||||
|
client.Transport = tr
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
url string
|
||||||
|
code int
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
{"http://good.test/png#1", http.StatusOK, false},
|
||||||
|
{"http://good.test/error#1", http.StatusInternalServerError, true},
|
||||||
|
// TODO: test more than just status code... verify that image
|
||||||
|
// is actually transformed and returned properly and that
|
||||||
|
// non-image responses are returned as-is
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
req, _ := http.NewRequest("GET", tt.url, nil)
|
||||||
|
|
||||||
|
resp, err := tr.RoundTrip(req)
|
||||||
|
if err != nil {
|
||||||
|
if !tt.expectError {
|
||||||
|
t.Errorf("RoundTrip(%v) returned unexpected error: %v", tt.url, err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
} else if tt.expectError {
|
||||||
|
t.Errorf("RoundTrip(%v) did not return expected error", tt.url)
|
||||||
|
}
|
||||||
|
if got, want := resp.StatusCode, tt.code; got != want {
|
||||||
|
t.Errorf("RoundTrip(%v) returned status code %d, want %d", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
package imageproxy
|
package imageproxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
|
"image/gif"
|
||||||
|
"image/jpeg"
|
||||||
|
"image/png"
|
||||||
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -32,6 +37,52 @@ func newImage(w, h int, pixels ...color.NRGBA) image.Image {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTransform(t *testing.T) {
|
||||||
|
src := newImage(2, 2, red, green, blue, yellow)
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
png.Encode(buf, src)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
encode func(io.Writer, image.Image)
|
||||||
|
exactOutput bool // whether input and output should match exactly
|
||||||
|
}{
|
||||||
|
{"gif", func(w io.Writer, m image.Image) { gif.Encode(w, m, nil) }, true},
|
||||||
|
{"jpeg", func(w io.Writer, m image.Image) { jpeg.Encode(w, m, nil) }, false},
|
||||||
|
{"png", func(w io.Writer, m image.Image) { png.Encode(w, m) }, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
tt.encode(buf, src)
|
||||||
|
in := buf.Bytes()
|
||||||
|
|
||||||
|
out, err := Transform(in, emptyOptions)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Transform with encoder %s returned unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(in, out) {
|
||||||
|
t.Errorf("Transform with with encoder %s with empty options returned modified result")
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err = Transform(in, Options{Width: -1, Height: -1})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Transform with encoder %s returned unexpected error: %v", tt.name, err)
|
||||||
|
}
|
||||||
|
if len(out) == 0 {
|
||||||
|
t.Errorf("Transform with encoder %s returned empty bytes", tt.name)
|
||||||
|
}
|
||||||
|
if tt.exactOutput && !reflect.DeepEqual(in, out) {
|
||||||
|
t.Errorf("Transform with encoder %s with noop Options returned modified result", tt.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := Transform([]byte{}, Options{Width: 1}); err == nil {
|
||||||
|
t.Errorf("Transform with invalid image input did not return expected err")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestTransformImage(t *testing.T) {
|
func TestTransformImage(t *testing.T) {
|
||||||
// ref is a 2x2 reference image containing four colors
|
// ref is a 2x2 reference image containing four colors
|
||||||
ref := newImage(2, 2, red, green, blue, yellow)
|
ref := newImage(2, 2, red, green, blue, yellow)
|
||||||
|
|
Loading…
Reference in a new issue