vendor: gotest.tools v3.0.3

- assert: fixes a bug that would cause a panic if there were any
  function calls before `assert.Check` on the same line
- golden: create the directory if it does not exist, when run with
  `-test.update-golden`

full diff: https://github.com/gotestyourself/gotest.tools/compare/v3.0.2...v3.0.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2020-11-23 12:33:57 +01:00
parent 6c0a036dce
commit 776cadc7db
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
12 changed files with 264 additions and 252 deletions

View File

@ -24,7 +24,7 @@ golang.org/x/sys eeed37f84f13f52d35e095e8023b
github.com/docker/go-units 519db1ee28dcc9fd2474ae59fca29a810482bfb1 # v0.4.0 github.com/docker/go-units 519db1ee28dcc9fd2474ae59fca29a810482bfb1 # v0.4.0
github.com/docker/go-connections 7395e3f8aa162843a74ed6d48e79627d9792ac55 # v0.4.0 github.com/docker/go-connections 7395e3f8aa162843a74ed6d48e79627d9792ac55 # v0.4.0
golang.org/x/text 23ae387dee1f90d29a23c0e87ee0b46038fbed0e # v0.3.3 golang.org/x/text 23ae387dee1f90d29a23c0e87ee0b46038fbed0e # v0.3.3
gotest.tools/v3 bb0d8a963040ea5048dcef1a14d8f8b58a33d4b3 # v3.0.2 gotest.tools/v3 568bc57cc5c19a2ef85e5749870b49a4cc2ab54d # v3.0.3
github.com/google/go-cmp 3af367b6b30c263d47e8895973edcca9a49cf029 # v0.2.0 github.com/google/go-cmp 3af367b6b30c263d47e8895973edcca9a49cf029 # v0.2.0
github.com/syndtr/gocapability 42c35b4376354fd554efc7ad35e0b7f94e3a0ffb github.com/syndtr/gocapability 42c35b4376354fd554efc7ad35e0b7f94e3a0ffb

View File

@ -2,7 +2,7 @@
A collection of packages to augment `testing` and support common patterns. A collection of packages to augment `testing` and support common patterns.
[![GoDoc](https://godoc.org/gotest.tools?status.svg)](http://gotest.tools) [![GoDoc](https://godoc.org/gotest.tools?status.svg)](https://pkg.go.dev/gotest.tools/v3/?tab=subdirectories)
[![CircleCI](https://circleci.com/gh/gotestyourself/gotest.tools/tree/master.svg?style=shield)](https://circleci.com/gh/gotestyourself/gotest.tools/tree/master) [![CircleCI](https://circleci.com/gh/gotestyourself/gotest.tools/tree/master.svg?style=shield)](https://circleci.com/gh/gotestyourself/gotest.tools/tree/master)
[![Go Reportcard](https://goreportcard.com/badge/gotest.tools)](https://goreportcard.com/report/gotest.tools) [![Go Reportcard](https://goreportcard.com/badge/gotest.tools)](https://goreportcard.com/report/gotest.tools)
@ -24,19 +24,19 @@ module paths pin to version `v2.3.0`.
## Packages ## Packages
* [assert](http://gotest.tools/assert) - * [assert](http://pkg.go.dev/gotest.tools/v3/assert) -
compare values and fail the test when a comparison fails compare values and fail the test when a comparison fails
* [env](http://gotest.tools/env) - * [env](http://pkg.go.dev/gotest.tools/v3/env) -
test code which uses environment variables test code which uses environment variables
* [fs](http://gotest.tools/fs) - * [fs](http://pkg.go.dev/gotest.tools/v3/fs) -
create temporary files and compare a filesystem tree to an expected value create temporary files and compare a filesystem tree to an expected value
* [golden](http://gotest.tools/golden) - * [golden](http://pkg.go.dev/gotest.tools/v3/golden) -
compare large multi-line strings against values frozen in golden files compare large multi-line strings against values frozen in golden files
* [icmd](http://gotest.tools/icmd) - * [icmd](http://pkg.go.dev/gotest.tools/v3/icmd) -
execute binaries and test the output execute binaries and test the output
* [poll](http://gotest.tools/poll) - * [poll](http://pkg.go.dev/gotest.tools/v3/poll) -
test asynchronous code by polling until a desired state is reached test asynchronous code by polling until a desired state is reached
* [skip](http://gotest.tools/skip) - * [skip](http://pkg.go.dev/gotest.tools/v3/skip) -
skip a test and print the source code of the condition used to skip the test skip a test and print the source code of the condition used to skip the test
## Related ## Related

View File

@ -49,7 +49,7 @@ The example below shows assert used with some common types.
Comparisons Comparisons
Package http://gotest.tools/assert/cmp provides Package http://pkg.go.dev/gotest.tools/v3/assert/cmp provides
many common comparisons. Additional comparisons can be written to compare many common comparisons. Additional comparisons can be written to compare
values in other ways. See the example Assert (CustomComparison). values in other ways. See the example Assert (CustomComparison).
@ -58,22 +58,16 @@ Automated migration from testify
gty-migrate-from-testify is a command which translates Go source code from gty-migrate-from-testify is a command which translates Go source code from
testify assertions to the assertions provided by this package. testify assertions to the assertions provided by this package.
See http://gotest.tools/assert/cmd/gty-migrate-from-testify. See http://pkg.go.dev/gotest.tools/v3/assert/cmd/gty-migrate-from-testify.
*/ */
package assert // import "gotest.tools/v3/assert" package assert // import "gotest.tools/v3/assert"
import ( import (
"fmt"
"go/ast"
"go/token"
"reflect"
gocmp "github.com/google/go-cmp/cmp" gocmp "github.com/google/go-cmp/cmp"
"gotest.tools/v3/assert/cmp" "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/internal/format" "gotest.tools/v3/internal/assert"
"gotest.tools/v3/internal/source"
) )
// BoolOrComparison can be a bool, or cmp.Comparison. See Assert() for usage. // BoolOrComparison can be a bool, or cmp.Comparison. See Assert() for usage.
@ -90,128 +84,6 @@ type helperT interface {
Helper() 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 := failureMsgFromError(check)
t.Log(format.WithCustomMessage(failureMessage+msg, 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 failureMsgFromError(err error) string {
// Handle errors with non-nil types
v := reflect.ValueOf(err)
if v.Kind() == reflect.Ptr && v.IsNil() {
return fmt.Sprintf("error is not nil: error has type %T", err)
}
return "error is not nil: " + err.Error()
}
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 // Assert performs a comparison. If the comparison fails, the test is marked as
// failed, a failure message is logged, and execution is stopped immediately. // failed, a failure message is logged, and execution is stopped immediately.
// //
@ -222,7 +94,7 @@ func boolFailureMessage(expr ast.Expr) (string, error) {
// cmp.Comparison // cmp.Comparison
// Uses cmp.Result.Success() to check for success of failure. // Uses cmp.Result.Success() to check for success of failure.
// The comparison is responsible for producing a helpful failure message. // The comparison is responsible for producing a helpful failure message.
// http://gotest.tools/assert/cmp provides many common comparisons. // http://pkg.go.dev/gotest.tools/v3/assert/cmp provides many common comparisons.
// error // error
// A nil value is considered success. // A nil value is considered success.
// A non-nil error is a failure, err.Error() is used as the failure message. // A non-nil error is a failure, err.Error() is used as the failure message.
@ -230,7 +102,9 @@ func Assert(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{})
if ht, ok := t.(helperT); ok { if ht, ok := t.(helperT); ok {
ht.Helper() ht.Helper()
} }
assert(t, t.FailNow, argsFromComparisonCall, comparison, msgAndArgs...) if !assert.Eval(t, assert.ArgsFromComparisonCall, comparison, msgAndArgs...) {
t.FailNow()
}
} }
// Check performs a comparison. If the comparison fails the test is marked as // Check performs a comparison. If the comparison fails the test is marked as
@ -242,7 +116,11 @@ func Check(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) b
if ht, ok := t.(helperT); ok { if ht, ok := t.(helperT); ok {
ht.Helper() ht.Helper()
} }
return assert(t, t.Fail, argsFromComparisonCall, comparison, msgAndArgs...) if !assert.Eval(t, assert.ArgsFromComparisonCall, comparison, msgAndArgs...) {
t.Fail()
return false
}
return true
} }
// NilError fails the test immediately if err is not nil. // NilError fails the test immediately if err is not nil.
@ -251,7 +129,9 @@ func NilError(t TestingT, err error, msgAndArgs ...interface{}) {
if ht, ok := t.(helperT); ok { if ht, ok := t.(helperT); ok {
ht.Helper() ht.Helper()
} }
assert(t, t.FailNow, argsAfterT, err, msgAndArgs...) if !assert.Eval(t, assert.ArgsAfterT, err, msgAndArgs...) {
t.FailNow()
}
} }
// Equal uses the == operator to assert two values are equal and fails the test // Equal uses the == operator to assert two values are equal and fails the test
@ -270,13 +150,15 @@ func Equal(t TestingT, x, y interface{}, msgAndArgs ...interface{}) {
if ht, ok := t.(helperT); ok { if ht, ok := t.(helperT); ok {
ht.Helper() ht.Helper()
} }
assert(t, t.FailNow, argsAfterT, cmp.Equal(x, y), msgAndArgs...) if !assert.Eval(t, assert.ArgsAfterT, cmp.Equal(x, y), msgAndArgs...) {
t.FailNow()
}
} }
// DeepEqual uses google/go-cmp (https://godoc.org/github.com/google/go-cmp/cmp) // DeepEqual uses google/go-cmp (https://godoc.org/github.com/google/go-cmp/cmp)
// to assert two values are equal and fails the test if they are not equal. // to assert two values are equal and fails the test if they are not equal.
// //
// Package http://gotest.tools/assert/opt provides some additional // Package http://pkg.go.dev/gotest.tools/v3/assert/opt provides some additional
// commonly used Options. // commonly used Options.
// //
// This is equivalent to Assert(t, cmp.DeepEqual(x, y)). // This is equivalent to Assert(t, cmp.DeepEqual(x, y)).
@ -284,7 +166,9 @@ func DeepEqual(t TestingT, x, y interface{}, opts ...gocmp.Option) {
if ht, ok := t.(helperT); ok { if ht, ok := t.(helperT); ok {
ht.Helper() ht.Helper()
} }
assert(t, t.FailNow, argsAfterT, cmp.DeepEqual(x, y, opts...)) if !assert.Eval(t, assert.ArgsAfterT, cmp.DeepEqual(x, y, opts...)) {
t.FailNow()
}
} }
// Error fails the test if err is nil, or the error message is not the expected // Error fails the test if err is nil, or the error message is not the expected
@ -294,7 +178,9 @@ func Error(t TestingT, err error, message string, msgAndArgs ...interface{}) {
if ht, ok := t.(helperT); ok { if ht, ok := t.(helperT); ok {
ht.Helper() ht.Helper()
} }
assert(t, t.FailNow, argsAfterT, cmp.Error(err, message), msgAndArgs...) if !assert.Eval(t, assert.ArgsAfterT, cmp.Error(err, message), msgAndArgs...) {
t.FailNow()
}
} }
// ErrorContains fails the test if err is nil, or the error message does not // ErrorContains fails the test if err is nil, or the error message does not
@ -304,7 +190,9 @@ func ErrorContains(t TestingT, err error, substring string, msgAndArgs ...interf
if ht, ok := t.(helperT); ok { if ht, ok := t.(helperT); ok {
ht.Helper() ht.Helper()
} }
assert(t, t.FailNow, argsAfterT, cmp.ErrorContains(err, substring), msgAndArgs...) if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorContains(err, substring), msgAndArgs...) {
t.FailNow()
}
} }
// ErrorType fails the test if err is nil, or err is not the expected type. // ErrorType fails the test if err is nil, or err is not the expected type.
@ -325,5 +213,7 @@ func ErrorType(t TestingT, err error, expected interface{}, msgAndArgs ...interf
if ht, ok := t.(helperT); ok { if ht, ok := t.(helperT); ok {
ht.Helper() ht.Helper()
} }
assert(t, t.FailNow, argsAfterT, cmp.ErrorType(err, expected), msgAndArgs...) if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorType(err, expected), msgAndArgs...) {
t.FailNow()
}
} }

View File

@ -21,7 +21,7 @@ type Comparison func() Result
// and succeeds if the values are equal. // and succeeds if the values are equal.
// //
// The comparison can be customized using comparison Options. // The comparison can be customized using comparison Options.
// Package http://gotest.tools/assert/opt provides some additional // Package http://pkg.go.dev/gotest.tools/v3/assert/opt provides some additional
// commonly used Options. // commonly used Options.
func DeepEqual(x, y interface{}, opts ...cmp.Option) Comparison { func DeepEqual(x, y interface{}, opts ...cmp.Option) Comparison {
return func() (result Result) { return func() (result Result) {

View File

@ -52,13 +52,12 @@ func ResultFromError(err error) Result {
} }
type templatedResult struct { type templatedResult struct {
success bool
template string template string
data map[string]interface{} data map[string]interface{}
} }
func (r templatedResult) Success() bool { func (r templatedResult) Success() bool {
return r.success return false
} }
func (r templatedResult) FailureMessage(args []ast.Expr) string { func (r templatedResult) FailureMessage(args []ast.Expr) string {

View File

@ -1,7 +1,7 @@
module gotest.tools/v3 module gotest.tools/v3
require ( require (
github.com/google/go-cmp v0.3.0 github.com/google/go-cmp v0.4.0
github.com/pkg/errors v0.8.1 github.com/pkg/errors v0.8.1
github.com/spf13/pflag v1.0.3 github.com/spf13/pflag v1.0.3
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4 golang.org/x/tools v0.0.0-20190624222133-a101b041ded4

View File

@ -0,0 +1,143 @@
package assert
import (
"fmt"
"go/ast"
"go/token"
"reflect"
"gotest.tools/v3/assert/cmp"
"gotest.tools/v3/internal/format"
"gotest.tools/v3/internal/source"
)
// LogT is the subset of testing.T used by the assert package.
type LogT interface {
Log(args ...interface{})
}
type helperT interface {
Helper()
}
const failureMessage = "assertion failed: "
// Eval the comparison and print a failure messages if the comparison has failed.
// nolint: gocyclo
func Eval(
t LogT,
argSelector argSelector,
comparison interface{},
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 := failureMsgFromError(check)
t.Log(format.WithCustomMessage(failureMessage+msg, 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))
}
return success
}
func runCompareFunc(
t LogT,
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 LogT, msgAndArgs ...interface{}) {
if ht, ok := t.(helperT); ok {
ht.Helper()
}
const stackIndex = 3 // Assert()/Check(), assert(), logFailureFromBool()
args, err := source.CallExprArgs(stackIndex)
if err != nil {
t.Log(err.Error())
return
}
const comparisonArgIndex = 1 // Assert(t, comparison)
if len(args) <= comparisonArgIndex {
t.Log(failureMessage + "but assert failed to find the expression to print")
return
}
msg, err := boolFailureMessage(args[comparisonArgIndex])
if err != nil {
t.Log(err.Error())
msg = "expression is false"
}
t.Log(format.WithCustomMessage(failureMessage+msg, msgAndArgs...))
}
func failureMsgFromError(err error) string {
// Handle errors with non-nil types
v := reflect.ValueOf(err)
if v.Kind() == reflect.Ptr && v.IsNil() {
return fmt.Sprintf("error is not nil: error has type %T", err)
}
return "error is not nil: " + err.Error()
}
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
}

View File

@ -9,8 +9,10 @@ import (
"gotest.tools/v3/internal/source" "gotest.tools/v3/internal/source"
) )
func runComparison( // RunComparison and return Comparison.Success. If the comparison fails a messages
t TestingT, // will be printed using t.Log.
func RunComparison(
t LogT,
argSelector argSelector, argSelector argSelector,
f cmp.Comparison, f cmp.Comparison,
msgAndArgs ...interface{}, msgAndArgs ...interface{},
@ -26,7 +28,7 @@ func runComparison(
var message string var message string
switch typed := result.(type) { switch typed := result.(type) {
case resultWithComparisonArgs: case resultWithComparisonArgs:
const stackIndex = 3 // Assert/Check, assert, runComparison const stackIndex = 3 // Assert/Check, assert, RunComparison
args, err := source.CallExprArgs(stackIndex) args, err := source.CallExprArgs(stackIndex)
if err != nil { if err != nil {
t.Log(err.Error()) t.Log(err.Error())
@ -88,15 +90,20 @@ func isShortPrintableExpr(expr ast.Expr) bool {
type argSelector func([]ast.Expr) []ast.Expr type argSelector func([]ast.Expr) []ast.Expr
func argsAfterT(args []ast.Expr) []ast.Expr { // ArgsAfterT selects args starting at position 1. Used when the caller has a
// testing.T as the first argument, and the args to select should follow it.
func ArgsAfterT(args []ast.Expr) []ast.Expr {
if len(args) < 1 { if len(args) < 1 {
return nil return nil
} }
return args[1:] return args[1:]
} }
func argsFromComparisonCall(args []ast.Expr) []ast.Expr { // ArgsFromComparisonCall selects args from the CallExpression at position 1.
if len(args) < 1 { // Used when the caller has a testing.T as the first argument, and the args to
// select are passed to the cmp.Comparison at position 1.
func ArgsFromComparisonCall(args []ast.Expr) []ast.Expr {
if len(args) <= 1 {
return nil return nil
} }
if callExpr, ok := args[1].(*ast.CallExpr); ok { if callExpr, ok := args[1].(*ast.CallExpr); ok {
@ -104,3 +111,15 @@ func argsFromComparisonCall(args []ast.Expr) []ast.Expr {
} }
return nil return nil
} }
// ArgsAtZeroIndex selects args from the CallExpression at position 1.
// Used when the caller accepts a single cmp.Comparison argument.
func ArgsAtZeroIndex(args []ast.Expr) []ast.Expr {
if len(args) == 0 {
return nil
}
if callExpr, ok := args[0].(*ast.CallExpr); ok {
return callExpr.Args
}
return nil
}

View File

@ -6,14 +6,17 @@ package cleanup
import ( import (
"os" "os"
"strings" "strings"
"gotest.tools/v3/x/subtest"
) )
type cleanupT interface { type cleanupT interface {
Cleanup(f func()) Cleanup(f func())
} }
// implemented by gotest.tools/x/subtest.TestContext
type addCleanupT interface {
AddCleanup(f func())
}
type logT interface { type logT interface {
Log(...interface{}) Log(...interface{})
} }
@ -39,7 +42,7 @@ func Cleanup(t logT, f func()) {
ct.Cleanup(f) ct.Cleanup(f)
return return
} }
if tc, ok := t.(subtest.TestContext); ok { if tc, ok := t.(addCleanupT); ok {
tc.AddCleanup(f) tc.AddCleanup(f)
} }
} }

View File

@ -93,8 +93,9 @@ func nodePosition(fileset *token.FileSet, node ast.Node) token.Position {
} }
// GoVersionLessThan returns true if runtime.Version() is semantically less than // GoVersionLessThan returns true if runtime.Version() is semantically less than
// version 1.minor. // version major.minor. Returns false if a release version can not be parsed from
func GoVersionLessThan(minor int64) bool { // runtime.Version().
func GoVersionLessThan(major, minor int64) bool {
version := runtime.Version() version := runtime.Version()
// not a release version // not a release version
if !strings.HasPrefix(version, "go") { if !strings.HasPrefix(version, "go") {
@ -105,11 +106,21 @@ func GoVersionLessThan(minor int64) bool {
if len(parts) < 2 { if len(parts) < 2 {
return false return false
} }
actual, err := strconv.ParseInt(parts[1], 10, 32) rMajor, err := strconv.ParseInt(parts[0], 10, 32)
return err == nil && parts[0] == "1" && actual < minor if err != nil {
return false
}
if rMajor != major {
return rMajor < major
}
rMinor, err := strconv.ParseInt(parts[1], 10, 32)
if err != nil {
return false
}
return rMinor < minor
} }
var goVersionBefore19 = GoVersionLessThan(9) var goVersionBefore19 = GoVersionLessThan(1, 9)
func getCallExprArgs(node ast.Node) ([]ast.Expr, error) { func getCallExprArgs(node ast.Node) ([]ast.Expr, error) {
visitor := &callExprVisitor{} visitor := &callExprVisitor{}

View File

@ -4,7 +4,11 @@ package poll // import "gotest.tools/v3/poll"
import ( import (
"fmt" "fmt"
"strings"
"time" "time"
"gotest.tools/v3/assert/cmp"
"gotest.tools/v3/internal/assert"
) )
// TestingT is the subset of testing.T used by WaitOn // TestingT is the subset of testing.T used by WaitOn
@ -138,3 +142,30 @@ func WaitOn(t TestingT, check Check, pollOps ...SettingOp) {
} }
} }
} }
// Compare values using the cmp.Comparison. If the comparison fails return a
// result which indicates to WaitOn that it should continue waiting.
// If the comparison is successful then WaitOn stops polling.
func Compare(compare cmp.Comparison) Result {
buf := new(logBuffer)
if assert.RunComparison(buf, assert.ArgsAtZeroIndex, compare) {
return Success()
}
return Continue(buf.String())
}
type logBuffer struct {
log [][]interface{}
}
func (c *logBuffer) Log(args ...interface{}) {
c.log = append(c.log, args)
}
func (c *logBuffer) String() string {
b := new(strings.Builder)
for _, item := range c.log {
b.WriteString(fmt.Sprint(item...) + " ")
}
return b.String()
}

View File

@ -1,84 +0,0 @@
/*Package subtest provides a TestContext to subtests which handles cleanup, and
provides a testing.TB, and context.Context.
This package was inspired by github.com/frankban/quicktest.
*/
package subtest // import "gotest.tools/v3/x/subtest"
import (
"context"
"testing"
)
type testcase struct {
testing.TB
ctx context.Context
cleanupFuncs []cleanupFunc
}
type cleanupFunc func()
func (tc *testcase) Ctx() context.Context {
if tc.ctx == nil {
var cancel func()
tc.ctx, cancel = context.WithCancel(context.Background())
tc.AddCleanup(cancel)
}
return tc.ctx
}
// cleanup runs all cleanup functions. Functions are run in the opposite order
// in which they were added. Cleanup is called automatically before Run exits.
func (tc *testcase) cleanup() {
for _, f := range tc.cleanupFuncs {
// Defer all cleanup functions so they all run even if one calls
// t.FailNow() or panics. Deferring them also runs them in reverse order.
defer f()
}
tc.cleanupFuncs = nil
}
func (tc *testcase) AddCleanup(f func()) {
tc.cleanupFuncs = append(tc.cleanupFuncs, f)
}
func (tc *testcase) Parallel() {
tp, ok := tc.TB.(parallel)
if !ok {
panic("Parallel called with a testing.B")
}
tp.Parallel()
}
type parallel interface {
Parallel()
}
// Run a subtest. When subtest exits, every cleanup function added with
// TestContext.AddCleanup will be run.
func Run(t *testing.T, name string, subtest func(t TestContext)) bool {
return t.Run(name, func(t *testing.T) {
tc := &testcase{TB: t}
defer tc.cleanup()
subtest(tc)
})
}
// TestContext provides a testing.TB and a context.Context for a test case.
type TestContext interface {
testing.TB
// AddCleanup function which will be run when before Run returns.
//
// Deprecated: Go 1.14+ now includes a testing.TB.Cleanup(func()) which
// should be used instead. AddCleanup will be removed in a future release.
AddCleanup(f func())
// Ctx returns a context for the test case. Multiple calls from the same subtest
// will return the same context. The context is cancelled when Run
// returns.
Ctx() context.Context
// Parallel calls t.Parallel on the testing.TB. Panics if testing.TB does
// not implement Parallel.
Parallel()
}
var _ TestContext = &testcase{}