1626 lines · 44.7 KB · Go
RawDownload
package assert import (	"bufio"	"bytes"	"encoding/json"	"errors"	"fmt"	"math"	"os"	"reflect"	"regexp"	"runtime"	"runtime/debug"	"strings"	"time"	"unicode"	"unicode/utf8" 	"github.com/davecgh/go-spew/spew"	"github.com/pmezard/go-difflib/difflib"	yaml "gopkg.in/yaml.v2") //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" // TestingT is an interface wrapper around *testing.Ttype 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 // ErrorAssertionFunc 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 failuretype Comparison func() (success bool) /*	Helper functions*/ // ObjectsAreEqual determines if two objects are considered equal.//// This function does no assertion of any kind.func ObjectsAreEqual(expected, actual interface{}) bool {	if expected == nil || actual == nil {		return 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// values are equal.func ObjectsAreEqualValues(expected, actual interface{}) bool {	if ObjectsAreEqual(expected, actual) {		return true	} 	actualType := reflect.TypeOf(actual)	if actualType == nil {		return false	}	expectedValue := reflect.ValueOf(expected)	if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {		// Attempt comparison after type conversion		return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)	} 	return false} /* CallerInfo is necessary because the assert functions use the testing objectinternally, causing it to print the file:line of the assert method, rather than wherethe problem actually occurred in calling code.*/ // CallerInfo returns an array of strings containing the file and line number// of each stack frame leading from the current test to the assert call that// failed.func CallerInfo() []string { 	pc := uintptr(0)	file := ""	line := 0	ok := false	name := "" 	callers := []string{}	for i := 0; ; i++ {		pc, file, line, ok = runtime.Caller(i)		if !ok {			// The breaks below failed to terminate the loop, and we ran off the			// end of the call stack.			break		} 		// This is a huge edge case, but it will panic if this is the case, see #180		if file == "<autogenerated>" {			break		} 		f := runtime.FuncForPC(pc)		if f == nil {			break		}		name = f.Name() 		// testing.tRunner is the standard library function that calls		// tests. Subtests are called directly by tRunner, without going through		// the Test/Benchmark/Example function that contains the t.Run calls, so		// with subtests we should break when we hit tRunner, without adding it		// to the list of callers.		if name == "testing.tRunner" {			break		} 		parts := strings.Split(file, "/")		file = parts[len(parts)-1]		if len(parts) > 1 {			dir := parts[len(parts)-2]			if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {				callers = append(callers, fmt.Sprintf("%s:%d", file, line))			}		} 		// Drop the package		segments := strings.Split(name, ".")		name = segments[len(segments)-1]		if isTest(name, "Test") ||			isTest(name, "Benchmark") ||			isTest(name, "Example") {			break		}	} 	return callers} // Stolen from the `go test` tool.// isTest tells whether name looks like a test (or benchmark, according to prefix).// It is a Test (say) if there is a character after Test that is not a lower-case letter.// We don't want TesticularCancer.func isTest(name, prefix string) bool {	if !strings.HasPrefix(name, prefix) {		return false	}	if len(name) == len(prefix) { // "Test" is ok		return true	}	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])	return !unicode.IsLower(rune)} func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {	if len(msgAndArgs) == 0 || msgAndArgs == nil {		return ""	}	if len(msgAndArgs) == 1 {		msg := msgAndArgs[0]		if msgAsStr, ok := msg.(string); ok {			return msgAsStr		}		return fmt.Sprintf("%+v", msg)	}	if len(msgAndArgs) > 1 {		return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)	}	return ""} // Aligns the provided message so that all lines after the first line start at the same location as the first line.// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab).// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the// basis on which the alignment occurs).func indentMessageLines(message string, longestLabelLen int) string {	outBuf := new(bytes.Buffer) 	for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {		// 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\t" + strings.Repeat(" ", longestLabelLen+1) + "\t")		}		outBuf.WriteString(scanner.Text())	} 	return outBuf.String()} type failNower interface {	FailNow()} // FailNow fails testfunc 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	// maintain backwards compatibility, so we fallback	// to panicking when FailNow is not available in	// TestingT.	// See issue #263 	if t, ok := t.(failNower); ok {		t.FailNow()	} else {		panic("test failed and t is missing `FailNow()`")	}	return false} // Fail reports a failure throughfunc Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {	if h, ok := t.(tHelper); ok {		h.Helper()	}	content := []labeledContent{		{"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("\n%s", ""+labeledOutput(content...)) 	return false} type labeledContent struct {	label   string	content string} // labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner:////   \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// alignment is achieved, "\t{{content}}\n" is added for the output.//// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line.func labeledOutput(content ...labeledContent) string {	longestLabel := 0	for _, v := range content {		if len(v.label) > longestLabel {			longestLabel = len(v.label)		}	}	var output string	for _, v := range content {		output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n"	}	return output} // Implements asserts that an object is implemented by the specified interface.////    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...)	} 	return true} // Equal asserts that two objects are equal.////    assert.Equal(t, 123, 123)//// 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...)	} 	if !ObjectsAreEqual(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...)	} 	return true } // validateEqualArgs checks whether provided arguments can be safely used in the// Equal/NotEqual functions.func validateEqualArgs(expected, actual interface{}) error {	if expected == nil && actual == nil {		return nil	} 	if isFunction(expected) || isFunction(actual) {		return errors.New("cannot take func type as argument")	}	return nil} // Same asserts that two pointers reference the same object.////    assert.Same(t, ptr1, ptr2)//// Both arguments must be pointer variables. Pointer variable sameness is// determined based on the equality of both type and value.func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {	if h, ok := t.(tHelper); ok {		h.Helper()	} 	if !samePointers(expected, actual) {		return Fail(t, fmt.Sprintf("Not same: \n"+			"expected: %p %#v\n"+			"actual  : %p %#v", expected, expected, actual, actual), msgAndArgs...)	} 	return true} // NotSame asserts that two pointers do not reference the same object.////    assert.NotSame(t, ptr1, ptr2)//// Both arguments must be pointer variables. Pointer variable sameness is// determined based on the equality of both type and value.func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {	if h, ok := t.(tHelper); ok {		h.Helper()	} 	if samePointers(expected, actual) {		return Fail(t, fmt.Sprintf(			"Expected and actual point to the same object: %p %#v",			expected, expected), msgAndArgs...)	}	return true} // samePointers compares two generic interface objects and returns whether// they point to the same objectfunc samePointers(first, second interface{}) bool {	firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second)	if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr {		return false	} 	firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second)	if firstType != secondType {		return false	} 	// compare pointer addresses	return first == second} // formatUnequalValues takes two values of arbitrary types and returns string// representations appropriate to be presented to the user.//// If the values are not of like type, the returned strings will be prefixed// with the type name, and the value will be enclosed in parenthesis similar// to a type conversion in the Go grammar.func formatUnequalValues(expected, actual interface{}) (e string, a string) {	if reflect.TypeOf(expected) != reflect.TypeOf(actual) {		return fmt.Sprintf("%T(%#v)", expected, expected),			fmt.Sprintf("%T(%#v)", actual, actual)	}	switch expected.(type) {	case time.Duration:		return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual)	}	return fmt.Sprintf("%#v", expected), fmt.Sprintf("%#v", actual)} // EqualValues asserts that two objects are equal or convertable to the same types// and equal.////    assert.EqualValues(t, uint32(123), int32(123))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...)	} 	return true } // Exactly asserts that two objects are equal in value and type.////    assert.Exactly(t, int32(123), int64(123))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\t%v != %v", aType, bType), msgAndArgs...)	} 	return Equal(t, expected, actual, msgAndArgs...) } // NotNil asserts that the specified object is not nil.////    assert.NotNil(t, err)func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {	if h, ok := t.(tHelper); ok {		h.Helper()	}	if !isNil(object) {		return true	}	return Fail(t, "Expected value not to be nil.", msgAndArgs...)} // containsKind checks if a specified kind in the slice of kinds.func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool {	for i := 0; i < len(kinds); i++ {		if kind == kinds[i] {			return true		}

Lines 1–500 of 1626.