/*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/v3/skip" import ( "fmt" "path" "reflect" "runtime" "strings" "gotest.tools/v3/internal/format" "gotest.tools/v3/internal/source" ) type skipT interface { Skip(args ...interface{}) Log(args ...interface{}) } // Result of skip function type Result interface { Skip() bool Message() string } type helperT interface { Helper() } // BoolOrCheckFunc can be a bool, func() bool, or func() Result. Other types will panic type BoolOrCheckFunc interface{} // 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. // The skip message will contain the source code of the expression. // Extra message text can be passed as a format string with args. 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...)) } case func() Result: result := check() if result.Skip() { msg := getFunctionName(check) + ": " + result.Message() t.Skip(format.WithCustomMessage(msg, msgAndArgs...)) } default: panic(fmt.Sprintf("invalid type for condition arg: %T", check)) } } func getFunctionName(function interface{}) string { funcPath := runtime.FuncForPC(reflect.ValueOf(function).Pointer()).Name() return strings.SplitN(path.Base(funcPath), ".", 2)[1] } func ifCondition(t skipT, condition bool, msgAndArgs ...interface{}) { if ht, ok := t.(helperT); ok { ht.Helper() } if !condition { return } const ( stackIndex = 2 argPos = 1 ) source, err := source.FormattedCallExprArg(stackIndex, argPos) if err != nil { t.Log(err.Error()) t.Skip(format.Message(msgAndArgs...)) } t.Skip(format.WithCustomMessage(source, msgAndArgs...)) }