update testify to latest released version
Signed-off-by: Steve Kriss <steve@heptio.com>pull/709/head
parent
0d2efaf991
commit
8789ae5cb1
|
@ -376,20 +376,20 @@
|
|||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/stretchr/objx"
|
||||
packages = ["."]
|
||||
revision = "1a9d0bb9f541897e62256577b352fdbc1fb4fd94"
|
||||
revision = "477a77ecc69700c7cdeb1fa9e129548e1c1c393c"
|
||||
version = "v0.1.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = [
|
||||
"assert",
|
||||
"mock",
|
||||
"require"
|
||||
]
|
||||
revision = "890a5c3458b43e6104ff5da8dfa139d013d77544"
|
||||
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
|
||||
version = "v1.2.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -806,6 +806,6 @@
|
|||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "529e7447c73a91dd886d9bf8ea5a522ca3795067a0aa7a61de70e433ea1747d0"
|
||||
inputs-digest = "70b3cfc235408d89934ada479417194e2a82df523f459f7d9d3264538805ea98"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
|
||||
[[constraint]]
|
||||
name = "github.com/stretchr/testify"
|
||||
branch = "master"
|
||||
version = "~1.2.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/hashicorp/go-plugin"
|
||||
|
|
5
vendor/github.com/stretchr/objx/LICENSE.md → vendor/github.com/stretchr/objx/LICENSE
generated
vendored
5
vendor/github.com/stretchr/objx/LICENSE.md → vendor/github.com/stretchr/objx/LICENSE
generated
vendored
|
@ -1,8 +1,7 @@
|
|||
objx - by Mat Ryer and Tyler Bunnell
|
||||
|
||||
The MIT License (MIT)
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2014 Stretchr, Inc.
|
||||
Copyright (c) 2017-2018 objx contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
|
@ -1,7 +1,6 @@
|
|||
package objx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -28,7 +27,7 @@ var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString)
|
|||
//
|
||||
// o.Get("books[1].chapters[2].title")
|
||||
func (m Map) Get(selector string) *Value {
|
||||
rawObj := access(m, selector, nil, false, false)
|
||||
rawObj := access(m, selector, nil, false)
|
||||
return &Value{data: rawObj}
|
||||
}
|
||||
|
||||
|
@ -43,47 +42,34 @@ func (m Map) Get(selector string) *Value {
|
|||
//
|
||||
// o.Set("books[1].chapters[2].title","Time to Go")
|
||||
func (m Map) Set(selector string, value interface{}) Map {
|
||||
access(m, selector, value, true, false)
|
||||
access(m, selector, value, true)
|
||||
return m
|
||||
}
|
||||
|
||||
// access accesses the object using the selector and performs the
|
||||
// appropriate action.
|
||||
func access(current, selector, value interface{}, isSet, panics bool) interface{} {
|
||||
|
||||
func access(current, selector, value interface{}, isSet bool) interface{} {
|
||||
switch selector.(type) {
|
||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
||||
|
||||
if array, ok := current.([]interface{}); ok {
|
||||
index := intFromInterface(selector)
|
||||
|
||||
if index >= len(array) {
|
||||
if panics {
|
||||
panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return array[index]
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
case string:
|
||||
|
||||
selStr := selector.(string)
|
||||
selSegs := strings.SplitN(selStr, PathSeparator, 2)
|
||||
thisSel := selSegs[0]
|
||||
index := -1
|
||||
var err error
|
||||
|
||||
// https://github.com/stretchr/objx/issues/12
|
||||
if strings.Contains(thisSel, "[") {
|
||||
|
||||
arrayMatches := arrayAccesRegex.FindStringSubmatch(thisSel)
|
||||
|
||||
if len(arrayMatches) > 0 {
|
||||
|
||||
// Get the key into the map
|
||||
thisSel = arrayMatches[1]
|
||||
|
||||
|
@ -95,14 +81,11 @@ func access(current, selector, value interface{}, isSet, panics bool) interface{
|
|||
// seriously wrong. Panic.
|
||||
panic("objx: Array index is not an integer. Must use array[int].")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if curMap, ok := current.(Map); ok {
|
||||
current = map[string]interface{}(curMap)
|
||||
}
|
||||
|
||||
// get the object in question
|
||||
switch current.(type) {
|
||||
case map[string]interface{}:
|
||||
|
@ -110,39 +93,26 @@ func access(current, selector, value interface{}, isSet, panics bool) interface{
|
|||
if len(selSegs) <= 1 && isSet {
|
||||
curMSI[thisSel] = value
|
||||
return nil
|
||||
} else {
|
||||
current = curMSI[thisSel]
|
||||
}
|
||||
current = curMSI[thisSel]
|
||||
default:
|
||||
current = nil
|
||||
}
|
||||
|
||||
if current == nil && panics {
|
||||
panic(fmt.Sprintf("objx: '%v' invalid on object.", selector))
|
||||
}
|
||||
|
||||
// do we need to access the item of an array?
|
||||
if index > -1 {
|
||||
if array, ok := current.([]interface{}); ok {
|
||||
if index < len(array) {
|
||||
current = array[index]
|
||||
} else {
|
||||
if panics {
|
||||
panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array)))
|
||||
}
|
||||
current = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(selSegs) > 1 {
|
||||
current = access(current, selSegs[1], value, isSet, panics)
|
||||
current = access(current, selSegs[1], value, isSet)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return current
|
||||
|
||||
}
|
||||
|
||||
// intFromInterface converts an interface object to the largest
|
||||
|
@ -172,8 +142,7 @@ func intFromInterface(selector interface{}) int {
|
|||
case uint64:
|
||||
value = int(selector.(uint64))
|
||||
default:
|
||||
panic("objx: array access argument is not an integer type (this should never happen)")
|
||||
return 0
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
|
|
@ -12,15 +12,11 @@ import (
|
|||
// JSON converts the contained object to a JSON string
|
||||
// representation
|
||||
func (m Map) JSON() (string, error) {
|
||||
|
||||
result, err := json.Marshal(m)
|
||||
|
||||
if err != nil {
|
||||
err = errors.New("objx: JSON encode failed with: " + err.Error())
|
||||
}
|
||||
|
||||
return string(result), err
|
||||
|
||||
}
|
||||
|
||||
// MustJSON converts the contained object to a JSON string
|
||||
|
@ -36,7 +32,6 @@ func (m Map) MustJSON() string {
|
|||
// Base64 converts the contained object to a Base64 string
|
||||
// representation of the JSON string representation
|
||||
func (m Map) Base64() (string, error) {
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
jsonData, err := m.JSON()
|
||||
|
@ -45,11 +40,13 @@ func (m Map) Base64() (string, error) {
|
|||
}
|
||||
|
||||
encoder := base64.NewEncoder(base64.StdEncoding, &buf)
|
||||
encoder.Write([]byte(jsonData))
|
||||
encoder.Close()
|
||||
_, err = encoder.Write([]byte(jsonData))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_ = encoder.Close()
|
||||
|
||||
return buf.String(), nil
|
||||
|
||||
}
|
||||
|
||||
// MustBase64 converts the contained object to a Base64 string
|
||||
|
@ -67,16 +64,13 @@ func (m Map) MustBase64() string {
|
|||
// representation of the JSON string representation and signs it
|
||||
// using the provided key.
|
||||
func (m Map) SignedBase64(key string) (string, error) {
|
||||
|
||||
base64, err := m.Base64()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
sig := HashWithKey(base64, key)
|
||||
|
||||
return base64 + SignatureSeparator + sig, nil
|
||||
|
||||
}
|
||||
|
||||
// MustSignedBase64 converts the contained object to a Base64 string
|
||||
|
@ -98,14 +92,11 @@ func (m Map) MustSignedBase64(key string) string {
|
|||
// URLValues creates a url.Values object from an Obj. This
|
||||
// function requires that the wrapped object be a map[string]interface{}
|
||||
func (m Map) URLValues() url.Values {
|
||||
|
||||
vals := make(url.Values)
|
||||
|
||||
for k, v := range m {
|
||||
//TODO: can this be done without sprintf?
|
||||
vals.Set(k, fmt.Sprintf("%v", v))
|
||||
}
|
||||
|
||||
return vals
|
||||
}
|
||||
|
||||
|
|
|
@ -1,72 +1,66 @@
|
|||
// objx - Go package for dealing with maps, slices, JSON and other data.
|
||||
//
|
||||
// Overview
|
||||
//
|
||||
// Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes
|
||||
// a powerful `Get` method (among others) that allows you to easily and quickly get
|
||||
// access to data within the map, without having to worry too much about type assertions,
|
||||
// missing data, default values etc.
|
||||
//
|
||||
// Pattern
|
||||
//
|
||||
// Objx uses a preditable pattern to make access data from within `map[string]interface{}'s
|
||||
// easy.
|
||||
//
|
||||
// Call one of the `objx.` functions to create your `objx.Map` to get going:
|
||||
//
|
||||
// m, err := objx.FromJSON(json)
|
||||
//
|
||||
// NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong,
|
||||
// the rest will be optimistic and try to figure things out without panicking.
|
||||
//
|
||||
// Use `Get` to access the value you're interested in. You can use dot and array
|
||||
// notation too:
|
||||
//
|
||||
// m.Get("places[0].latlng")
|
||||
//
|
||||
// Once you have saught the `Value` you're interested in, you can use the `Is*` methods
|
||||
// to determine its type.
|
||||
//
|
||||
// if m.Get("code").IsStr() { /* ... */ }
|
||||
//
|
||||
// Or you can just assume the type, and use one of the strong type methods to
|
||||
// extract the real value:
|
||||
//
|
||||
// m.Get("code").Int()
|
||||
//
|
||||
// If there's no value there (or if it's the wrong type) then a default value
|
||||
// will be returned, or you can be explicit about the default value.
|
||||
//
|
||||
// Get("code").Int(-1)
|
||||
//
|
||||
// If you're dealing with a slice of data as a value, Objx provides many useful
|
||||
// methods for iterating, manipulating and selecting that data. You can find out more
|
||||
// by exploring the index below.
|
||||
//
|
||||
// Reading data
|
||||
//
|
||||
// A simple example of how to use Objx:
|
||||
//
|
||||
// // use MustFromJSON to make an objx.Map from some JSON
|
||||
// m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`)
|
||||
//
|
||||
// // get the details
|
||||
// name := m.Get("name").Str()
|
||||
// age := m.Get("age").Int()
|
||||
//
|
||||
// // get their nickname (or use their name if they
|
||||
// // don't have one)
|
||||
// nickname := m.Get("nickname").Str(name)
|
||||
//
|
||||
// Ranging
|
||||
//
|
||||
// Since `objx.Map` is a `map[string]interface{}` you can treat it as such. For
|
||||
// example, to `range` the data, do what you would expect:
|
||||
//
|
||||
// m := objx.MustFromJSON(json)
|
||||
// for key, value := range m {
|
||||
//
|
||||
// /* ... do your magic ... */
|
||||
//
|
||||
// }
|
||||
/*
|
||||
Objx - Go package for dealing with maps, slices, JSON and other data.
|
||||
|
||||
Overview
|
||||
|
||||
Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes
|
||||
a powerful `Get` method (among others) that allows you to easily and quickly get
|
||||
access to data within the map, without having to worry too much about type assertions,
|
||||
missing data, default values etc.
|
||||
|
||||
Pattern
|
||||
|
||||
Objx uses a preditable pattern to make access data from within `map[string]interface{}` easy.
|
||||
Call one of the `objx.` functions to create your `objx.Map` to get going:
|
||||
|
||||
m, err := objx.FromJSON(json)
|
||||
|
||||
NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong,
|
||||
the rest will be optimistic and try to figure things out without panicking.
|
||||
|
||||
Use `Get` to access the value you're interested in. You can use dot and array
|
||||
notation too:
|
||||
|
||||
m.Get("places[0].latlng")
|
||||
|
||||
Once you have sought the `Value` you're interested in, you can use the `Is*` methods to determine its type.
|
||||
|
||||
if m.Get("code").IsStr() { // Your code... }
|
||||
|
||||
Or you can just assume the type, and use one of the strong type methods to extract the real value:
|
||||
|
||||
m.Get("code").Int()
|
||||
|
||||
If there's no value there (or if it's the wrong type) then a default value will be returned,
|
||||
or you can be explicit about the default value.
|
||||
|
||||
Get("code").Int(-1)
|
||||
|
||||
If you're dealing with a slice of data as a value, Objx provides many useful methods for iterating,
|
||||
manipulating and selecting that data. You can find out more by exploring the index below.
|
||||
|
||||
Reading data
|
||||
|
||||
A simple example of how to use Objx:
|
||||
|
||||
// Use MustFromJSON to make an objx.Map from some JSON
|
||||
m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`)
|
||||
|
||||
// Get the details
|
||||
name := m.Get("name").Str()
|
||||
age := m.Get("age").Int()
|
||||
|
||||
// Get their nickname (or use their name if they don't have one)
|
||||
nickname := m.Get("nickname").Str(name)
|
||||
|
||||
Ranging
|
||||
|
||||
Since `objx.Map` is a `map[string]interface{}` you can treat it as such.
|
||||
For example, to `range` the data, do what you would expect:
|
||||
|
||||
m := objx.MustFromJSON(json)
|
||||
for key, value := range m {
|
||||
// Your code...
|
||||
}
|
||||
*/
|
||||
package objx
|
||||
|
|
|
@ -27,7 +27,7 @@ func (m Map) Value() *Value {
|
|||
}
|
||||
|
||||
// Nil represents a nil Map.
|
||||
var Nil Map = New(nil)
|
||||
var Nil = New(nil)
|
||||
|
||||
// New creates a new Map containing the map[string]interface{} in the data argument.
|
||||
// If the data argument is not a map[string]interface, New attempts to call the
|
||||
|
@ -47,9 +47,8 @@ func New(data interface{}) Map {
|
|||
//
|
||||
// The arguments follow a key, value pattern.
|
||||
//
|
||||
// Panics
|
||||
//
|
||||
// Panics if any key arugment is non-string or if there are an odd number of arguments.
|
||||
// Returns nil if any key argument is non-string or if there are an odd number of arguments.
|
||||
//
|
||||
// Example
|
||||
//
|
||||
|
@ -58,32 +57,25 @@ func New(data interface{}) Map {
|
|||
// m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true))
|
||||
//
|
||||
// // creates an Map equivalent to
|
||||
// m := objx.New(map[string]interface{}{"name": "Mat", "age": 29, "subobj": map[string]interface{}{"active": true}})
|
||||
// m := objx.Map{"name": "Mat", "age": 29, "subobj": objx.Map{"active": true}}
|
||||
func MSI(keyAndValuePairs ...interface{}) Map {
|
||||
|
||||
newMap := make(map[string]interface{})
|
||||
newMap := Map{}
|
||||
keyAndValuePairsLen := len(keyAndValuePairs)
|
||||
|
||||
if keyAndValuePairsLen%2 != 0 {
|
||||
panic("objx: MSI must have an even number of arguments following the 'key, value' pattern.")
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < keyAndValuePairsLen; i = i + 2 {
|
||||
|
||||
key := keyAndValuePairs[i]
|
||||
value := keyAndValuePairs[i+1]
|
||||
|
||||
// make sure the key is a string
|
||||
keyString, keyStringOK := key.(string)
|
||||
if !keyStringOK {
|
||||
panic("objx: MSI must follow 'string, interface{}' pattern. " + keyString + " is not a valid key.")
|
||||
return nil
|
||||
}
|
||||
|
||||
newMap[keyString] = value
|
||||
|
||||
}
|
||||
|
||||
return New(newMap)
|
||||
return newMap
|
||||
}
|
||||
|
||||
// ****** Conversion Constructors
|
||||
|
@ -94,11 +86,9 @@ func MSI(keyAndValuePairs ...interface{}) Map {
|
|||
// Panics if the JSON is invalid.
|
||||
func MustFromJSON(jsonString string) Map {
|
||||
o, err := FromJSON(jsonString)
|
||||
|
||||
if err != nil {
|
||||
panic("objx: MustFromJSON failed with error: " + err.Error())
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
|
@ -107,16 +97,12 @@ func MustFromJSON(jsonString string) Map {
|
|||
//
|
||||
// Returns an error if the JSON is invalid.
|
||||
func FromJSON(jsonString string) (Map, error) {
|
||||
|
||||
var data interface{}
|
||||
err := json.Unmarshal([]byte(jsonString), &data)
|
||||
|
||||
if err != nil {
|
||||
return Nil, err
|
||||
}
|
||||
|
||||
return New(data), nil
|
||||
|
||||
}
|
||||
|
||||
// FromBase64 creates a new Obj containing the data specified
|
||||
|
@ -124,14 +110,11 @@ func FromJSON(jsonString string) (Map, error) {
|
|||
//
|
||||
// The string is an encoded JSON string returned by Base64
|
||||
func FromBase64(base64String string) (Map, error) {
|
||||
|
||||
decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64String))
|
||||
|
||||
decoded, err := ioutil.ReadAll(decoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return FromJSON(string(decoded))
|
||||
}
|
||||
|
||||
|
@ -140,13 +123,10 @@ func FromBase64(base64String string) (Map, error) {
|
|||
//
|
||||
// The string is an encoded JSON string returned by Base64
|
||||
func MustFromBase64(base64String string) Map {
|
||||
|
||||
result, err := FromBase64(base64String)
|
||||
|
||||
if err != nil {
|
||||
panic("objx: MustFromBase64 failed with error: " + err.Error())
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -157,14 +137,13 @@ func MustFromBase64(base64String string) Map {
|
|||
func FromSignedBase64(base64String, key string) (Map, error) {
|
||||
parts := strings.Split(base64String, SignatureSeparator)
|
||||
if len(parts) != 2 {
|
||||
return nil, errors.New("objx: Signed base64 string is malformed.")
|
||||
return nil, errors.New("objx: Signed base64 string is malformed")
|
||||
}
|
||||
|
||||
sig := HashWithKey(parts[0], key)
|
||||
if parts[1] != sig {
|
||||
return nil, errors.New("objx: Signature for base64 data does not match.")
|
||||
return nil, errors.New("objx: Signature for base64 data does not match")
|
||||
}
|
||||
|
||||
return FromBase64(parts[0])
|
||||
}
|
||||
|
||||
|
@ -173,13 +152,10 @@ func FromSignedBase64(base64String, key string) (Map, error) {
|
|||
//
|
||||
// The string is an encoded JSON string returned by Base64
|
||||
func MustFromSignedBase64(base64String, key string) Map {
|
||||
|
||||
result, err := FromSignedBase64(base64String, key)
|
||||
|
||||
if err != nil {
|
||||
panic("objx: MustFromSignedBase64 failed with error: " + err.Error())
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -188,19 +164,15 @@ func MustFromSignedBase64(base64String, key string) Map {
|
|||
//
|
||||
// For queries with multiple values, the first value is selected.
|
||||
func FromURLQuery(query string) (Map, error) {
|
||||
|
||||
vals, err := url.ParseQuery(query)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := make(map[string]interface{})
|
||||
m := Map{}
|
||||
for k, vals := range vals {
|
||||
m[k] = vals[0]
|
||||
}
|
||||
|
||||
return New(m), nil
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// MustFromURLQuery generates a new Obj by parsing the specified
|
||||
|
@ -210,13 +182,9 @@ func FromURLQuery(query string) (Map, error) {
|
|||
//
|
||||
// Panics if it encounters an error
|
||||
func MustFromURLQuery(query string) Map {
|
||||
|
||||
o, err := FromURLQuery(query)
|
||||
|
||||
if err != nil {
|
||||
panic("objx: MustFromURLQuery failed with error: " + err.Error())
|
||||
}
|
||||
|
||||
return o
|
||||
|
||||
}
|
||||
|
|
|
@ -2,32 +2,23 @@ package objx
|
|||
|
||||
// Exclude returns a new Map with the keys in the specified []string
|
||||
// excluded.
|
||||
func (d Map) Exclude(exclude []string) Map {
|
||||
|
||||
func (m Map) Exclude(exclude []string) Map {
|
||||
excluded := make(Map)
|
||||
for k, v := range d {
|
||||
var shouldInclude bool = true
|
||||
for _, toExclude := range exclude {
|
||||
if k == toExclude {
|
||||
shouldInclude = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if shouldInclude {
|
||||
for k, v := range m {
|
||||
if !contains(exclude, k) {
|
||||
excluded[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return excluded
|
||||
}
|
||||
|
||||
// Copy creates a shallow copy of the Obj.
|
||||
func (m Map) Copy() Map {
|
||||
copied := make(map[string]interface{})
|
||||
copied := Map{}
|
||||
for k, v := range m {
|
||||
copied[k] = v
|
||||
}
|
||||
return New(copied)
|
||||
return copied
|
||||
}
|
||||
|
||||
// Merge blends the specified map with a copy of this map and returns the result.
|
||||
|
@ -38,31 +29,28 @@ func (m Map) Merge(merge Map) Map {
|
|||
return m.Copy().MergeHere(merge)
|
||||
}
|
||||
|
||||
// Merge blends the specified map with this map and returns the current map.
|
||||
// MergeHere blends the specified map with this map and returns the current map.
|
||||
//
|
||||
// Keys that appear in both will be selected from the specified map. The original map
|
||||
// Keys that appear in both will be selected from the specified map. The original map
|
||||
// will be modified. This method requires that
|
||||
// the wrapped object be a map[string]interface{}
|
||||
func (m Map) MergeHere(merge Map) Map {
|
||||
|
||||
for k, v := range merge {
|
||||
m[k] = v
|
||||
}
|
||||
|
||||
return m
|
||||
|
||||
}
|
||||
|
||||
// Transform builds a new Obj giving the transformer a chance
|
||||
// to change the keys and values as it goes. This method requires that
|
||||
// the wrapped object be a map[string]interface{}
|
||||
func (m Map) Transform(transformer func(key string, value interface{}) (string, interface{})) Map {
|
||||
newMap := make(map[string]interface{})
|
||||
newMap := Map{}
|
||||
for k, v := range m {
|
||||
modifiedKey, modifiedVal := transformer(k, v)
|
||||
newMap[modifiedKey] = modifiedVal
|
||||
}
|
||||
return New(newMap)
|
||||
return newMap
|
||||
}
|
||||
|
||||
// TransformKeys builds a new map using the specified key mapping.
|
||||
|
@ -71,11 +59,19 @@ func (m Map) Transform(transformer func(key string, value interface{}) (string,
|
|||
// This method requires that the wrapped object be a map[string]interface{}
|
||||
func (m Map) TransformKeys(mapping map[string]string) Map {
|
||||
return m.Transform(func(key string, value interface{}) (string, interface{}) {
|
||||
|
||||
if newKey, ok := mapping[key]; ok {
|
||||
return newKey, value
|
||||
}
|
||||
|
||||
return key, value
|
||||
})
|
||||
}
|
||||
|
||||
// Checks if a string slice contains a string
|
||||
func contains(s []string, e string) bool {
|
||||
for _, a := range s {
|
||||
if a == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -5,10 +5,8 @@ import (
|
|||
"encoding/hex"
|
||||
)
|
||||
|
||||
// HashWithKey hashes the specified string using the security
|
||||
// key.
|
||||
// HashWithKey hashes the specified string using the security key
|
||||
func HashWithKey(data, key string) string {
|
||||
hash := sha1.New()
|
||||
hash.Write([]byte(data + ":" + key))
|
||||
return hex.EncodeToString(hash.Sum(nil))
|
||||
d := sha1.Sum([]byte(data + ":" + key))
|
||||
return hex.EncodeToString(d[:])
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,8 +30,6 @@ func (v *Value) String() string {
|
|||
return strconv.FormatFloat(v.Float64(), 'f', -1, 64)
|
||||
case v.IsInt():
|
||||
return strconv.FormatInt(int64(v.Int()), 10)
|
||||
case v.IsInt():
|
||||
return strconv.FormatInt(int64(v.Int()), 10)
|
||||
case v.IsInt8():
|
||||
return strconv.FormatInt(int64(v.Int8()), 10)
|
||||
case v.IsInt16():
|
||||
|
@ -51,6 +49,5 @@ func (v *Value) String() string {
|
|||
case v.IsUint64():
|
||||
return strconv.FormatUint(v.Uint64(), 10)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%#v", v.Data())
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell
|
||||
|
||||
Please consider promoting this project if you find it useful.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
|
||||
OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -13,6 +13,9 @@ import (
|
|||
|
||||
// Conditionf uses a Comparison to assert a complex condition.
|
||||
func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Condition(t, comp, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -22,19 +25,41 @@ func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bo
|
|||
// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
|
||||
// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
|
||||
// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Contains(t, s, contains, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return DirExists(t, path, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
|
||||
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||
// the number of appearances of each of them in both lists should match.
|
||||
//
|
||||
// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
|
||||
func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
|
||||
// a slice or a channel with len == 0.
|
||||
//
|
||||
// assert.Emptyf(t, obj, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Empty(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -42,12 +67,13 @@ func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) boo
|
|||
//
|
||||
// assert.Equalf(t, 123, 123, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Equal(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -56,9 +82,10 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar
|
|||
//
|
||||
// actualObj, err := SomeFunction()
|
||||
// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -66,9 +93,10 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args
|
|||
// and equal.
|
||||
//
|
||||
// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -78,58 +106,81 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri
|
|||
// if assert.Errorf(t, err, "error message %s", "formatted") {
|
||||
// assert.Equal(t, expectedErrorf, err)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Error(t, err, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Exactlyf asserts that two objects are equal is value and type.
|
||||
// Exactlyf asserts that two objects are equal in value and type.
|
||||
//
|
||||
// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Failf reports a failure through
|
||||
func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Fail(t, failureMessage, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// FailNowf fails test
|
||||
func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Falsef asserts that the specified value is false.
|
||||
//
|
||||
// assert.Falsef(t, myBool, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return False(t, value, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return FileExists(t, path, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// HTTPBodyContainsf asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
|
||||
return HTTPBodyContains(t, handler, method, url, values, str)
|
||||
func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// HTTPBodyNotContainsf asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
|
||||
return HTTPBodyNotContains(t, handler, method, url, values, str)
|
||||
func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// HTTPErrorf asserts that a specified handler returns an error status code.
|
||||
|
@ -137,8 +188,11 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u
|
|||
// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||
return HTTPError(t, handler, method, url, values)
|
||||
func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// HTTPRedirectf asserts that a specified handler returns a redirect status code.
|
||||
|
@ -146,8 +200,11 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string,
|
|||
// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||
//
|
||||
// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
|
||||
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||
return HTTPRedirect(t, handler, method, url, values)
|
||||
func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// HTTPSuccessf asserts that a specified handler returns a success status code.
|
||||
|
@ -155,54 +212,80 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri
|
|||
// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||
return HTTPSuccess(t, handler, method, url, values)
|
||||
func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Implementsf asserts that an object is implemented by the specified interface.
|
||||
//
|
||||
// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
|
||||
func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InDeltaf asserts that the two numerals are within delta of each other.
|
||||
//
|
||||
// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InDeltaSlicef is the same as InDelta, except it compares two slices.
|
||||
func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InEpsilonf asserts that expected and actual have a relative error less than epsilon
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
|
||||
func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// IsTypef asserts that the specified objects are of the same type.
|
||||
func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// JSONEqf asserts that two JSON strings are equivalent.
|
||||
//
|
||||
// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -210,18 +293,20 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int
|
|||
// Lenf also fails if the object has a type that len() not accept.
|
||||
//
|
||||
// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Len(t, object, length, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Nilf asserts that the specified object is nil.
|
||||
//
|
||||
// assert.Nilf(t, err, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Nil(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -231,9 +316,10 @@ func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool
|
|||
// if assert.NoErrorf(t, err, "error message %s", "formatted") {
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NoError(t, err, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -243,9 +329,10 @@ func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
|||
// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
|
||||
// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
|
||||
// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -255,9 +342,10 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a
|
|||
// if assert.NotEmptyf(t, obj, "error message %s", "formatted") {
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEmpty(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -265,29 +353,32 @@ func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{})
|
|||
//
|
||||
// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotNilf asserts that the specified object is not nil.
|
||||
//
|
||||
// assert.NotNilf(t, err, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotNil(t, object, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||
//
|
||||
// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotPanics(t, f, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -295,9 +386,10 @@ func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bo
|
|||
//
|
||||
// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
|
||||
// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -305,23 +397,28 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ..
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// NotZerof asserts that i is not the zero value for its type and returns the truth.
|
||||
// NotZerof asserts that i is not the zero value for its type.
|
||||
func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return NotZero(t, i, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Panicsf asserts that the code inside the specified PanicTestFunc panics.
|
||||
//
|
||||
// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Panics(t, f, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -329,9 +426,10 @@ func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool
|
|||
// the recovered panic value equals the expected panic value.
|
||||
//
|
||||
// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -339,9 +437,10 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str
|
|||
//
|
||||
// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
|
||||
// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
|
@ -349,31 +448,37 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Subset(t, list, subset, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Truef asserts that the specified value is true.
|
||||
//
|
||||
// assert.Truef(t, myBool, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return True(t, value, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// WithinDurationf asserts that the two times are within duration delta of each other.
|
||||
//
|
||||
// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Zerof asserts that i is the zero value for its type and returns the truth.
|
||||
// Zerof asserts that i is the zero value for its type.
|
||||
func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
return Zero(t, i, append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,6 +7,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
|
@ -26,6 +27,22 @@ type TestingT interface {
|
|||
Errorf(format string, args ...interface{})
|
||||
}
|
||||
|
||||
// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
|
||||
// for table driven tests.
|
||||
type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool
|
||||
|
||||
// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
|
||||
// for table driven tests.
|
||||
type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool
|
||||
|
||||
// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
|
||||
// for table driven tests.
|
||||
type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool
|
||||
|
||||
// ValuesAssertionFunc is a common function prototype when validating an error value. Can be useful
|
||||
// for table driven tests.
|
||||
type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool
|
||||
|
||||
// Comparison a custom function that returns true on success and false on failure
|
||||
type Comparison func() (success bool)
|
||||
|
||||
|
@ -37,21 +54,23 @@ type Comparison func() (success bool)
|
|||
//
|
||||
// This function does no assertion of any kind.
|
||||
func ObjectsAreEqual(expected, actual interface{}) bool {
|
||||
|
||||
if expected == nil || actual == nil {
|
||||
return expected == actual
|
||||
}
|
||||
if exp, ok := expected.([]byte); ok {
|
||||
act, ok := actual.([]byte)
|
||||
if !ok {
|
||||
return false
|
||||
} else if exp == nil || act == nil {
|
||||
return exp == nil && act == nil
|
||||
}
|
||||
return bytes.Equal(exp, act)
|
||||
}
|
||||
return reflect.DeepEqual(expected, actual)
|
||||
|
||||
exp, ok := expected.([]byte)
|
||||
if !ok {
|
||||
return reflect.DeepEqual(expected, actual)
|
||||
}
|
||||
|
||||
act, ok := actual.([]byte)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if exp == nil || act == nil {
|
||||
return exp == nil && act == nil
|
||||
}
|
||||
return bytes.Equal(exp, act)
|
||||
}
|
||||
|
||||
// ObjectsAreEqualValues gets whether two objects are equal, or if their
|
||||
|
@ -155,21 +174,6 @@ func isTest(name, prefix string) bool {
|
|||
return !unicode.IsLower(rune)
|
||||
}
|
||||
|
||||
// getWhitespaceString returns a string that is long enough to overwrite the default
|
||||
// output from the go testing framework.
|
||||
func getWhitespaceString() string {
|
||||
|
||||
_, file, line, ok := runtime.Caller(1)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
parts := strings.Split(file, "/")
|
||||
file = parts[len(parts)-1]
|
||||
|
||||
return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line)))
|
||||
|
||||
}
|
||||
|
||||
func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
|
||||
if len(msgAndArgs) == 0 || msgAndArgs == nil {
|
||||
return ""
|
||||
|
@ -194,7 +198,7 @@ func indentMessageLines(message string, longestLabelLen int) string {
|
|||
// no need to align first line because it starts at the correct location (after the label)
|
||||
if i != 0 {
|
||||
// append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab
|
||||
outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
|
||||
outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")
|
||||
}
|
||||
outBuf.WriteString(scanner.Text())
|
||||
}
|
||||
|
@ -208,6 +212,9 @@ type failNower interface {
|
|||
|
||||
// FailNow fails test
|
||||
func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
Fail(t, failureMessage, msgAndArgs...)
|
||||
|
||||
// We cannot extend TestingT with FailNow() and
|
||||
|
@ -226,17 +233,27 @@ func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool
|
|||
|
||||
// Fail reports a failure through
|
||||
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
content := []labeledContent{
|
||||
{"Error Trace", strings.Join(CallerInfo(), "\n\r\t\t\t")},
|
||||
{"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")},
|
||||
{"Error", failureMessage},
|
||||
}
|
||||
|
||||
// Add test name if the Go version supports it
|
||||
if n, ok := t.(interface {
|
||||
Name() string
|
||||
}); ok {
|
||||
content = append(content, labeledContent{"Test", n.Name()})
|
||||
}
|
||||
|
||||
message := messageFromMsgAndArgs(msgAndArgs...)
|
||||
if len(message) > 0 {
|
||||
content = append(content, labeledContent{"Messages", message})
|
||||
}
|
||||
|
||||
t.Errorf("%s", "\r"+getWhitespaceString()+labeledOutput(content...))
|
||||
t.Errorf("\n%s", ""+labeledOutput(content...))
|
||||
|
||||
return false
|
||||
}
|
||||
|
@ -248,7 +265,7 @@ type labeledContent struct {
|
|||
|
||||
// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner:
|
||||
//
|
||||
// \r\t{{label}}:{{align_spaces}}\t{{content}}\n
|
||||
// \t{{label}}:{{align_spaces}}\t{{content}}\n
|
||||
//
|
||||
// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label.
|
||||
// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this
|
||||
|
@ -264,7 +281,7 @@ func labeledOutput(content ...labeledContent) string {
|
|||
}
|
||||
var output string
|
||||
for _, v := range content {
|
||||
output += "\r\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"
|
||||
output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
@ -273,19 +290,26 @@ func labeledOutput(content ...labeledContent) string {
|
|||
//
|
||||
// assert.Implements(t, (*MyInterface)(nil), new(MyObject))
|
||||
func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
interfaceType := reflect.TypeOf(interfaceObject).Elem()
|
||||
|
||||
if object == nil {
|
||||
return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...)
|
||||
}
|
||||
if !reflect.TypeOf(object).Implements(interfaceType) {
|
||||
return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
// IsType asserts that the specified objects are of the same type.
|
||||
func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
|
||||
return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
|
||||
|
@ -298,12 +322,13 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs
|
|||
//
|
||||
// assert.Equal(t, 123, 123)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses). Function equality
|
||||
// cannot be determined and will always fail.
|
||||
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if err := validateEqualArgs(expected, actual); err != nil {
|
||||
return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)",
|
||||
expected, actual, err), msgAndArgs...)
|
||||
|
@ -314,7 +339,7 @@ func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{})
|
|||
expected, actual = formatUnequalValues(expected, actual)
|
||||
return Fail(t, fmt.Sprintf("Not equal: \n"+
|
||||
"expected: %s\n"+
|
||||
"actual: %s%s", expected, actual, diff), msgAndArgs...)
|
||||
"actual : %s%s", expected, actual, diff), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
|
@ -341,34 +366,36 @@ func formatUnequalValues(expected, actual interface{}) (e string, a string) {
|
|||
// and equal.
|
||||
//
|
||||
// assert.EqualValues(t, uint32(123), int32(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if !ObjectsAreEqualValues(expected, actual) {
|
||||
diff := diff(expected, actual)
|
||||
expected, actual = formatUnequalValues(expected, actual)
|
||||
return Fail(t, fmt.Sprintf("Not equal: \n"+
|
||||
"expected: %s\n"+
|
||||
"actual: %s%s", expected, actual, diff), msgAndArgs...)
|
||||
"actual : %s%s", expected, actual, diff), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
// Exactly asserts that two objects are equal is value and type.
|
||||
// Exactly asserts that two objects are equal in value and type.
|
||||
//
|
||||
// assert.Exactly(t, int32(123), int64(123))
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
aType := reflect.TypeOf(expected)
|
||||
bType := reflect.TypeOf(actual)
|
||||
|
||||
if aType != bType {
|
||||
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...)
|
||||
}
|
||||
|
||||
return Equal(t, expected, actual, msgAndArgs...)
|
||||
|
@ -378,9 +405,10 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
|
|||
// NotNil asserts that the specified object is not nil.
|
||||
//
|
||||
// assert.NotNil(t, err)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if !isNil(object) {
|
||||
return true
|
||||
}
|
||||
|
@ -405,82 +433,52 @@ func isNil(object interface{}) bool {
|
|||
// Nil asserts that the specified object is nil.
|
||||
//
|
||||
// assert.Nil(t, err)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if isNil(object) {
|
||||
return true
|
||||
}
|
||||
return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
|
||||
}
|
||||
|
||||
var numericZeros = []interface{}{
|
||||
int(0),
|
||||
int8(0),
|
||||
int16(0),
|
||||
int32(0),
|
||||
int64(0),
|
||||
uint(0),
|
||||
uint8(0),
|
||||
uint16(0),
|
||||
uint32(0),
|
||||
uint64(0),
|
||||
float32(0),
|
||||
float64(0),
|
||||
}
|
||||
|
||||
// isEmpty gets whether the specified object is considered empty or not.
|
||||
func isEmpty(object interface{}) bool {
|
||||
|
||||
// get nil case out of the way
|
||||
if object == nil {
|
||||
return true
|
||||
} else if object == "" {
|
||||
return true
|
||||
} else if object == false {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, v := range numericZeros {
|
||||
if object == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
objValue := reflect.ValueOf(object)
|
||||
|
||||
switch objValue.Kind() {
|
||||
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
|
||||
{
|
||||
return (objValue.Len() == 0)
|
||||
}
|
||||
case reflect.Struct:
|
||||
switch object.(type) {
|
||||
case time.Time:
|
||||
return object.(time.Time).IsZero()
|
||||
}
|
||||
// collection types are empty when they have no element
|
||||
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
|
||||
return objValue.Len() == 0
|
||||
// pointers are empty if nil or if the value they point to is empty
|
||||
case reflect.Ptr:
|
||||
{
|
||||
if objValue.IsNil() {
|
||||
return true
|
||||
}
|
||||
switch object.(type) {
|
||||
case *time.Time:
|
||||
return object.(*time.Time).IsZero()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
if objValue.IsNil() {
|
||||
return true
|
||||
}
|
||||
deref := objValue.Elem().Interface()
|
||||
return isEmpty(deref)
|
||||
// for all other types, compare against the zero value
|
||||
default:
|
||||
zero := reflect.Zero(objValue.Type())
|
||||
return reflect.DeepEqual(object, zero.Interface())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
|
||||
// a slice or a channel with len == 0.
|
||||
//
|
||||
// assert.Empty(t, obj)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
pass := isEmpty(object)
|
||||
if !pass {
|
||||
|
@ -497,9 +495,10 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
|||
// if assert.NotEmpty(t, obj) {
|
||||
// assert.Equal(t, "two", obj[1])
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
pass := !isEmpty(object)
|
||||
if !pass {
|
||||
|
@ -526,9 +525,10 @@ func getLen(x interface{}) (ok bool, length int) {
|
|||
// Len also fails if the object has a type that len() not accept.
|
||||
//
|
||||
// assert.Len(t, mySlice, 3)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
ok, l := getLen(object)
|
||||
if !ok {
|
||||
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
|
||||
|
@ -543,9 +543,15 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{})
|
|||
// True asserts that the specified value is true.
|
||||
//
|
||||
// assert.True(t, myBool)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if h, ok := t.(interface {
|
||||
Helper()
|
||||
}); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if value != true {
|
||||
return Fail(t, "Should be true", msgAndArgs...)
|
||||
|
@ -558,9 +564,10 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
|||
// False asserts that the specified value is false.
|
||||
//
|
||||
// assert.False(t, myBool)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if value != false {
|
||||
return Fail(t, "Should be false", msgAndArgs...)
|
||||
|
@ -574,11 +581,12 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
|||
//
|
||||
// assert.NotEqual(t, obj1, obj2)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
//
|
||||
// Pointer variable equality is determined based on the equality of the
|
||||
// referenced values (as opposed to the memory addresses).
|
||||
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if err := validateEqualArgs(expected, actual); err != nil {
|
||||
return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)",
|
||||
expected, actual, err), msgAndArgs...)
|
||||
|
@ -636,9 +644,10 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) {
|
|||
// assert.Contains(t, "Hello World", "World")
|
||||
// assert.Contains(t, ["Hello", "World"], "World")
|
||||
// assert.Contains(t, {"Hello": "World"}, "Hello")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
ok, found := includeElement(s, contains)
|
||||
if !ok {
|
||||
|
@ -658,9 +667,10 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
|
|||
// assert.NotContains(t, "Hello World", "Earth")
|
||||
// assert.NotContains(t, ["Hello", "World"], "Earth")
|
||||
// assert.NotContains(t, {"Hello": "World"}, "Earth")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
ok, found := includeElement(s, contains)
|
||||
if !ok {
|
||||
|
@ -678,9 +688,10 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if subset == nil {
|
||||
return true // we consider nil to be equal to the nil set
|
||||
}
|
||||
|
@ -721,11 +732,12 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
|
|||
// elements given in the specified subset(array, slice...).
|
||||
//
|
||||
// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if subset == nil {
|
||||
return false // we consider nil to be equal to the nil set
|
||||
return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...)
|
||||
}
|
||||
|
||||
subsetValue := reflect.ValueOf(subset)
|
||||
|
@ -760,8 +772,68 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
|
|||
return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
|
||||
}
|
||||
|
||||
// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
|
||||
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
|
||||
// the number of appearances of each of them in both lists should match.
|
||||
//
|
||||
// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
|
||||
func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if isEmpty(listA) && isEmpty(listB) {
|
||||
return true
|
||||
}
|
||||
|
||||
aKind := reflect.TypeOf(listA).Kind()
|
||||
bKind := reflect.TypeOf(listB).Kind()
|
||||
|
||||
if aKind != reflect.Array && aKind != reflect.Slice {
|
||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listA, aKind), msgAndArgs...)
|
||||
}
|
||||
|
||||
if bKind != reflect.Array && bKind != reflect.Slice {
|
||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listB, bKind), msgAndArgs...)
|
||||
}
|
||||
|
||||
aValue := reflect.ValueOf(listA)
|
||||
bValue := reflect.ValueOf(listB)
|
||||
|
||||
aLen := aValue.Len()
|
||||
bLen := bValue.Len()
|
||||
|
||||
if aLen != bLen {
|
||||
return Fail(t, fmt.Sprintf("lengths don't match: %d != %d", aLen, bLen), msgAndArgs...)
|
||||
}
|
||||
|
||||
// Mark indexes in bValue that we already used
|
||||
visited := make([]bool, bLen)
|
||||
for i := 0; i < aLen; i++ {
|
||||
element := aValue.Index(i).Interface()
|
||||
found := false
|
||||
for j := 0; j < bLen; j++ {
|
||||
if visited[j] {
|
||||
continue
|
||||
}
|
||||
if ObjectsAreEqual(bValue.Index(j).Interface(), element) {
|
||||
visited[j] = true
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return Fail(t, fmt.Sprintf("element %s appears more times in %s than in %s", element, aValue, bValue), msgAndArgs...)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Condition uses a Comparison to assert a complex condition.
|
||||
func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
result := comp()
|
||||
if !result {
|
||||
Fail(t, "Condition failed!", msgAndArgs...)
|
||||
|
@ -798,12 +870,13 @@ func didPanic(f PanicTestFunc) (bool, interface{}) {
|
|||
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
||||
//
|
||||
// assert.Panics(t, func(){ GoCrazy() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
|
@ -813,16 +886,17 @@ func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
|||
// the recovered panic value equals the expected panic value.
|
||||
//
|
||||
// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
funcDidPanic, panicValue := didPanic(f)
|
||||
if !funcDidPanic {
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
|
||||
}
|
||||
if panicValue != expected {
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%v\n\r\tPanic value:\t%v", f, expected, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v", f, expected, panicValue), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
|
@ -831,12 +905,13 @@ func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndAr
|
|||
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||
//
|
||||
// assert.NotPanics(t, func(){ RemainCalm() })
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
|
||||
return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v", f, panicValue), msgAndArgs...)
|
||||
}
|
||||
|
||||
return true
|
||||
|
@ -845,9 +920,10 @@ func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
|||
// WithinDuration asserts that the two times are within duration delta of each other.
|
||||
//
|
||||
// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
dt := expected.Sub(actual)
|
||||
if dt < -delta || dt > delta {
|
||||
|
@ -896,9 +972,10 @@ func toFloat(x interface{}) (float64, bool) {
|
|||
// InDelta asserts that the two numerals are within delta of each other.
|
||||
//
|
||||
// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
af, aok := toFloat(expected)
|
||||
bf, bok := toFloat(actual)
|
||||
|
@ -925,6 +1002,9 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs
|
|||
|
||||
// InDeltaSlice is the same as InDelta, except it compares two slices.
|
||||
func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if expected == nil || actual == nil ||
|
||||
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
||||
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
||||
|
@ -944,6 +1024,50 @@ func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAn
|
|||
return true
|
||||
}
|
||||
|
||||
// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
|
||||
func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if expected == nil || actual == nil ||
|
||||
reflect.TypeOf(actual).Kind() != reflect.Map ||
|
||||
reflect.TypeOf(expected).Kind() != reflect.Map {
|
||||
return Fail(t, "Arguments must be maps", msgAndArgs...)
|
||||
}
|
||||
|
||||
expectedMap := reflect.ValueOf(expected)
|
||||
actualMap := reflect.ValueOf(actual)
|
||||
|
||||
if expectedMap.Len() != actualMap.Len() {
|
||||
return Fail(t, "Arguments must have the same number of keys", msgAndArgs...)
|
||||
}
|
||||
|
||||
for _, k := range expectedMap.MapKeys() {
|
||||
ev := expectedMap.MapIndex(k)
|
||||
av := actualMap.MapIndex(k)
|
||||
|
||||
if !ev.IsValid() {
|
||||
return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...)
|
||||
}
|
||||
|
||||
if !av.IsValid() {
|
||||
return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...)
|
||||
}
|
||||
|
||||
if !InDelta(
|
||||
t,
|
||||
ev.Interface(),
|
||||
av.Interface(),
|
||||
delta,
|
||||
msgAndArgs...,
|
||||
) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func calcRelativeError(expected, actual interface{}) (float64, error) {
|
||||
af, aok := toFloat(expected)
|
||||
if !aok {
|
||||
|
@ -961,9 +1085,10 @@ func calcRelativeError(expected, actual interface{}) (float64, error) {
|
|||
}
|
||||
|
||||
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
actualEpsilon, err := calcRelativeError(expected, actual)
|
||||
if err != nil {
|
||||
return Fail(t, err.Error(), msgAndArgs...)
|
||||
|
@ -978,6 +1103,9 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd
|
|||
|
||||
// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
|
||||
func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if expected == nil || actual == nil ||
|
||||
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
||||
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
||||
|
@ -1007,9 +1135,10 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
|
|||
// if assert.NoError(t, err) {
|
||||
// assert.Equal(t, expectedObj, actualObj)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if err != nil {
|
||||
return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...)
|
||||
}
|
||||
|
@ -1023,9 +1152,10 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
|||
// if assert.Error(t, err) {
|
||||
// assert.Equal(t, expectedError, err)
|
||||
// }
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
return Fail(t, "An error is expected but got nil.", msgAndArgs...)
|
||||
|
@ -1039,9 +1169,10 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
|||
//
|
||||
// actualObj, err := SomeFunction()
|
||||
// assert.EqualError(t, err, expectedErrorString)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if !Error(t, theError, msgAndArgs...) {
|
||||
return false
|
||||
}
|
||||
|
@ -1051,7 +1182,7 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte
|
|||
if expected != actual {
|
||||
return Fail(t, fmt.Sprintf("Error message not equal:\n"+
|
||||
"expected: %q\n"+
|
||||
"actual: %q", expected, actual), msgAndArgs...)
|
||||
"actual : %q", expected, actual), msgAndArgs...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -1074,9 +1205,10 @@ func matchRegexp(rx interface{}, str interface{}) bool {
|
|||
//
|
||||
// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
|
||||
// assert.Regexp(t, "start...$", "it's not starting")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
match := matchRegexp(rx, str)
|
||||
|
||||
|
@ -1091,9 +1223,10 @@ func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface
|
|||
//
|
||||
// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
|
||||
// assert.NotRegexp(t, "^start", "it's not starting")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
match := matchRegexp(rx, str)
|
||||
|
||||
if match {
|
||||
|
@ -1104,28 +1237,71 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf
|
|||
|
||||
}
|
||||
|
||||
// Zero asserts that i is the zero value for its type and returns the truth.
|
||||
// Zero asserts that i is the zero value for its type.
|
||||
func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
|
||||
return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// NotZero asserts that i is not the zero value for its type and returns the truth.
|
||||
// NotZero asserts that i is not the zero value for its type.
|
||||
func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
|
||||
return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
|
||||
func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
info, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...)
|
||||
}
|
||||
return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...)
|
||||
}
|
||||
if info.IsDir() {
|
||||
return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
|
||||
func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
info, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...)
|
||||
}
|
||||
return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...)
|
||||
}
|
||||
if !info.IsDir() {
|
||||
return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// JSONEq asserts that two JSON strings are equivalent.
|
||||
//
|
||||
// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
var expectedJSONAsInterface, actualJSONAsInterface interface{}
|
||||
|
||||
if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil {
|
||||
|
@ -1164,12 +1340,18 @@ func diff(expected interface{}, actual interface{}) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array {
|
||||
if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String {
|
||||
return ""
|
||||
}
|
||||
|
||||
e := spewConfig.Sdump(expected)
|
||||
a := spewConfig.Sdump(actual)
|
||||
var e, a string
|
||||
if ek != reflect.String {
|
||||
e = spewConfig.Sdump(expected)
|
||||
a = spewConfig.Sdump(actual)
|
||||
} else {
|
||||
e = expected.(string)
|
||||
a = actual.(string)
|
||||
}
|
||||
|
||||
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
|
||||
A: difflib.SplitLines(e),
|
||||
|
@ -1206,3 +1388,7 @@ var spewConfig = spew.ConfigState{
|
|||
DisableCapacities: true,
|
||||
SortKeys: true,
|
||||
}
|
||||
|
||||
type tHelper interface {
|
||||
Helper()
|
||||
}
|
||||
|
|
|
@ -12,10 +12,11 @@ import (
|
|||
// an error if building a new request fails.
|
||||
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) {
|
||||
w := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
req.URL.RawQuery = values.Encode()
|
||||
handler(w, req)
|
||||
return w.Code, nil
|
||||
}
|
||||
|
@ -25,7 +26,10 @@ func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (
|
|||
// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
||||
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
|
@ -45,7 +49,10 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value
|
|||
// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
||||
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
|
@ -65,7 +72,10 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu
|
|||
// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
||||
func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
code, err := httpCode(handler, method, url, values)
|
||||
if err != nil {
|
||||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err))
|
||||
|
@ -95,10 +105,13 @@ func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) s
|
|||
// HTTPBodyContains asserts that a specified handler returns a
|
||||
// body that contains a string.
|
||||
//
|
||||
// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
|
||||
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
body := HTTPBody(handler, method, url, values)
|
||||
|
||||
contains := strings.Contains(body, fmt.Sprint(str))
|
||||
|
@ -112,10 +125,13 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string,
|
|||
// HTTPBodyNotContains asserts that a specified handler returns a
|
||||
// body that does not contain a string.
|
||||
//
|
||||
// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||
// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky")
|
||||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
|
||||
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
body := HTTPBody(handler, method, url, values)
|
||||
|
||||
contains := strings.Contains(body, fmt.Sprint(str))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package mock
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
|
@ -41,6 +42,9 @@ type Call struct {
|
|||
// this method is called.
|
||||
ReturnArguments Arguments
|
||||
|
||||
// Holds the caller info for the On() call
|
||||
callerInfo []string
|
||||
|
||||
// The number of times to return the return arguments when setting
|
||||
// expectations. 0 means to always return the value.
|
||||
Repeatability int
|
||||
|
@ -48,22 +52,28 @@ type Call struct {
|
|||
// Amount of times this call has been called
|
||||
totalCalls int
|
||||
|
||||
// Call to this method can be optional
|
||||
optional bool
|
||||
|
||||
// Holds a channel that will be used to block the Return until it either
|
||||
// receives a message or is closed. nil means it returns immediately.
|
||||
WaitFor <-chan time.Time
|
||||
|
||||
waitTime time.Duration
|
||||
|
||||
// Holds a handler used to manipulate arguments content that are passed by
|
||||
// reference. It's useful when mocking methods such as unmarshalers or
|
||||
// decoders.
|
||||
RunFn func(Arguments)
|
||||
}
|
||||
|
||||
func newCall(parent *Mock, methodName string, methodArguments ...interface{}) *Call {
|
||||
func newCall(parent *Mock, methodName string, callerInfo []string, methodArguments ...interface{}) *Call {
|
||||
return &Call{
|
||||
Parent: parent,
|
||||
Method: methodName,
|
||||
Arguments: methodArguments,
|
||||
ReturnArguments: make([]interface{}, 0),
|
||||
callerInfo: callerInfo,
|
||||
Repeatability: 0,
|
||||
WaitFor: nil,
|
||||
RunFn: nil,
|
||||
|
@ -130,7 +140,10 @@ func (c *Call) WaitUntil(w <-chan time.Time) *Call {
|
|||
//
|
||||
// Mock.On("MyMethod", arg1, arg2).After(time.Second)
|
||||
func (c *Call) After(d time.Duration) *Call {
|
||||
return c.WaitUntil(time.After(d))
|
||||
c.lock()
|
||||
defer c.unlock()
|
||||
c.waitTime = d
|
||||
return c
|
||||
}
|
||||
|
||||
// Run sets a handler to be called before returning. It can be used when
|
||||
|
@ -148,6 +161,15 @@ func (c *Call) Run(fn func(args Arguments)) *Call {
|
|||
return c
|
||||
}
|
||||
|
||||
// Maybe allows the method call to be optional. Not calling an optional method
|
||||
// will not cause an error while asserting expectations
|
||||
func (c *Call) Maybe() *Call {
|
||||
c.lock()
|
||||
defer c.unlock()
|
||||
c.optional = true
|
||||
return c
|
||||
}
|
||||
|
||||
// On chains a new expectation description onto the mocked interface. This
|
||||
// allows syntax like.
|
||||
//
|
||||
|
@ -169,6 +191,10 @@ type Mock struct {
|
|||
// Holds the calls that were made to this mocked object.
|
||||
Calls []Call
|
||||
|
||||
// test is An optional variable that holds the test struct, to be used when an
|
||||
// invalid mock call was made.
|
||||
test TestingT
|
||||
|
||||
// TestData holds any data that might be useful for testing. Testify ignores
|
||||
// this data completely allowing you to do whatever you like with it.
|
||||
testData objx.Map
|
||||
|
@ -191,6 +217,27 @@ func (m *Mock) TestData() objx.Map {
|
|||
Setting expectations
|
||||
*/
|
||||
|
||||
// Test sets the test struct variable of the mock object
|
||||
func (m *Mock) Test(t TestingT) {
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
m.test = t
|
||||
}
|
||||
|
||||
// fail fails the current test with the given formatted format and args.
|
||||
// In case that a test was defined, it uses the test APIs for failing a test,
|
||||
// otherwise it uses panic.
|
||||
func (m *Mock) fail(format string, args ...interface{}) {
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
|
||||
if m.test == nil {
|
||||
panic(fmt.Sprintf(format, args...))
|
||||
}
|
||||
m.test.Errorf(format, args...)
|
||||
m.test.FailNow()
|
||||
}
|
||||
|
||||
// On starts a description of an expectation of the specified method
|
||||
// being called.
|
||||
//
|
||||
|
@ -204,7 +251,7 @@ func (m *Mock) On(methodName string, arguments ...interface{}) *Call {
|
|||
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
c := newCall(m, methodName, arguments...)
|
||||
c := newCall(m, methodName, assert.CallerInfo(), arguments...)
|
||||
m.ExpectedCalls = append(m.ExpectedCalls, c)
|
||||
return c
|
||||
}
|
||||
|
@ -227,27 +274,25 @@ func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *
|
|||
return -1, nil
|
||||
}
|
||||
|
||||
func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) {
|
||||
diffCount := 0
|
||||
func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call, string) {
|
||||
var diffCount int
|
||||
var closestCall *Call
|
||||
var err string
|
||||
|
||||
for _, call := range m.expectedCalls() {
|
||||
if call.Method == method {
|
||||
|
||||
_, tempDiffCount := call.Arguments.Diff(arguments)
|
||||
errInfo, tempDiffCount := call.Arguments.Diff(arguments)
|
||||
if tempDiffCount < diffCount || diffCount == 0 {
|
||||
diffCount = tempDiffCount
|
||||
closestCall = call
|
||||
err = errInfo
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if closestCall == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, closestCall
|
||||
return closestCall, err
|
||||
}
|
||||
|
||||
func callString(method string, arguments Arguments, includeArgumentValues bool) string {
|
||||
|
@ -294,6 +339,7 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
|
|||
// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
|
||||
func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments {
|
||||
m.mutex.Lock()
|
||||
//TODO: could combine expected and closes in single loop
|
||||
found, call := m.findExpectedCall(methodName, arguments...)
|
||||
|
||||
if found < 0 {
|
||||
|
@ -304,43 +350,52 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
|
|||
// b) the arguments are not what was expected, or
|
||||
// c) the developer has forgotten to add an accompanying On...Return pair.
|
||||
|
||||
closestFound, closestCall := m.findClosestCall(methodName, arguments...)
|
||||
closestCall, mismatch := m.findClosestCall(methodName, arguments...)
|
||||
m.mutex.Unlock()
|
||||
|
||||
if closestFound {
|
||||
panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\n", callString(methodName, arguments, true), callString(methodName, closestCall.Arguments, true), diffArguments(arguments, closestCall.Arguments)))
|
||||
if closestCall != nil {
|
||||
m.fail("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\nDiff: %s",
|
||||
callString(methodName, arguments, true),
|
||||
callString(methodName, closestCall.Arguments, true),
|
||||
diffArguments(closestCall.Arguments, arguments),
|
||||
strings.TrimSpace(mismatch),
|
||||
)
|
||||
} else {
|
||||
panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo()))
|
||||
m.fail("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo())
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case call.Repeatability == 1:
|
||||
if call.Repeatability == 1 {
|
||||
call.Repeatability = -1
|
||||
call.totalCalls++
|
||||
|
||||
case call.Repeatability > 1:
|
||||
} else if call.Repeatability > 1 {
|
||||
call.Repeatability--
|
||||
call.totalCalls++
|
||||
|
||||
case call.Repeatability == 0:
|
||||
call.totalCalls++
|
||||
}
|
||||
call.totalCalls++
|
||||
|
||||
// add the call
|
||||
m.Calls = append(m.Calls, *newCall(m, methodName, arguments...))
|
||||
m.Calls = append(m.Calls, *newCall(m, methodName, assert.CallerInfo(), arguments...))
|
||||
m.mutex.Unlock()
|
||||
|
||||
// block if specified
|
||||
if call.WaitFor != nil {
|
||||
<-call.WaitFor
|
||||
} else {
|
||||
time.Sleep(call.waitTime)
|
||||
}
|
||||
|
||||
if call.RunFn != nil {
|
||||
call.RunFn(arguments)
|
||||
m.mutex.Lock()
|
||||
runFn := call.RunFn
|
||||
m.mutex.Unlock()
|
||||
|
||||
if runFn != nil {
|
||||
runFn(arguments)
|
||||
}
|
||||
|
||||
return call.ReturnArguments
|
||||
m.mutex.Lock()
|
||||
returnArgs := call.ReturnArguments
|
||||
m.mutex.Unlock()
|
||||
|
||||
return returnArgs
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -356,6 +411,9 @@ type assertExpectationser interface {
|
|||
//
|
||||
// Calls may have occurred in any order.
|
||||
func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
for _, obj := range testObjects {
|
||||
if m, ok := obj.(Mock); ok {
|
||||
t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)")
|
||||
|
@ -363,6 +421,7 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
|
|||
}
|
||||
m := obj.(assertExpectationser)
|
||||
if !m.AssertExpectations(t) {
|
||||
t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m))
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -372,6 +431,9 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
|
|||
// AssertExpectations asserts that everything specified with On and Return was
|
||||
// in fact called as expected. Calls may have occurred in any order.
|
||||
func (m *Mock) AssertExpectations(t TestingT) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
var somethingMissing bool
|
||||
|
@ -380,16 +442,17 @@ func (m *Mock) AssertExpectations(t TestingT) bool {
|
|||
// iterate through each expectation
|
||||
expectedCalls := m.expectedCalls()
|
||||
for _, expectedCall := range expectedCalls {
|
||||
if !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 {
|
||||
if !expectedCall.optional && !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 {
|
||||
somethingMissing = true
|
||||
failedExpectations++
|
||||
t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
|
||||
t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo)
|
||||
} else {
|
||||
if expectedCall.Repeatability > 0 {
|
||||
somethingMissing = true
|
||||
failedExpectations++
|
||||
t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo)
|
||||
} else {
|
||||
t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
|
||||
t.Logf("PASS:\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -403,6 +466,9 @@ func (m *Mock) AssertExpectations(t TestingT) bool {
|
|||
|
||||
// AssertNumberOfCalls asserts that the method was called expectedCalls times.
|
||||
func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
var actualCalls int
|
||||
|
@ -417,11 +483,22 @@ func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls
|
|||
// AssertCalled asserts that the method was called.
|
||||
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
|
||||
func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
if !assert.True(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(arguments))) {
|
||||
t.Logf("%v", m.expectedCalls())
|
||||
return false
|
||||
if !m.methodWasCalled(methodName, arguments) {
|
||||
var calledWithArgs []string
|
||||
for _, call := range m.calls() {
|
||||
calledWithArgs = append(calledWithArgs, fmt.Sprintf("%v", call.Arguments))
|
||||
}
|
||||
if len(calledWithArgs) == 0 {
|
||||
return assert.Fail(t, "Should have called with given arguments",
|
||||
fmt.Sprintf("Expected %q to have been called with:\n%v\nbut no actual calls happened", methodName, arguments))
|
||||
}
|
||||
return assert.Fail(t, "Should have called with given arguments",
|
||||
fmt.Sprintf("Expected %q to have been called with:\n%v\nbut actual calls were:\n %v", methodName, arguments, strings.Join(calledWithArgs, "\n")))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -429,11 +506,14 @@ func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interfac
|
|||
// AssertNotCalled asserts that the method was not called.
|
||||
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
|
||||
func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
if !assert.False(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(arguments))) {
|
||||
t.Logf("%v", m.expectedCalls())
|
||||
return false
|
||||
if m.methodWasCalled(methodName, arguments) {
|
||||
return assert.Fail(t, "Should not have called with given arguments",
|
||||
fmt.Sprintf("Expected %q to not have been called with:\n%v\nbut actually it was.", methodName, arguments))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -473,7 +553,7 @@ type Arguments []interface{}
|
|||
const (
|
||||
// Anything is used in Diff and Assert when the argument being tested
|
||||
// shouldn't be taken into consideration.
|
||||
Anything string = "mock.Anything"
|
||||
Anything = "mock.Anything"
|
||||
)
|
||||
|
||||
// AnythingOfTypeArgument is a string that contains the type of an argument
|
||||
|
@ -498,9 +578,25 @@ type argumentMatcher struct {
|
|||
|
||||
func (f argumentMatcher) Matches(argument interface{}) bool {
|
||||
expectType := f.fn.Type().In(0)
|
||||
expectTypeNilSupported := false
|
||||
switch expectType.Kind() {
|
||||
case reflect.Interface, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Ptr:
|
||||
expectTypeNilSupported = true
|
||||
}
|
||||
|
||||
if reflect.TypeOf(argument).AssignableTo(expectType) {
|
||||
result := f.fn.Call([]reflect.Value{reflect.ValueOf(argument)})
|
||||
argType := reflect.TypeOf(argument)
|
||||
var arg reflect.Value
|
||||
if argType == nil {
|
||||
arg = reflect.New(expectType).Elem()
|
||||
} else {
|
||||
arg = reflect.ValueOf(argument)
|
||||
}
|
||||
|
||||
if argType == nil && !expectTypeNilSupported {
|
||||
panic(errors.New("attempting to call matcher with nil for non-nil expected type"))
|
||||
}
|
||||
if argType == nil || argType.AssignableTo(expectType) {
|
||||
result := f.fn.Call([]reflect.Value{arg})
|
||||
return result[0].Bool()
|
||||
}
|
||||
return false
|
||||
|
@ -560,6 +656,7 @@ func (args Arguments) Is(objects ...interface{}) bool {
|
|||
//
|
||||
// Returns the diff string and number of differences found.
|
||||
func (args Arguments) Diff(objects []interface{}) (string, int) {
|
||||
//TODO: could return string as error and nil for No difference
|
||||
|
||||
var output = "\n"
|
||||
var differences int
|
||||
|
@ -571,25 +668,30 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
|||
|
||||
for i := 0; i < maxArgCount; i++ {
|
||||
var actual, expected interface{}
|
||||
var actualFmt, expectedFmt string
|
||||
|
||||
if len(objects) <= i {
|
||||
actual = "(Missing)"
|
||||
actualFmt = "(Missing)"
|
||||
} else {
|
||||
actual = objects[i]
|
||||
actualFmt = fmt.Sprintf("(%[1]T=%[1]v)", actual)
|
||||
}
|
||||
|
||||
if len(args) <= i {
|
||||
expected = "(Missing)"
|
||||
expectedFmt = "(Missing)"
|
||||
} else {
|
||||
expected = args[i]
|
||||
expectedFmt = fmt.Sprintf("(%[1]T=%[1]v)", expected)
|
||||
}
|
||||
|
||||
if matcher, ok := expected.(argumentMatcher); ok {
|
||||
if matcher.Matches(actual) {
|
||||
output = fmt.Sprintf("%s\t%d: \u2705 %s matched by %s\n", output, i, actual, matcher)
|
||||
output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher)
|
||||
} else {
|
||||
differences++
|
||||
output = fmt.Sprintf("%s\t%d: \u2705 %s not matched by %s\n", output, i, actual, matcher)
|
||||
output = fmt.Sprintf("%s\t%d: PASS: %s not matched by %s\n", output, i, actualFmt, matcher)
|
||||
}
|
||||
} else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
|
||||
|
||||
|
@ -597,7 +699,7 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
|||
if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
|
||||
// not match
|
||||
differences++
|
||||
output = fmt.Sprintf("%s\t%d: \u274C type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actual)
|
||||
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -606,11 +708,11 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
|||
|
||||
if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
|
||||
// match
|
||||
output = fmt.Sprintf("%s\t%d: \u2705 %s == %s\n", output, i, actual, expected)
|
||||
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt)
|
||||
} else {
|
||||
// not match
|
||||
differences++
|
||||
output = fmt.Sprintf("%s\t%d: \u274C %s != %s\n", output, i, actual, expected)
|
||||
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -627,6 +729,9 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
|||
// Assert compares the arguments with the specified objects and fails if
|
||||
// they do not exactly match.
|
||||
func (args Arguments) Assert(t TestingT, objects ...interface{}) bool {
|
||||
if h, ok := t.(tHelper); ok {
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
// get the differences
|
||||
diff, diffCount := args.Diff(objects)
|
||||
|
@ -774,3 +879,7 @@ var spewConfig = spew.ConfigState{
|
|||
DisableCapacities: true,
|
||||
SortKeys: true,
|
||||
}
|
||||
|
||||
type tHelper interface {
|
||||
Helper()
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -6,4 +6,24 @@ type TestingT interface {
|
|||
FailNow()
|
||||
}
|
||||
|
||||
type tHelper interface {
|
||||
Helper()
|
||||
}
|
||||
|
||||
// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
|
||||
// for table driven tests.
|
||||
type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{})
|
||||
|
||||
// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
|
||||
// for table driven tests.
|
||||
type ValueAssertionFunc func(TestingT, interface{}, ...interface{})
|
||||
|
||||
// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
|
||||
// for table driven tests.
|
||||
type BoolAssertionFunc func(TestingT, bool, ...interface{})
|
||||
|
||||
// ValuesAssertionFunc is a common function prototype when validating an error value. Can be useful
|
||||
// for table driven tests.
|
||||
type ErrorAssertionFunc func(TestingT, error, ...interface{})
|
||||
|
||||
//go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl -include-format-funcs
|
||||
|
|
Loading…
Reference in New Issue