2018-06-08 12:09:51 -04:00
|
|
|
/*Package skip provides functions for skipping a test and printing the source code
|
|
|
|
of the condition used to skip the test.
|
|
|
|
*/
|
|
|
|
package skip // import "gotest.tools/skip"
|
2017-08-29 14:34:43 -04:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"path"
|
|
|
|
"reflect"
|
|
|
|
"runtime"
|
|
|
|
"strings"
|
|
|
|
|
2018-06-08 12:09:51 -04:00
|
|
|
"gotest.tools/internal/format"
|
|
|
|
"gotest.tools/internal/source"
|
2017-08-29 14:34:43 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
type skipT interface {
|
|
|
|
Skip(args ...interface{})
|
|
|
|
Log(args ...interface{})
|
|
|
|
}
|
|
|
|
|
2019-04-05 11:02:23 -04:00
|
|
|
// Result of skip function
|
|
|
|
type Result interface {
|
|
|
|
Skip() bool
|
|
|
|
Message() string
|
|
|
|
}
|
|
|
|
|
2018-01-16 17:20:43 -05:00
|
|
|
type helperT interface {
|
|
|
|
Helper()
|
|
|
|
}
|
|
|
|
|
2019-04-05 11:02:23 -04:00
|
|
|
// BoolOrCheckFunc can be a bool, func() bool, or func() Result. Other types will panic
|
2018-01-16 17:20:43 -05:00
|
|
|
type BoolOrCheckFunc interface{}
|
|
|
|
|
2019-04-05 11:02:23 -04:00
|
|
|
// If the condition expression evaluates to true, skip the test.
|
|
|
|
//
|
|
|
|
// The condition argument may be one of three types: bool, func() bool, or
|
|
|
|
// func() SkipResult.
|
|
|
|
// When called with a bool, the test will be skip if the condition evaluates to true.
|
|
|
|
// When called with a func() bool, the test will be skip if the function returns true.
|
|
|
|
// When called with a func() Result, the test will be skip if the Skip method
|
|
|
|
// of the result returns true.
|
2018-06-08 12:09:51 -04:00
|
|
|
// The skip message will contain the source code of the expression.
|
2019-04-05 11:02:23 -04:00
|
|
|
// Extra message text can be passed as a format string with args.
|
2018-01-16 17:20:43 -05:00
|
|
|
func If(t skipT, condition BoolOrCheckFunc, msgAndArgs ...interface{}) {
|
|
|
|
if ht, ok := t.(helperT); ok {
|
|
|
|
ht.Helper()
|
|
|
|
}
|
|
|
|
switch check := condition.(type) {
|
|
|
|
case bool:
|
|
|
|
ifCondition(t, check, msgAndArgs...)
|
|
|
|
case func() bool:
|
|
|
|
if check() {
|
|
|
|
t.Skip(format.WithCustomMessage(getFunctionName(check), msgAndArgs...))
|
|
|
|
}
|
2019-04-05 11:02:23 -04:00
|
|
|
case func() Result:
|
|
|
|
result := check()
|
|
|
|
if result.Skip() {
|
|
|
|
msg := getFunctionName(check) + ": " + result.Message()
|
|
|
|
t.Skip(format.WithCustomMessage(msg, msgAndArgs...))
|
|
|
|
}
|
2018-01-16 17:20:43 -05:00
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("invalid type for condition arg: %T", check))
|
2017-08-29 14:34:43 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-05 11:02:23 -04:00
|
|
|
func getFunctionName(function interface{}) string {
|
2017-08-29 14:34:43 -04:00
|
|
|
funcPath := runtime.FuncForPC(reflect.ValueOf(function).Pointer()).Name()
|
|
|
|
return strings.SplitN(path.Base(funcPath), ".", 2)[1]
|
|
|
|
}
|
|
|
|
|
2018-01-16 17:20:43 -05:00
|
|
|
func ifCondition(t skipT, condition bool, msgAndArgs ...interface{}) {
|
|
|
|
if ht, ok := t.(helperT); ok {
|
|
|
|
ht.Helper()
|
2017-08-29 14:34:43 -04:00
|
|
|
}
|
2018-01-16 17:20:43 -05:00
|
|
|
if !condition {
|
|
|
|
return
|
2017-08-29 14:34:43 -04:00
|
|
|
}
|
2018-01-16 17:20:43 -05:00
|
|
|
const (
|
|
|
|
stackIndex = 2
|
|
|
|
argPos = 1
|
|
|
|
)
|
2017-12-22 16:33:58 -05:00
|
|
|
source, err := source.FormattedCallExprArg(stackIndex, argPos)
|
2017-08-29 14:34:43 -04:00
|
|
|
if err != nil {
|
2018-01-16 17:20:43 -05:00
|
|
|
t.Log(err.Error())
|
|
|
|
t.Skip(format.Message(msgAndArgs...))
|
2017-08-29 14:34:43 -04:00
|
|
|
}
|
2018-01-16 17:20:43 -05:00
|
|
|
t.Skip(format.WithCustomMessage(source, msgAndArgs...))
|
2017-08-29 14:34:43 -04:00
|
|
|
}
|