go-kit/test/test.go

220 lines
5.3 KiB
Go

package test
import (
"bytes"
"fmt"
"path/filepath"
"reflect"
"runtime"
"strings"
"testing"
)
// Assert fails the test if the condition is false.
func Assert(tb testing.TB, condition bool, msg string, v ...interface{}) {
if !condition {
b := bytes.NewBufferString("\t" + msg + "\n")
fmt.Fprintln(b, v...)
print(b)
tb.FailNow()
}
}
// OK fails the test if an err is not nil.
func OK(tb testing.TB, err error) {
if err != nil {
print(bytes.NewBufferString(
fmt.Sprintf("\tUnexpected error: %v", err)))
tb.FailNow()
}
}
// NotNil fails the test if anything is nil.
func NotNil(tb testing.TB, anything interface{}) {
if isNil(anything) {
print(bytes.NewBufferString("\tExpected non-nil value"))
tb.FailNow()
}
}
// Nil fails the test if something is NOT nil.
func Nil(tb testing.TB, something interface{}) {
if !isNil(something) {
print(bytes.NewBufferString(
fmt.Sprintf("\tExpected value to be nil\n\n\tgot: %#v", something)))
tb.FailNow()
}
}
// Equals fails the test if exp is not equal to act.
func Equals(tb testing.TB, exp, act interface{}) {
if b, ok := equals(exp, act); !ok {
print(b)
tb.FailNow()
}
}
func equals(exp, act interface{}) (b *bytes.Buffer, ok bool) {
b = new(bytes.Buffer)
fmt.Fprintf(b, "\texp: %s\n\n\tgot: %s", stringer(exp), stringer(act))
return b, reflect.DeepEqual(exp, act)
}
// Includes fails if expected string is NOT included in the actual string
func Includes(tb testing.TB, exp string, act ...string) {
for _, a := range act {
if strings.Index(a, exp) >= 0 {
return
}
}
print(bytes.NewBufferString(
fmt.Sprintf("\tExpected to include: %s\n\n\tgot: %s", exp, act)))
tb.FailNow()
}
// NotIncludes fails if expected string is included in the actual string
func NotIncludes(tb testing.TB, exp string, act ...string) {
for _, a := range act {
if strings.Index(a, exp) >= 0 {
print(bytes.NewBufferString(
fmt.Sprintf("\tNOT expected to include: %#v\n\n\tgot: %#v", exp, act)))
tb.FailNow()
}
}
}
// IncludesI fails if expected string is NOT included in the actuall string (ignore case)
func IncludesI(tb testing.TB, exp string, act ...string) {
for _, a := range act {
if strings.Index(strings.ToLower(a), strings.ToLower(exp)) >= 0 {
return
}
}
print(bytes.NewBufferString(
fmt.Sprintf("\tExpected to include: %s\n\n\tgot: %s", exp, act)))
tb.FailNow()
}
// IncludesSlice fails if all of expected items is NOT included in the actual slice
func IncludesSlice(tb testing.TB, exp, act interface{}) {
if reflect.ValueOf(exp).Kind() != reflect.Slice {
panic("IncludesSlice requires a expected slice")
}
if reflect.ValueOf(act).Kind() != reflect.Slice {
panic("IncludesSlice requires a actual slice")
}
expSlice := reflect.ValueOf(exp)
actSlice := reflect.ValueOf(act)
expLen := expSlice.Len()
actLen := actSlice.Len()
if expLen <= actLen {
var score int
for idxA := 0; idxA < actLen; idxA++ {
for idxE := 0; idxE < expLen; idxE++ {
if reflect.DeepEqual(expSlice.Index(idxE).Interface(), actSlice.Index(idxA).Interface()) {
score++
}
}
}
if score == expLen {
return
}
}
print(bytes.NewBufferString(
fmt.Sprintf("\tExpected to all items to be included: %+v\n\n\tIn: %+v", exp, act)))
tb.FailNow()
}
// IncludesMap fails if all of expected map entries are NOT included in the actuall map
func IncludesMap(tb testing.TB, exp, act interface{}) {
if b, ok := includesMap(exp, act); !ok {
print(b)
tb.FailNow()
}
}
func includesMap(exp, act interface{}) (b *bytes.Buffer, ok bool) {
if reflect.ValueOf(exp).Kind() != reflect.Map {
panic("IncludesMap requires a expected map")
}
if reflect.ValueOf(act).Kind() != reflect.Map {
panic("IncludesMap requires a actual map")
}
expMap := reflect.ValueOf(exp)
actMap := reflect.ValueOf(act)
expLen := len(expMap.MapKeys())
actLen := len(actMap.MapKeys())
if expLen <= actLen {
var score int
for _, actKey := range actMap.MapKeys() {
for _, expKey := range expMap.MapKeys() {
if reflect.DeepEqual(expKey.Interface(), actKey.Interface()) &&
reflect.DeepEqual(expMap.MapIndex(expKey).Interface(), actMap.MapIndex(actKey).Interface()) {
score++
}
}
}
if score == expLen {
return b, true
}
}
fmt.Fprintf(b, "\tExpected to all items to be included: %+v\n\n\tIn: %+v", exp, act)
return b, false
}
// Zero fails the test if anything is NOT nil.
func Zero(tb testing.TB, anything interface{}) {
if !isZero(anything) {
print(bytes.NewBufferString("\tExpected zero value"))
tb.FailNow()
}
}
// NotZero fails the test if anything is NOT nil.
func NotZero(tb testing.TB, anything interface{}) {
if isZero(anything) {
print(bytes.NewBufferString("\tExpected non-zero value"))
tb.FailNow()
}
}
func isZero(anything interface{}) bool {
refZero := reflect.Zero(reflect.ValueOf(anything).Type())
return reflect.DeepEqual(refZero.Interface(), anything)
}
func isNil(anything interface{}) bool {
return reflect.DeepEqual(reflect.ValueOf(nil), reflect.ValueOf(anything)) ||
reflect.ValueOf(anything).IsNil()
}
func print(b *bytes.Buffer) {
_, file, line, _ := runtime.Caller(2)
fmt.Printf("\033[31m%s:%d:\n\n%s\033[39m\n\n",
filepath.Base(file), line, b.String())
}
func stringer(a interface{}) string {
switch s := a.(type) {
case string:
return s
case []byte:
return string(s)
default:
return fmt.Sprintf("%#v", s)
}
}