golang-client/testUtil/testUtil.go

164 lines
6.2 KiB
Go

// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
//
// 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 testUtil has helpers to be used with unit tests
package testUtil
import (
"errors"
"fmt"
"net/http"
"net/http/httptest"
"net/http/httputil"
"path/filepath"
"reflect"
"runtime"
"strings"
"testing"
)
// Equals fails the test if exp is not equal to act.
// Code was copied from https://github.com/benbjohnson/testing MIT license
func Equals(tb testing.TB, exp, act interface{}) {
if !reflect.DeepEqual(exp, act) {
_, file, line, _ := runtime.Caller(1)
fmt.Printf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n", filepath.Base(file), line, exp, act)
tb.FailNow()
}
}
// Assert fails the test if the condition is false.
// Code was copied from https://github.com/benbjohnson/testing MIT license
func Assert(tb testing.TB, condition bool, msg string, v ...interface{}) {
if !condition {
_, file, line, _ := runtime.Caller(1)
fmt.Printf("\033[31m%s:%d: "+msg+"\033[39m\n\n", append([]interface{}{filepath.Base(file), line}, v...)...)
tb.FailNow()
}
}
// IsNil ensures that the act interface is nil
// otherwise an error is raised.
func IsNil(tb testing.TB, act interface{}) {
if act != nil {
tb.Error("expected nil", act)
tb.FailNow()
}
}
// CreateGetJSONTestServer creates a httptest.Server that can be used to test
// JSON Get requests. Takes a token, JSON payload, and a verification function
// to do additional validation
func CreateGetJsonTestServer(
t *testing.T,
expectedAuthToken string,
jsonResponsePayload string,
verifyRequest func(*http.Request)) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
headerValuesEqual(t, r, "X-Auth-Token", expectedAuthToken)
headerValuesEqual(t, r, "Accept", "application/json")
// verifyRequest(r)
if r.Method == "GET" {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(jsonResponsePayload))
w.WriteHeader(http.StatusOK)
return
}
t.Error(errors.New("Failed: r.Method == GET"))
}))
}
// CreateGetJSONTestRequestServer creates a httptest.Server that can be used to test GetJson requests. Just specify the token,
// json payload that is to be read by the response, and a verification func that can be used
// to do additional validation of the request that is built
func CreateGetJSONTestRequestServer(t *testing.T, expectedAuthTokenValue string, jsonResponsePayload string, verifyRequest func(*http.Request)) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
headerValuesEqual(t, r, "X-Auth-Token", expectedAuthTokenValue)
headerValuesEqual(t, r, "Accept", "application/json")
verifyRequest(r)
if r.Method == "GET" {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(jsonResponsePayload))
w.WriteHeader(http.StatusOK)
return
}
t.Error(errors.New("Failed: r.Method == GET"))
}))
}
// CreatePostJSONTestRequestServer creates a http.Server that can be used to test PostJson requests. Specify the token,
// response json payload and the url and request body that is expected.
func CreatePostJSONTestRequestServer(t *testing.T, expectedAuthTokenValue string, outputResponseJSONPayload string, expectedRequestURLEndsWith string, expectedRequestBody string) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
headerValuesEqual(t, r, "X-Auth-Token", expectedAuthTokenValue)
headerValuesEqual(t, r, "Accept", "application/json")
headerValuesEqual(t, r, "Content-Type", "application/json")
reqURL := r.URL.String()
if !strings.HasSuffix(reqURL, expectedRequestURLEndsWith) {
t.Error(errors.New("Incorrect url created, expected:" + expectedRequestURLEndsWith + " at the end, actual url:" + reqURL))
}
actualRequestBody := dumpRequestBody(r)
if actualRequestBody != expectedRequestBody {
t.Error(errors.New("Incorrect payload created, expected:'" + expectedRequestBody + "', actual '" + actualRequestBody + "'"))
}
if r.Method == "POST" {
w.Header().Set("Content-Type", "application/json")
// Status Code has to be written before writing the payload or
// else it defaults to 200 OK instead.
w.WriteHeader(http.StatusCreated)
w.Write([]byte(outputResponseJSONPayload))
return
}
t.Error(errors.New("Failed: r.Method == POST"))
}))
}
// CreateDeleteTestRequestServer creates a http.Server that can be used to test Delete requests.
func CreateDeleteTestRequestServer(t *testing.T, expectedAuthTokenValue string, urlEndsWith string) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
headerValuesEqual(t, r, "X-Auth-Token", expectedAuthTokenValue)
reqURL := r.URL.String()
if !strings.HasSuffix(reqURL, urlEndsWith) {
t.Error(errors.New("Incorrect url created, expected '" + urlEndsWith + "' at the end, actual url:" + reqURL))
}
if r.Method == "DELETE" {
w.WriteHeader(204)
return
}
t.Error(errors.New("Failed: r.Method == DELETE"))
}))
}
func dumpRequestBody(request *http.Request) (body string) {
requestWithBody, _ := httputil.DumpRequest(request, true)
requestWithoutBody, _ := httputil.DumpRequest(request, false)
body = strings.Replace(string(requestWithBody), string(requestWithoutBody), "", 1)
return
}
func headerValuesEqual(t *testing.T, req *http.Request, name string, expectedValue string) {
actualValue := req.Header.Get(name)
if actualValue != expectedValue {
t.Error(fmt.Errorf("Expected Header {Name:'%s', Value:'%s', actual value '%s'", name, expectedValue, actualValue))
}
}