Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
add lots more tests
  • Loading branch information
willnorris committed Dec 5, 2014
1 parent dd1df46 commit 76faab6
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 13 deletions.
27 changes: 27 additions & 0 deletions cache_test.go
@@ -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.")
}
}
155 changes: 142 additions & 13 deletions imageproxy_test.go
Expand Up @@ -2,34 +2,45 @@ package imageproxy

import (
"bufio"
"bytes"
"errors"
"fmt"
"image"
"image/png"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
)

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 {
url string
allowed bool
url string
whitelist []string
allowed bool
}{
{"http://a.test/image", true},
{"http://x.a.test/image", false},
{"http://foo/image", nil, true},
{"http://foo/image", []string{}, true},

{"http://a.test/image", whitelist, true},
{"http://x.a.test/image", whitelist, false},

{"http://b.test/image", true},
{"http://x.b.test/image", true},
{"http://x.y.b.test/image", true},
{"http://b.test/image", whitelist, true},
{"http://x.b.test/image", whitelist, true},
{"http://x.y.b.test/image", whitelist, true},

{"http://c.test/image", false},
{"http://xc.test/image", false},
{"/image", false},
{"http://c.test/image", whitelist, false},
{"http://xc.test/image", whitelist, false},
{"/image", whitelist, false},
}

for _, tt := range tests {
p := NewProxy(nil, nil)
p.Whitelist = tt.whitelist

u, err := url.Parse(tt.url)
if err != nil {
t.Errorf("error parsing url %q: %v", tt.url, err)
Expand Down Expand Up @@ -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)
}
}
}
51 changes: 51 additions & 0 deletions transform_test.go
@@ -1,9 +1,14 @@
package imageproxy

import (
"bytes"
"image"
"image/color"
"image/draw"
"image/gif"
"image/jpeg"
"image/png"
"io"
"reflect"
"testing"

Expand Down Expand Up @@ -32,6 +37,52 @@ func newImage(w, h int, pixels ...color.NRGBA) image.Image {
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) {
// ref is a 2x2 reference image containing four colors
ref := newImage(2, 2, red, green, blue, yellow)
Expand Down

0 comments on commit 76faab6

Please sign in to comment.