...

Source file src/gotest.tools/v3/skip/skip.go

Documentation: gotest.tools/v3/skip

     1  /*
     2  Package skip provides functions for skipping a test and printing the source code
     3  of the condition used to skip the test.
     4  */
     5  package skip // import "gotest.tools/v3/skip"
     6  
     7  import (
     8  	"fmt"
     9  	"path"
    10  	"reflect"
    11  	"runtime"
    12  	"strings"
    13  
    14  	"gotest.tools/v3/internal/format"
    15  	"gotest.tools/v3/internal/source"
    16  )
    17  
    18  type skipT interface {
    19  	Skip(args ...interface{})
    20  	Log(args ...interface{})
    21  }
    22  
    23  // Result of skip function
    24  type Result interface {
    25  	Skip() bool
    26  	Message() string
    27  }
    28  
    29  type helperT interface {
    30  	Helper()
    31  }
    32  
    33  // BoolOrCheckFunc can be a bool, func() bool, or func() Result. Other types will panic
    34  type BoolOrCheckFunc interface{}
    35  
    36  // If the condition expression evaluates to true, skip the test.
    37  //
    38  // The condition argument may be one of three types: bool, func() bool, or
    39  // func() SkipResult.
    40  // When called with a bool, the test will be skip if the condition evaluates to true.
    41  // When called with a func() bool, the test will be skip if the function returns true.
    42  // When called with a func() Result, the test will be skip if the Skip method
    43  // of the result returns true.
    44  // The skip message will contain the source code of the expression.
    45  // Extra message text can be passed as a format string with args.
    46  func If(t skipT, condition BoolOrCheckFunc, msgAndArgs ...interface{}) {
    47  	if ht, ok := t.(helperT); ok {
    48  		ht.Helper()
    49  	}
    50  	switch check := condition.(type) {
    51  	case bool:
    52  		ifCondition(t, check, msgAndArgs...)
    53  	case func() bool:
    54  		if check() {
    55  			t.Skip(format.WithCustomMessage(getFunctionName(check), msgAndArgs...))
    56  		}
    57  	case func() Result:
    58  		result := check()
    59  		if result.Skip() {
    60  			msg := getFunctionName(check) + ": " + result.Message()
    61  			t.Skip(format.WithCustomMessage(msg, msgAndArgs...))
    62  		}
    63  	default:
    64  		panic(fmt.Sprintf("invalid type for condition arg: %T", check))
    65  	}
    66  }
    67  
    68  func getFunctionName(function interface{}) string {
    69  	funcPath := runtime.FuncForPC(reflect.ValueOf(function).Pointer()).Name()
    70  	return strings.SplitN(path.Base(funcPath), ".", 2)[1]
    71  }
    72  
    73  func ifCondition(t skipT, condition bool, msgAndArgs ...interface{}) {
    74  	if ht, ok := t.(helperT); ok {
    75  		ht.Helper()
    76  	}
    77  	if !condition {
    78  		return
    79  	}
    80  	const (
    81  		stackIndex = 2
    82  		argPos     = 1
    83  	)
    84  	source, err := source.FormattedCallExprArg(stackIndex, argPos)
    85  	if err != nil {
    86  		t.Log(err.Error())
    87  		t.Skip(format.Message(msgAndArgs...))
    88  	}
    89  	t.Skip(format.WithCustomMessage(source, msgAndArgs...))
    90  }
    91  

View as plain text