2017-10-06 00:08:03 +03:00
|
|
|
package awstesting
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"encoding/xml"
|
|
|
|
"fmt"
|
|
|
|
"net/url"
|
|
|
|
"reflect"
|
|
|
|
"regexp"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Match is a testing helper to test for testing error by comparing expected
|
|
|
|
// with a regular expression.
|
|
|
|
func Match(t *testing.T, regex, expected string) {
|
|
|
|
if !regexp.MustCompile(regex).Match([]byte(expected)) {
|
|
|
|
t.Errorf("%q\n\tdoes not match /%s/", expected, regex)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// AssertURL verifies the expected URL is matches the actual.
|
|
|
|
func AssertURL(t *testing.T, expect, actual string, msgAndArgs ...interface{}) bool {
|
|
|
|
expectURL, err := url.Parse(expect)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf(errMsg("unable to parse expected URL", err, msgAndArgs))
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
actualURL, err := url.Parse(actual)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf(errMsg("unable to parse actual URL", err, msgAndArgs))
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
equal(t, expectURL.Host, actualURL.Host, msgAndArgs...)
|
|
|
|
equal(t, expectURL.Scheme, actualURL.Scheme, msgAndArgs...)
|
|
|
|
equal(t, expectURL.Path, actualURL.Path, msgAndArgs...)
|
|
|
|
|
|
|
|
return AssertQuery(t, expectURL.Query().Encode(), actualURL.Query().Encode(), msgAndArgs...)
|
|
|
|
}
|
|
|
|
|
|
|
|
var queryMapKey = regexp.MustCompile("(.*?)\\.[0-9]+\\.key")
|
|
|
|
|
|
|
|
// AssertQuery verifies the expect HTTP query string matches the actual.
|
|
|
|
func AssertQuery(t *testing.T, expect, actual string, msgAndArgs ...interface{}) bool {
|
|
|
|
expectQ, err := url.ParseQuery(expect)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf(errMsg("unable to parse expected Query", err, msgAndArgs))
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
actualQ, err := url.ParseQuery(actual)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf(errMsg("unable to parse actual Query", err, msgAndArgs))
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure the keys are the same
|
|
|
|
if !equal(t, queryValueKeys(expectQ), queryValueKeys(actualQ), msgAndArgs...) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
keys := map[string][]string{}
|
|
|
|
for key, v := range expectQ {
|
|
|
|
if queryMapKey.Match([]byte(key)) {
|
|
|
|
submatch := queryMapKey.FindStringSubmatch(key)
|
|
|
|
keys[submatch[1]] = append(keys[submatch[1]], v...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for k, v := range keys {
|
|
|
|
// clear all keys that have prefix
|
|
|
|
for key := range expectQ {
|
|
|
|
if strings.HasPrefix(key, k) {
|
|
|
|
delete(expectQ, key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Strings(v)
|
|
|
|
for i, value := range v {
|
|
|
|
expectQ[fmt.Sprintf("%s.%d.key", k, i+1)] = []string{value}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for k, expectQVals := range expectQ {
|
|
|
|
sort.Strings(expectQVals)
|
|
|
|
actualQVals := actualQ[k]
|
|
|
|
sort.Strings(actualQVals)
|
|
|
|
if !equal(t, expectQVals, actualQVals, msgAndArgs...) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// AssertJSON verifies that the expect json string matches the actual.
|
|
|
|
func AssertJSON(t *testing.T, expect, actual string, msgAndArgs ...interface{}) bool {
|
|
|
|
expectVal := map[string]interface{}{}
|
|
|
|
if err := json.Unmarshal([]byte(expect), &expectVal); err != nil {
|
|
|
|
t.Errorf(errMsg("unable to parse expected JSON", err, msgAndArgs...))
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
actualVal := map[string]interface{}{}
|
|
|
|
if err := json.Unmarshal([]byte(actual), &actualVal); err != nil {
|
|
|
|
t.Errorf(errMsg("unable to parse actual JSON", err, msgAndArgs...))
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return equal(t, expectVal, actualVal, msgAndArgs...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AssertXML verifies that the expect xml string matches the actual.
|
|
|
|
func AssertXML(t *testing.T, expect, actual string, container interface{}, msgAndArgs ...interface{}) bool {
|
|
|
|
expectVal := container
|
|
|
|
if err := xml.Unmarshal([]byte(expect), &expectVal); err != nil {
|
|
|
|
t.Errorf(errMsg("unable to parse expected XML", err, msgAndArgs...))
|
|
|
|
}
|
|
|
|
|
|
|
|
actualVal := container
|
|
|
|
if err := xml.Unmarshal([]byte(actual), &actualVal); err != nil {
|
|
|
|
t.Errorf(errMsg("unable to parse actual XML", err, msgAndArgs...))
|
|
|
|
}
|
|
|
|
return equal(t, expectVal, actualVal, msgAndArgs...)
|
|
|
|
}
|
|
|
|
|
2017-10-06 01:31:53 +03:00
|
|
|
// DidPanic returns if the function paniced and returns true if the function paniced.
|
|
|
|
func DidPanic(fn func()) (bool, interface{}) {
|
|
|
|
var paniced bool
|
|
|
|
var msg interface{}
|
|
|
|
func() {
|
|
|
|
defer func() {
|
|
|
|
if msg = recover(); msg != nil {
|
|
|
|
paniced = true
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
fn()
|
|
|
|
}()
|
|
|
|
|
|
|
|
return paniced, msg
|
|
|
|
}
|
|
|
|
|
2017-10-06 00:08:03 +03:00
|
|
|
// objectsAreEqual determines if two objects are considered equal.
|
|
|
|
//
|
|
|
|
// This function does no assertion of any kind.
|
|
|
|
//
|
|
|
|
// Based on github.com/stretchr/testify/assert.ObjectsAreEqual
|
|
|
|
// Copied locally to prevent non-test build dependencies on testify
|
|
|
|
func objectsAreEqual(expected, actual interface{}) bool {
|
|
|
|
if expected == nil || actual == nil {
|
|
|
|
return expected == actual
|
|
|
|
}
|
|
|
|
|
|
|
|
return reflect.DeepEqual(expected, actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Equal asserts that two objects are equal.
|
|
|
|
//
|
|
|
|
// assert.Equal(t, 123, 123, "123 and 123 should be equal")
|
|
|
|
//
|
|
|
|
// Returns whether the assertion was successful (true) or not (false).
|
|
|
|
//
|
|
|
|
// Based on github.com/stretchr/testify/assert.Equal
|
|
|
|
// Copied locally to prevent non-test build dependencies on testify
|
|
|
|
func equal(t *testing.T, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
|
|
|
if !objectsAreEqual(expected, actual) {
|
|
|
|
t.Errorf("%s\n%s", messageFromMsgAndArgs(msgAndArgs),
|
|
|
|
SprintExpectActual(expected, actual))
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func errMsg(baseMsg string, err error, msgAndArgs ...interface{}) string {
|
|
|
|
message := messageFromMsgAndArgs(msgAndArgs)
|
|
|
|
if message != "" {
|
|
|
|
message += ", "
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("%s%s, %v", message, baseMsg, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Based on github.com/stretchr/testify/assert.messageFromMsgAndArgs
|
|
|
|
// Copied locally to prevent non-test build dependencies on testify
|
|
|
|
func messageFromMsgAndArgs(msgAndArgs []interface{}) string {
|
|
|
|
if len(msgAndArgs) == 0 || msgAndArgs == nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
if len(msgAndArgs) == 1 {
|
|
|
|
return msgAndArgs[0].(string)
|
|
|
|
}
|
|
|
|
if len(msgAndArgs) > 1 {
|
|
|
|
return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func queryValueKeys(v url.Values) []string {
|
|
|
|
keys := make([]string, 0, len(v))
|
|
|
|
for k := range v {
|
|
|
|
keys = append(keys, k)
|
|
|
|
}
|
|
|
|
sort.Strings(keys)
|
|
|
|
return keys
|
|
|
|
}
|
|
|
|
|
|
|
|
// SprintExpectActual returns a string for test failure cases when the actual
|
|
|
|
// value is not the same as the expected.
|
|
|
|
func SprintExpectActual(expect, actual interface{}) string {
|
|
|
|
return fmt.Sprintf("expect: %+v\nactual: %+v\n", expect, actual)
|
|
|
|
}
|