Mock can be deadlocked by a panic (#1157)

If an argumentMatcher function panics and AssertExpectations is deferred then the test would deadlock.
This commit is contained in:
Bracken 2022-06-23 10:42:21 +01:00 committed by GitHub
parent 1b73601ae8
commit c206b2e823
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 1 deletions

View File

@ -858,7 +858,16 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
}
if matcher, ok := expected.(argumentMatcher); ok {
if matcher.Matches(actual) {
var matches bool
func() {
defer func() {
if r := recover(); r != nil {
actualFmt = fmt.Sprintf("panic in argument matcher: %v", r)
}
}()
matches = matcher.Matches(actual)
}()
if matches {
output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher)
} else {
differences++

View File

@ -233,6 +233,32 @@ func Test_Mock_On_WithIntArgMatcher(t *testing.T) {
})
}
func Test_Mock_On_WithArgMatcherThatPanics(t *testing.T) {
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod2", MatchedBy(func(_ interface{}) bool {
panic("try to lock mockedService")
})).Return()
defer func() {
assertedExpectations := make(chan struct{})
go func() {
tt := new(testing.T)
mockedService.AssertExpectations(tt)
close(assertedExpectations)
}()
select {
case <-assertedExpectations:
case <-time.After(time.Second):
t.Fatal("AssertExpectations() deadlocked, did the panic leave mockedService locked?")
}
}()
assert.Panics(t, func() {
mockedService.TheExampleMethod2(false)
})
}
func TestMock_WithTest(t *testing.T) {
var (
mockedService TestExampleImplementation