aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/gotest.tools/assert
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2019-01-20 15:41:27 +0100
committerMichael Muré <batolettre@gmail.com>2019-03-01 22:40:22 +0100
commit14b240af8fef269d2c1d5dde2fff192b656c50f3 (patch)
tree4f6ea032789d811cd019bbb6c190c99a650084b2 /vendor/gotest.tools/assert
parentd10c76469d40f13e27739fd363145e89bf74c3e0 (diff)
downloadgit-bug-14b240af8fef269d2c1d5dde2fff192b656c50f3.tar.gz
identity: more cleaning and fixes after a code review
Diffstat (limited to 'vendor/gotest.tools/assert')
-rw-r--r--vendor/gotest.tools/assert/assert.go311
-rw-r--r--vendor/gotest.tools/assert/cmp/compare.go312
-rw-r--r--vendor/gotest.tools/assert/cmp/result.go94
-rw-r--r--vendor/gotest.tools/assert/result.go107
4 files changed, 0 insertions, 824 deletions
diff --git a/vendor/gotest.tools/assert/assert.go b/vendor/gotest.tools/assert/assert.go
deleted file mode 100644
index 05d66354..00000000
--- a/vendor/gotest.tools/assert/assert.go
+++ /dev/null
@@ -1,311 +0,0 @@
-/*Package assert provides assertions for comparing expected values to actual
-values. When an assertion fails a helpful error message is printed.
-
-Assert and Check
-
-Assert() and Check() both accept a Comparison, and fail the test when the
-comparison fails. The one difference is that Assert() will end the test execution
-immediately (using t.FailNow()) whereas Check() will fail the test (using t.Fail()),
-return the value of the comparison, then proceed with the rest of the test case.
-
-Example usage
-
-The example below shows assert used with some common types.
-
-
- import (
- "testing"
-
- "gotest.tools/assert"
- is "gotest.tools/assert/cmp"
- )
-
- func TestEverything(t *testing.T) {
- // booleans
- assert.Assert(t, ok)
- assert.Assert(t, !missing)
-
- // primitives
- assert.Equal(t, count, 1)
- assert.Equal(t, msg, "the message")
- assert.Assert(t, total != 10) // NotEqual
-
- // errors
- assert.NilError(t, closer.Close())
- assert.Error(t, err, "the exact error message")
- assert.ErrorContains(t, err, "includes this")
- assert.ErrorType(t, err, os.IsNotExist)
-
- // complex types
- assert.DeepEqual(t, result, myStruct{Name: "title"})
- assert.Assert(t, is.Len(items, 3))
- assert.Assert(t, len(sequence) != 0) // NotEmpty
- assert.Assert(t, is.Contains(mapping, "key"))
-
- // pointers and interface
- assert.Assert(t, is.Nil(ref))
- assert.Assert(t, ref != nil) // NotNil
- }
-
-Comparisons
-
-Package https://godoc.org/gotest.tools/assert/cmp provides
-many common comparisons. Additional comparisons can be written to compare
-values in other ways. See the example Assert (CustomComparison).
-
-Automated migration from testify
-
-gty-migrate-from-testify is a binary which can update source code which uses
-testify assertions to use the assertions provided by this package.
-
-See http://bit.do/cmd-gty-migrate-from-testify.
-
-
-*/
-package assert // import "gotest.tools/assert"
-
-import (
- "fmt"
- "go/ast"
- "go/token"
-
- gocmp "github.com/google/go-cmp/cmp"
- "gotest.tools/assert/cmp"
- "gotest.tools/internal/format"
- "gotest.tools/internal/source"
-)
-
-// BoolOrComparison can be a bool, or cmp.Comparison. See Assert() for usage.
-type BoolOrComparison interface{}
-
-// TestingT is the subset of testing.T used by the assert package.
-type TestingT interface {
- FailNow()
- Fail()
- Log(args ...interface{})
-}
-
-type helperT interface {
- Helper()
-}
-
-const failureMessage = "assertion failed: "
-
-// nolint: gocyclo
-func assert(
- t TestingT,
- failer func(),
- argSelector argSelector,
- comparison BoolOrComparison,
- msgAndArgs ...interface{},
-) bool {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- var success bool
- switch check := comparison.(type) {
- case bool:
- if check {
- return true
- }
- logFailureFromBool(t, msgAndArgs...)
-
- // Undocumented legacy comparison without Result type
- case func() (success bool, message string):
- success = runCompareFunc(t, check, msgAndArgs...)
-
- case nil:
- return true
-
- case error:
- msg := "error is not nil: "
- t.Log(format.WithCustomMessage(failureMessage+msg+check.Error(), msgAndArgs...))
-
- case cmp.Comparison:
- success = runComparison(t, argSelector, check, msgAndArgs...)
-
- case func() cmp.Result:
- success = runComparison(t, argSelector, check, msgAndArgs...)
-
- default:
- t.Log(fmt.Sprintf("invalid Comparison: %v (%T)", check, check))
- }
-
- if success {
- return true
- }
- failer()
- return false
-}
-
-func runCompareFunc(
- t TestingT,
- f func() (success bool, message string),
- msgAndArgs ...interface{},
-) bool {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- if success, message := f(); !success {
- t.Log(format.WithCustomMessage(failureMessage+message, msgAndArgs...))
- return false
- }
- return true
-}
-
-func logFailureFromBool(t TestingT, msgAndArgs ...interface{}) {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- const stackIndex = 3 // Assert()/Check(), assert(), formatFailureFromBool()
- const comparisonArgPos = 1
- args, err := source.CallExprArgs(stackIndex)
- if err != nil {
- t.Log(err.Error())
- return
- }
-
- msg, err := boolFailureMessage(args[comparisonArgPos])
- if err != nil {
- t.Log(err.Error())
- msg = "expression is false"
- }
-
- t.Log(format.WithCustomMessage(failureMessage+msg, msgAndArgs...))
-}
-
-func boolFailureMessage(expr ast.Expr) (string, error) {
- if binaryExpr, ok := expr.(*ast.BinaryExpr); ok && binaryExpr.Op == token.NEQ {
- x, err := source.FormatNode(binaryExpr.X)
- if err != nil {
- return "", err
- }
- y, err := source.FormatNode(binaryExpr.Y)
- if err != nil {
- return "", err
- }
- return x + " is " + y, nil
- }
-
- if unaryExpr, ok := expr.(*ast.UnaryExpr); ok && unaryExpr.Op == token.NOT {
- x, err := source.FormatNode(unaryExpr.X)
- if err != nil {
- return "", err
- }
- return x + " is true", nil
- }
-
- formatted, err := source.FormatNode(expr)
- if err != nil {
- return "", err
- }
- return "expression is false: " + formatted, nil
-}
-
-// Assert performs a comparison. If the comparison fails the test is marked as
-// failed, a failure message is logged, and execution is stopped immediately.
-//
-// The comparison argument may be one of three types: bool, cmp.Comparison or
-// error.
-// When called with a bool the failure message will contain the literal source
-// code of the expression.
-// When called with a cmp.Comparison the comparison is responsible for producing
-// a helpful failure message.
-// When called with an error a nil value is considered success. A non-nil error
-// is a failure, and Error() is used as the failure message.
-func Assert(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- assert(t, t.FailNow, argsFromComparisonCall, comparison, msgAndArgs...)
-}
-
-// Check performs a comparison. If the comparison fails the test is marked as
-// failed, a failure message is logged, and Check returns false. Otherwise returns
-// true.
-//
-// See Assert for details about the comparison arg and failure messages.
-func Check(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) bool {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- return assert(t, t.Fail, argsFromComparisonCall, comparison, msgAndArgs...)
-}
-
-// NilError fails the test immediately if err is not nil.
-// This is equivalent to Assert(t, err)
-func NilError(t TestingT, err error, msgAndArgs ...interface{}) {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- assert(t, t.FailNow, argsAfterT, err, msgAndArgs...)
-}
-
-// Equal uses the == operator to assert two values are equal and fails the test
-// if they are not equal.
-//
-// If the comparison fails Equal will use the variable names for x and y as part
-// of the failure message to identify the actual and expected values.
-//
-// If either x or y are a multi-line string the failure message will include a
-// unified diff of the two values. If the values only differ by whitespace
-// the unified diff will be augmented by replacing whitespace characters with
-// visible characters to identify the whitespace difference.
-//
-// This is equivalent to Assert(t, cmp.Equal(x, y)).
-func Equal(t TestingT, x, y interface{}, msgAndArgs ...interface{}) {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- assert(t, t.FailNow, argsAfterT, cmp.Equal(x, y), msgAndArgs...)
-}
-
-// DeepEqual uses google/go-cmp (http://bit.do/go-cmp) to assert two values are
-// equal and fails the test if they are not equal.
-//
-// Package https://godoc.org/gotest.tools/assert/opt provides some additional
-// commonly used Options.
-//
-// This is equivalent to Assert(t, cmp.DeepEqual(x, y)).
-func DeepEqual(t TestingT, x, y interface{}, opts ...gocmp.Option) {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- assert(t, t.FailNow, argsAfterT, cmp.DeepEqual(x, y, opts...))
-}
-
-// Error fails the test if err is nil, or the error message is not the expected
-// message.
-// Equivalent to Assert(t, cmp.Error(err, message)).
-func Error(t TestingT, err error, message string, msgAndArgs ...interface{}) {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- assert(t, t.FailNow, argsAfterT, cmp.Error(err, message), msgAndArgs...)
-}
-
-// ErrorContains fails the test if err is nil, or the error message does not
-// contain the expected substring.
-// Equivalent to Assert(t, cmp.ErrorContains(err, substring)).
-func ErrorContains(t TestingT, err error, substring string, msgAndArgs ...interface{}) {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- assert(t, t.FailNow, argsAfterT, cmp.ErrorContains(err, substring), msgAndArgs...)
-}
-
-// ErrorType fails the test if err is nil, or err is not the expected type.
-//
-// Expected can be one of:
-// a func(error) bool which returns true if the error is the expected type,
-// an instance of (or a pointer to) a struct of the expected type,
-// a pointer to an interface the error is expected to implement,
-// a reflect.Type of the expected struct or interface.
-//
-// Equivalent to Assert(t, cmp.ErrorType(err, expected)).
-func ErrorType(t TestingT, err error, expected interface{}, msgAndArgs ...interface{}) {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- assert(t, t.FailNow, argsAfterT, cmp.ErrorType(err, expected), msgAndArgs...)
-}
diff --git a/vendor/gotest.tools/assert/cmp/compare.go b/vendor/gotest.tools/assert/cmp/compare.go
deleted file mode 100644
index ae03749e..00000000
--- a/vendor/gotest.tools/assert/cmp/compare.go
+++ /dev/null
@@ -1,312 +0,0 @@
-/*Package cmp provides Comparisons for Assert and Check*/
-package cmp // import "gotest.tools/assert/cmp"
-
-import (
- "fmt"
- "reflect"
- "strings"
-
- "github.com/google/go-cmp/cmp"
- "gotest.tools/internal/format"
-)
-
-// Comparison is a function which compares values and returns ResultSuccess if
-// the actual value matches the expected value. If the values do not match the
-// Result will contain a message about why it failed.
-type Comparison func() Result
-
-// DeepEqual compares two values using google/go-cmp (http://bit.do/go-cmp)
-// and succeeds if the values are equal.
-//
-// The comparison can be customized using comparison Options.
-// Package https://godoc.org/gotest.tools/assert/opt provides some additional
-// commonly used Options.
-func DeepEqual(x, y interface{}, opts ...cmp.Option) Comparison {
- return func() (result Result) {
- defer func() {
- if panicmsg, handled := handleCmpPanic(recover()); handled {
- result = ResultFailure(panicmsg)
- }
- }()
- diff := cmp.Diff(x, y, opts...)
- if diff == "" {
- return ResultSuccess
- }
- return multiLineDiffResult(diff)
- }
-}
-
-func handleCmpPanic(r interface{}) (string, bool) {
- if r == nil {
- return "", false
- }
- panicmsg, ok := r.(string)
- if !ok {
- panic(r)
- }
- switch {
- case strings.HasPrefix(panicmsg, "cannot handle unexported field"):
- return panicmsg, true
- }
- panic(r)
-}
-
-func toResult(success bool, msg string) Result {
- if success {
- return ResultSuccess
- }
- return ResultFailure(msg)
-}
-
-// Equal succeeds if x == y. See assert.Equal for full documentation.
-func Equal(x, y interface{}) Comparison {
- return func() Result {
- switch {
- case x == y:
- return ResultSuccess
- case isMultiLineStringCompare(x, y):
- diff := format.UnifiedDiff(format.DiffConfig{A: x.(string), B: y.(string)})
- return multiLineDiffResult(diff)
- }
- return ResultFailureTemplate(`
- {{- .Data.x}} (
- {{- with callArg 0 }}{{ formatNode . }} {{end -}}
- {{- printf "%T" .Data.x -}}
- ) != {{ .Data.y}} (
- {{- with callArg 1 }}{{ formatNode . }} {{end -}}
- {{- printf "%T" .Data.y -}}
- )`,
- map[string]interface{}{"x": x, "y": y})
- }
-}
-
-func isMultiLineStringCompare(x, y interface{}) bool {
- strX, ok := x.(string)
- if !ok {
- return false
- }
- strY, ok := y.(string)
- if !ok {
- return false
- }
- return strings.Contains(strX, "\n") || strings.Contains(strY, "\n")
-}
-
-func multiLineDiffResult(diff string) Result {
- return ResultFailureTemplate(`
---- {{ with callArg 0 }}{{ formatNode . }}{{else}}←{{end}}
-+++ {{ with callArg 1 }}{{ formatNode . }}{{else}}→{{end}}
-{{ .Data.diff }}`,
- map[string]interface{}{"diff": diff})
-}
-
-// Len succeeds if the sequence has the expected length.
-func Len(seq interface{}, expected int) Comparison {
- return func() (result Result) {
- defer func() {
- if e := recover(); e != nil {
- result = ResultFailure(fmt.Sprintf("type %T does not have a length", seq))
- }
- }()
- value := reflect.ValueOf(seq)
- length := value.Len()
- if length == expected {
- return ResultSuccess
- }
- msg := fmt.Sprintf("expected %s (length %d) to have length %d", seq, length, expected)
- return ResultFailure(msg)
- }
-}
-
-// Contains succeeds if item is in collection. Collection may be a string, map,
-// slice, or array.
-//
-// If collection is a string, item must also be a string, and is compared using
-// strings.Contains().
-// If collection is a Map, contains will succeed if item is a key in the map.
-// If collection is a slice or array, item is compared to each item in the
-// sequence using reflect.DeepEqual().
-func Contains(collection interface{}, item interface{}) Comparison {
- return func() Result {
- colValue := reflect.ValueOf(collection)
- if !colValue.IsValid() {
- return ResultFailure(fmt.Sprintf("nil does not contain items"))
- }
- msg := fmt.Sprintf("%v does not contain %v", collection, item)
-
- itemValue := reflect.ValueOf(item)
- switch colValue.Type().Kind() {
- case reflect.String:
- if itemValue.Type().Kind() != reflect.String {
- return ResultFailure("string may only contain strings")
- }
- return toResult(
- strings.Contains(colValue.String(), itemValue.String()),
- fmt.Sprintf("string %q does not contain %q", collection, item))
-
- case reflect.Map:
- if itemValue.Type() != colValue.Type().Key() {
- return ResultFailure(fmt.Sprintf(
- "%v can not contain a %v key", colValue.Type(), itemValue.Type()))
- }
- return toResult(colValue.MapIndex(itemValue).IsValid(), msg)
-
- case reflect.Slice, reflect.Array:
- for i := 0; i < colValue.Len(); i++ {
- if reflect.DeepEqual(colValue.Index(i).Interface(), item) {
- return ResultSuccess
- }
- }
- return ResultFailure(msg)
- default:
- return ResultFailure(fmt.Sprintf("type %T does not contain items", collection))
- }
- }
-}
-
-// Panics succeeds if f() panics.
-func Panics(f func()) Comparison {
- return func() (result Result) {
- defer func() {
- if err := recover(); err != nil {
- result = ResultSuccess
- }
- }()
- f()
- return ResultFailure("did not panic")
- }
-}
-
-// Error succeeds if err is a non-nil error, and the error message equals the
-// expected message.
-func Error(err error, message string) Comparison {
- return func() Result {
- switch {
- case err == nil:
- return ResultFailure("expected an error, got nil")
- case err.Error() != message:
- return ResultFailure(fmt.Sprintf(
- "expected error %q, got %+v", message, err))
- }
- return ResultSuccess
- }
-}
-
-// ErrorContains succeeds if err is a non-nil error, and the error message contains
-// the expected substring.
-func ErrorContains(err error, substring string) Comparison {
- return func() Result {
- switch {
- case err == nil:
- return ResultFailure("expected an error, got nil")
- case !strings.Contains(err.Error(), substring):
- return ResultFailure(fmt.Sprintf(
- "expected error to contain %q, got %+v", substring, err))
- }
- return ResultSuccess
- }
-}
-
-// Nil succeeds if obj is a nil interface, pointer, or function.
-//
-// Use NilError() for comparing errors. Use Len(obj, 0) for comparing slices,
-// maps, and channels.
-func Nil(obj interface{}) Comparison {
- msgFunc := func(value reflect.Value) string {
- return fmt.Sprintf("%v (type %s) is not nil", reflect.Indirect(value), value.Type())
- }
- return isNil(obj, msgFunc)
-}
-
-func isNil(obj interface{}, msgFunc func(reflect.Value) string) Comparison {
- return func() Result {
- if obj == nil {
- return ResultSuccess
- }
- value := reflect.ValueOf(obj)
- kind := value.Type().Kind()
- if kind >= reflect.Chan && kind <= reflect.Slice {
- if value.IsNil() {
- return ResultSuccess
- }
- return ResultFailure(msgFunc(value))
- }
-
- return ResultFailure(fmt.Sprintf("%v (type %s) can not be nil", value, value.Type()))
- }
-}
-
-// ErrorType succeeds if err is not nil and is of the expected type.
-//
-// Expected can be one of:
-// a func(error) bool which returns true if the error is the expected type,
-// an instance of (or a pointer to) a struct of the expected type,
-// a pointer to an interface the error is expected to implement,
-// a reflect.Type of the expected struct or interface.
-func ErrorType(err error, expected interface{}) Comparison {
- return func() Result {
- switch expectedType := expected.(type) {
- case func(error) bool:
- return cmpErrorTypeFunc(err, expectedType)
- case reflect.Type:
- if expectedType.Kind() == reflect.Interface {
- return cmpErrorTypeImplementsType(err, expectedType)
- }
- return cmpErrorTypeEqualType(err, expectedType)
- case nil:
- return ResultFailure(fmt.Sprintf("invalid type for expected: nil"))
- }
-
- expectedType := reflect.TypeOf(expected)
- switch {
- case expectedType.Kind() == reflect.Struct, isPtrToStruct(expectedType):
- return cmpErrorTypeEqualType(err, expectedType)
- case isPtrToInterface(expectedType):
- return cmpErrorTypeImplementsType(err, expectedType.Elem())
- }
- return ResultFailure(fmt.Sprintf("invalid type for expected: %T", expected))
- }
-}
-
-func cmpErrorTypeFunc(err error, f func(error) bool) Result {
- if f(err) {
- return ResultSuccess
- }
- actual := "nil"
- if err != nil {
- actual = fmt.Sprintf("%s (%T)", err, err)
- }
- return ResultFailureTemplate(`error is {{ .Data.actual }}
- {{- with callArg 1 }}, not {{ formatNode . }}{{end -}}`,
- map[string]interface{}{"actual": actual})
-}
-
-func cmpErrorTypeEqualType(err error, expectedType reflect.Type) Result {
- if err == nil {
- return ResultFailure(fmt.Sprintf("error is nil, not %s", expectedType))
- }
- errValue := reflect.ValueOf(err)
- if errValue.Type() == expectedType {
- return ResultSuccess
- }
- return ResultFailure(fmt.Sprintf("error is %s (%T), not %s", err, err, expectedType))
-}
-
-func cmpErrorTypeImplementsType(err error, expectedType reflect.Type) Result {
- if err == nil {
- return ResultFailure(fmt.Sprintf("error is nil, not %s", expectedType))
- }
- errValue := reflect.ValueOf(err)
- if errValue.Type().Implements(expectedType) {
- return ResultSuccess
- }
- return ResultFailure(fmt.Sprintf("error is %s (%T), not %s", err, err, expectedType))
-}
-
-func isPtrToInterface(typ reflect.Type) bool {
- return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Interface
-}
-
-func isPtrToStruct(typ reflect.Type) bool {
- return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct
-}
diff --git a/vendor/gotest.tools/assert/cmp/result.go b/vendor/gotest.tools/assert/cmp/result.go
deleted file mode 100644
index 7c3c37dd..00000000
--- a/vendor/gotest.tools/assert/cmp/result.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package cmp
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "text/template"
-
- "gotest.tools/internal/source"
-)
-
-// Result of a Comparison.
-type Result interface {
- Success() bool
-}
-
-type result struct {
- success bool
- message string
-}
-
-func (r result) Success() bool {
- return r.success
-}
-
-func (r result) FailureMessage() string {
- return r.message
-}
-
-// ResultSuccess is a constant which is returned by a ComparisonWithResult to
-// indicate success.
-var ResultSuccess = result{success: true}
-
-// ResultFailure returns a failed Result with a failure message.
-func ResultFailure(message string) Result {
- return result{message: message}
-}
-
-// ResultFromError returns ResultSuccess if err is nil. Otherwise ResultFailure
-// is returned with the error message as the failure message.
-func ResultFromError(err error) Result {
- if err == nil {
- return ResultSuccess
- }
- return ResultFailure(err.Error())
-}
-
-type templatedResult struct {
- success bool
- template string
- data map[string]interface{}
-}
-
-func (r templatedResult) Success() bool {
- return r.success
-}
-
-func (r templatedResult) FailureMessage(args []ast.Expr) string {
- msg, err := renderMessage(r, args)
- if err != nil {
- return fmt.Sprintf("failed to render failure message: %s", err)
- }
- return msg
-}
-
-// ResultFailureTemplate returns a Result with a template string and data which
-// can be used to format a failure message. The template may access data from .Data,
-// the comparison args with the callArg function, and the formatNode function may
-// be used to format the call args.
-func ResultFailureTemplate(template string, data map[string]interface{}) Result {
- return templatedResult{template: template, data: data}
-}
-
-func renderMessage(result templatedResult, args []ast.Expr) (string, error) {
- tmpl := template.New("failure").Funcs(template.FuncMap{
- "formatNode": source.FormatNode,
- "callArg": func(index int) ast.Expr {
- if index >= len(args) {
- return nil
- }
- return args[index]
- },
- })
- var err error
- tmpl, err = tmpl.Parse(result.template)
- if err != nil {
- return "", err
- }
- buf := new(bytes.Buffer)
- err = tmpl.Execute(buf, map[string]interface{}{
- "Data": result.data,
- })
- return buf.String(), err
-}
diff --git a/vendor/gotest.tools/assert/result.go b/vendor/gotest.tools/assert/result.go
deleted file mode 100644
index 3900264d..00000000
--- a/vendor/gotest.tools/assert/result.go
+++ /dev/null
@@ -1,107 +0,0 @@
-package assert
-
-import (
- "fmt"
- "go/ast"
-
- "gotest.tools/assert/cmp"
- "gotest.tools/internal/format"
- "gotest.tools/internal/source"
-)
-
-func runComparison(
- t TestingT,
- argSelector argSelector,
- f cmp.Comparison,
- msgAndArgs ...interface{},
-) bool {
- if ht, ok := t.(helperT); ok {
- ht.Helper()
- }
- result := f()
- if result.Success() {
- return true
- }
-
- var message string
- switch typed := result.(type) {
- case resultWithComparisonArgs:
- const stackIndex = 3 // Assert/Check, assert, runComparison
- args, err := source.CallExprArgs(stackIndex)
- if err != nil {
- t.Log(err.Error())
- }
- message = typed.FailureMessage(filterPrintableExpr(argSelector(args)))
- case resultBasic:
- message = typed.FailureMessage()
- default:
- message = fmt.Sprintf("comparison returned invalid Result type: %T", result)
- }
-
- t.Log(format.WithCustomMessage(failureMessage+message, msgAndArgs...))
- return false
-}
-
-type resultWithComparisonArgs interface {
- FailureMessage(args []ast.Expr) string
-}
-
-type resultBasic interface {
- FailureMessage() string
-}
-
-// filterPrintableExpr filters the ast.Expr slice to only include Expr that are
-// easy to read when printed and contain relevant information to an assertion.
-//
-// Ident and SelectorExpr are included because they print nicely and the variable
-// names may provide additional context to their values.
-// BasicLit and CompositeLit are excluded because their source is equivalent to
-// their value, which is already available.
-// Other types are ignored for now, but could be added if they are relevant.
-func filterPrintableExpr(args []ast.Expr) []ast.Expr {
- result := make([]ast.Expr, len(args))
- for i, arg := range args {
- if isShortPrintableExpr(arg) {
- result[i] = arg
- continue
- }
-
- if starExpr, ok := arg.(*ast.StarExpr); ok {
- result[i] = starExpr.X
- continue
- }
- result[i] = nil
- }
- return result
-}
-
-func isShortPrintableExpr(expr ast.Expr) bool {
- switch expr.(type) {
- case *ast.Ident, *ast.SelectorExpr, *ast.IndexExpr, *ast.SliceExpr:
- return true
- case *ast.BinaryExpr, *ast.UnaryExpr:
- return true
- default:
- // CallExpr, ParenExpr, TypeAssertExpr, KeyValueExpr, StarExpr
- return false
- }
-}
-
-type argSelector func([]ast.Expr) []ast.Expr
-
-func argsAfterT(args []ast.Expr) []ast.Expr {
- if len(args) < 1 {
- return nil
- }
- return args[1:]
-}
-
-func argsFromComparisonCall(args []ast.Expr) []ast.Expr {
- if len(args) < 1 {
- return nil
- }
- if callExpr, ok := args[1].(*ast.CallExpr); ok {
- return callExpr.Args
- }
- return nil
-}