forked from Shiloh/githaven
245 lines
7.4 KiB
Go
245 lines
7.4 KiB
Go
|
package assertions
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
|
||
|
"github.com/smartystreets/assertions/internal/oglematchers"
|
||
|
)
|
||
|
|
||
|
// ShouldContain receives exactly two parameters. The first is a slice and the
|
||
|
// second is a proposed member. Membership is determined using ShouldEqual.
|
||
|
func ShouldContain(actual interface{}, expected ...interface{}) string {
|
||
|
if fail := need(1, expected); fail != success {
|
||
|
return fail
|
||
|
}
|
||
|
|
||
|
if matchError := oglematchers.Contains(expected[0]).Matches(actual); matchError != nil {
|
||
|
typeName := reflect.TypeOf(actual)
|
||
|
|
||
|
if fmt.Sprintf("%v", matchError) == "which is not a slice or array" {
|
||
|
return fmt.Sprintf(shouldHaveBeenAValidCollection, typeName)
|
||
|
}
|
||
|
return fmt.Sprintf(shouldHaveContained, typeName, expected[0])
|
||
|
}
|
||
|
return success
|
||
|
}
|
||
|
|
||
|
// ShouldNotContain receives exactly two parameters. The first is a slice and the
|
||
|
// second is a proposed member. Membership is determinied using ShouldEqual.
|
||
|
func ShouldNotContain(actual interface{}, expected ...interface{}) string {
|
||
|
if fail := need(1, expected); fail != success {
|
||
|
return fail
|
||
|
}
|
||
|
typeName := reflect.TypeOf(actual)
|
||
|
|
||
|
if matchError := oglematchers.Contains(expected[0]).Matches(actual); matchError != nil {
|
||
|
if fmt.Sprintf("%v", matchError) == "which is not a slice or array" {
|
||
|
return fmt.Sprintf(shouldHaveBeenAValidCollection, typeName)
|
||
|
}
|
||
|
return success
|
||
|
}
|
||
|
return fmt.Sprintf(shouldNotHaveContained, typeName, expected[0])
|
||
|
}
|
||
|
|
||
|
// ShouldContainKey receives exactly two parameters. The first is a map and the
|
||
|
// second is a proposed key. Keys are compared with a simple '=='.
|
||
|
func ShouldContainKey(actual interface{}, expected ...interface{}) string {
|
||
|
if fail := need(1, expected); fail != success {
|
||
|
return fail
|
||
|
}
|
||
|
|
||
|
keys, isMap := mapKeys(actual)
|
||
|
if !isMap {
|
||
|
return fmt.Sprintf(shouldHaveBeenAValidMap, reflect.TypeOf(actual))
|
||
|
}
|
||
|
|
||
|
if !keyFound(keys, expected[0]) {
|
||
|
return fmt.Sprintf(shouldHaveContainedKey, reflect.TypeOf(actual), expected)
|
||
|
}
|
||
|
|
||
|
return ""
|
||
|
}
|
||
|
|
||
|
// ShouldNotContainKey receives exactly two parameters. The first is a map and the
|
||
|
// second is a proposed absent key. Keys are compared with a simple '=='.
|
||
|
func ShouldNotContainKey(actual interface{}, expected ...interface{}) string {
|
||
|
if fail := need(1, expected); fail != success {
|
||
|
return fail
|
||
|
}
|
||
|
|
||
|
keys, isMap := mapKeys(actual)
|
||
|
if !isMap {
|
||
|
return fmt.Sprintf(shouldHaveBeenAValidMap, reflect.TypeOf(actual))
|
||
|
}
|
||
|
|
||
|
if keyFound(keys, expected[0]) {
|
||
|
return fmt.Sprintf(shouldNotHaveContainedKey, reflect.TypeOf(actual), expected)
|
||
|
}
|
||
|
|
||
|
return ""
|
||
|
}
|
||
|
|
||
|
func mapKeys(m interface{}) ([]reflect.Value, bool) {
|
||
|
value := reflect.ValueOf(m)
|
||
|
if value.Kind() != reflect.Map {
|
||
|
return nil, false
|
||
|
}
|
||
|
return value.MapKeys(), true
|
||
|
}
|
||
|
func keyFound(keys []reflect.Value, expectedKey interface{}) bool {
|
||
|
found := false
|
||
|
for _, key := range keys {
|
||
|
if key.Interface() == expectedKey {
|
||
|
found = true
|
||
|
}
|
||
|
}
|
||
|
return found
|
||
|
}
|
||
|
|
||
|
// ShouldBeIn receives at least 2 parameters. The first is a proposed member of the collection
|
||
|
// that is passed in either as the second parameter, or of the collection that is comprised
|
||
|
// of all the remaining parameters. This assertion ensures that the proposed member is in
|
||
|
// the collection (using ShouldEqual).
|
||
|
func ShouldBeIn(actual interface{}, expected ...interface{}) string {
|
||
|
if fail := atLeast(1, expected); fail != success {
|
||
|
return fail
|
||
|
}
|
||
|
|
||
|
if len(expected) == 1 {
|
||
|
return shouldBeIn(actual, expected[0])
|
||
|
}
|
||
|
return shouldBeIn(actual, expected)
|
||
|
}
|
||
|
func shouldBeIn(actual interface{}, expected interface{}) string {
|
||
|
if matchError := oglematchers.Contains(actual).Matches(expected); matchError != nil {
|
||
|
return fmt.Sprintf(shouldHaveBeenIn, actual, reflect.TypeOf(expected))
|
||
|
}
|
||
|
return success
|
||
|
}
|
||
|
|
||
|
// ShouldNotBeIn receives at least 2 parameters. The first is a proposed member of the collection
|
||
|
// that is passed in either as the second parameter, or of the collection that is comprised
|
||
|
// of all the remaining parameters. This assertion ensures that the proposed member is NOT in
|
||
|
// the collection (using ShouldEqual).
|
||
|
func ShouldNotBeIn(actual interface{}, expected ...interface{}) string {
|
||
|
if fail := atLeast(1, expected); fail != success {
|
||
|
return fail
|
||
|
}
|
||
|
|
||
|
if len(expected) == 1 {
|
||
|
return shouldNotBeIn(actual, expected[0])
|
||
|
}
|
||
|
return shouldNotBeIn(actual, expected)
|
||
|
}
|
||
|
func shouldNotBeIn(actual interface{}, expected interface{}) string {
|
||
|
if matchError := oglematchers.Contains(actual).Matches(expected); matchError == nil {
|
||
|
return fmt.Sprintf(shouldNotHaveBeenIn, actual, reflect.TypeOf(expected))
|
||
|
}
|
||
|
return success
|
||
|
}
|
||
|
|
||
|
// ShouldBeEmpty receives a single parameter (actual) and determines whether or not
|
||
|
// calling len(actual) would return `0`. It obeys the rules specified by the len
|
||
|
// function for determining length: http://golang.org/pkg/builtin/#len
|
||
|
func ShouldBeEmpty(actual interface{}, expected ...interface{}) string {
|
||
|
if fail := need(0, expected); fail != success {
|
||
|
return fail
|
||
|
}
|
||
|
|
||
|
if actual == nil {
|
||
|
return success
|
||
|
}
|
||
|
|
||
|
value := reflect.ValueOf(actual)
|
||
|
switch value.Kind() {
|
||
|
case reflect.Slice:
|
||
|
if value.Len() == 0 {
|
||
|
return success
|
||
|
}
|
||
|
case reflect.Chan:
|
||
|
if value.Len() == 0 {
|
||
|
return success
|
||
|
}
|
||
|
case reflect.Map:
|
||
|
if value.Len() == 0 {
|
||
|
return success
|
||
|
}
|
||
|
case reflect.String:
|
||
|
if value.Len() == 0 {
|
||
|
return success
|
||
|
}
|
||
|
case reflect.Ptr:
|
||
|
elem := value.Elem()
|
||
|
kind := elem.Kind()
|
||
|
if (kind == reflect.Slice || kind == reflect.Array) && elem.Len() == 0 {
|
||
|
return success
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fmt.Sprintf(shouldHaveBeenEmpty, actual)
|
||
|
}
|
||
|
|
||
|
// ShouldNotBeEmpty receives a single parameter (actual) and determines whether or not
|
||
|
// calling len(actual) would return a value greater than zero. It obeys the rules
|
||
|
// specified by the `len` function for determining length: http://golang.org/pkg/builtin/#len
|
||
|
func ShouldNotBeEmpty(actual interface{}, expected ...interface{}) string {
|
||
|
if fail := need(0, expected); fail != success {
|
||
|
return fail
|
||
|
}
|
||
|
|
||
|
if empty := ShouldBeEmpty(actual, expected...); empty != success {
|
||
|
return success
|
||
|
}
|
||
|
return fmt.Sprintf(shouldNotHaveBeenEmpty, actual)
|
||
|
}
|
||
|
|
||
|
// ShouldHaveLength receives 2 parameters. The first is a collection to check
|
||
|
// the length of, the second being the expected length. It obeys the rules
|
||
|
// specified by the len function for determining length:
|
||
|
// http://golang.org/pkg/builtin/#len
|
||
|
func ShouldHaveLength(actual interface{}, expected ...interface{}) string {
|
||
|
if fail := need(1, expected); fail != success {
|
||
|
return fail
|
||
|
}
|
||
|
|
||
|
var expectedLen int64
|
||
|
lenValue := reflect.ValueOf(expected[0])
|
||
|
switch lenValue.Kind() {
|
||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
|
expectedLen = lenValue.Int()
|
||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||
|
expectedLen = int64(lenValue.Uint())
|
||
|
default:
|
||
|
return fmt.Sprintf(shouldHaveBeenAValidInteger, reflect.TypeOf(expected[0]))
|
||
|
}
|
||
|
|
||
|
if expectedLen < 0 {
|
||
|
return fmt.Sprintf(shouldHaveBeenAValidLength, expected[0])
|
||
|
}
|
||
|
|
||
|
value := reflect.ValueOf(actual)
|
||
|
switch value.Kind() {
|
||
|
case reflect.Slice,
|
||
|
reflect.Chan,
|
||
|
reflect.Map,
|
||
|
reflect.String:
|
||
|
if int64(value.Len()) == expectedLen {
|
||
|
return success
|
||
|
} else {
|
||
|
return fmt.Sprintf(shouldHaveHadLength, actual, value.Len(), expectedLen)
|
||
|
}
|
||
|
case reflect.Ptr:
|
||
|
elem := value.Elem()
|
||
|
kind := elem.Kind()
|
||
|
if kind == reflect.Slice || kind == reflect.Array {
|
||
|
if int64(elem.Len()) == expectedLen {
|
||
|
return success
|
||
|
} else {
|
||
|
return fmt.Sprintf(shouldHaveHadLength, actual, elem.Len(), expectedLen)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return fmt.Sprintf(shouldHaveBeenAValidCollection, reflect.TypeOf(actual))
|
||
|
}
|