github.com/onsi/gomega@v1.32.0/matchers/panic_matcher.go (about) 1 package matchers 2 3 import ( 4 "fmt" 5 "reflect" 6 7 "github.com/onsi/gomega/format" 8 ) 9 10 type PanicMatcher struct { 11 Expected interface{} 12 object interface{} 13 } 14 15 func (matcher *PanicMatcher) Match(actual interface{}) (success bool, err error) { 16 if actual == nil { 17 return false, fmt.Errorf("PanicMatcher expects a non-nil actual.") 18 } 19 20 actualType := reflect.TypeOf(actual) 21 if actualType.Kind() != reflect.Func { 22 return false, fmt.Errorf("PanicMatcher expects a function. Got:\n%s", format.Object(actual, 1)) 23 } 24 if !(actualType.NumIn() == 0 && actualType.NumOut() == 0) { 25 return false, fmt.Errorf("PanicMatcher expects a function with no arguments and no return value. Got:\n%s", format.Object(actual, 1)) 26 } 27 28 success = false 29 defer func() { 30 if e := recover(); e != nil { 31 matcher.object = e 32 33 if matcher.Expected == nil { 34 success = true 35 return 36 } 37 38 valueMatcher, valueIsMatcher := matcher.Expected.(omegaMatcher) 39 if !valueIsMatcher { 40 valueMatcher = &EqualMatcher{Expected: matcher.Expected} 41 } 42 43 success, err = valueMatcher.Match(e) 44 if err != nil { 45 err = fmt.Errorf("PanicMatcher's value matcher failed with:\n%s%s", format.Indent, err.Error()) 46 } 47 } 48 }() 49 50 reflect.ValueOf(actual).Call([]reflect.Value{}) 51 52 return 53 } 54 55 func (matcher *PanicMatcher) FailureMessage(actual interface{}) (message string) { 56 if matcher.Expected == nil { 57 // We wanted any panic to occur, but none did. 58 return format.Message(actual, "to panic") 59 } 60 61 if matcher.object == nil { 62 // We wanted a panic with a specific value to occur, but none did. 63 switch matcher.Expected.(type) { 64 case omegaMatcher: 65 return format.Message(actual, "to panic with a value matching", matcher.Expected) 66 default: 67 return format.Message(actual, "to panic with", matcher.Expected) 68 } 69 } 70 71 // We got a panic, but the value isn't what we expected. 72 switch matcher.Expected.(type) { 73 case omegaMatcher: 74 return format.Message( 75 actual, 76 fmt.Sprintf( 77 "to panic with a value matching\n%s\nbut panicked with\n%s", 78 format.Object(matcher.Expected, 1), 79 format.Object(matcher.object, 1), 80 ), 81 ) 82 default: 83 return format.Message( 84 actual, 85 fmt.Sprintf( 86 "to panic with\n%s\nbut panicked with\n%s", 87 format.Object(matcher.Expected, 1), 88 format.Object(matcher.object, 1), 89 ), 90 ) 91 } 92 } 93 94 func (matcher *PanicMatcher) NegatedFailureMessage(actual interface{}) (message string) { 95 if matcher.Expected == nil { 96 // We didn't want any panic to occur, but one did. 97 return format.Message(actual, fmt.Sprintf("not to panic, but panicked with\n%s", format.Object(matcher.object, 1))) 98 } 99 100 // We wanted a to ensure a panic with a specific value did not occur, but it did. 101 switch matcher.Expected.(type) { 102 case omegaMatcher: 103 return format.Message( 104 actual, 105 fmt.Sprintf( 106 "not to panic with a value matching\n%s\nbut panicked with\n%s", 107 format.Object(matcher.Expected, 1), 108 format.Object(matcher.object, 1), 109 ), 110 ) 111 default: 112 return format.Message(actual, "not to panic with", matcher.Expected) 113 } 114 }