...

Source file src/github.com/onsi/gomega/gleak/ignoring_top_function.go

Documentation: github.com/onsi/gomega/gleak

     1  package gleak
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/onsi/gomega/format"
     8  	"github.com/onsi/gomega/types"
     9  )
    10  
    11  // IgnoringTopFunction succeeds if the topmost function in the backtrace of an
    12  // actual goroutine has the specified function name, and optionally the actual
    13  // goroutine has the specified goroutine state.
    14  //
    15  // The expected top function name topfn is either in the form of
    16  // "topfunction-name", "topfunction-name...", or "topfunction-name [state]".
    17  //
    18  // An ellipsis "..." after a topfunction-name matches any goroutine's top
    19  // function name if topfunction-name is a prefix and the goroutine's top
    20  // function name is at least one level deeper. For instance, "foo.bar..."
    21  // matches "foo.bar.baz", but doesn't match "foo.bar".
    22  //
    23  // If the optional expected state is specified, then a goroutine's state needs
    24  // to start with this expected state text. For instance, "foo.bar [running]"
    25  // matches a goroutine where the name of the top function is "foo.bar" and the
    26  // goroutine's state starts with "running".
    27  func IgnoringTopFunction(topfname string) types.GomegaMatcher {
    28  	if brIndex := strings.Index(topfname, "["); brIndex >= 0 {
    29  		expectedState := strings.Trim(topfname[brIndex:], "[]")
    30  		expectedTopFunction := strings.Trim(topfname[:brIndex], " ")
    31  		return &ignoringTopFunctionMatcher{
    32  			expectedTopFunction: expectedTopFunction,
    33  			expectedState:       expectedState,
    34  		}
    35  	}
    36  	if strings.HasSuffix(topfname, "...") {
    37  		expectedTopFunction := topfname[:len(topfname)-3+1] // ...one trailing dot still expected
    38  		return &ignoringTopFunctionMatcher{
    39  			expectedTopFunction: expectedTopFunction,
    40  			matchPrefix:         true,
    41  		}
    42  	}
    43  	return &ignoringTopFunctionMatcher{
    44  		expectedTopFunction: topfname,
    45  	}
    46  }
    47  
    48  type ignoringTopFunctionMatcher struct {
    49  	expectedTopFunction string
    50  	expectedState       string
    51  	matchPrefix         bool
    52  }
    53  
    54  // Match succeeds if an actual goroutine's top function in the backtrace matches
    55  // the specified function name or function name prefix, or name and goroutine
    56  // state.
    57  func (matcher *ignoringTopFunctionMatcher) Match(actual interface{}) (success bool, err error) {
    58  	g, err := G(actual, "IgnoringTopFunction")
    59  	if err != nil {
    60  		return false, err
    61  	}
    62  	if matcher.matchPrefix {
    63  		return strings.HasPrefix(g.TopFunction, matcher.expectedTopFunction), nil
    64  	}
    65  	if g.TopFunction != matcher.expectedTopFunction {
    66  		return false, nil
    67  	}
    68  	if matcher.expectedState == "" {
    69  		return true, nil
    70  	}
    71  	return strings.HasPrefix(g.State, matcher.expectedState), nil
    72  }
    73  
    74  // FailureMessage returns a failure message if the actual goroutine doesn't have
    75  // the specified function name/prefix (and optional state) at the top of the
    76  // backtrace.
    77  func (matcher *ignoringTopFunctionMatcher) FailureMessage(actual interface{}) (message string) {
    78  	return format.Message(actual, matcher.message())
    79  }
    80  
    81  // NegatedFailureMessage returns a failure message if the actual goroutine has
    82  // the specified function name/prefix (and optional state) at the top of the
    83  // backtrace.
    84  func (matcher *ignoringTopFunctionMatcher) NegatedFailureMessage(actual interface{}) (message string) {
    85  	return format.Message(actual, "not "+matcher.message())
    86  }
    87  
    88  func (matcher *ignoringTopFunctionMatcher) message() string {
    89  	if matcher.matchPrefix {
    90  		return fmt.Sprintf("to have the prefix %q for its topmost function", matcher.expectedTopFunction)
    91  	}
    92  	if matcher.expectedState != "" {
    93  		return fmt.Sprintf("to have the topmost function %q and the state %q",
    94  			matcher.expectedTopFunction, matcher.expectedState)
    95  	}
    96  	return fmt.Sprintf("to have the topmost function %q", matcher.expectedTopFunction)
    97  }
    98  

View as plain text