uber-go / mock

GoMock is a mocking framework for the Go programming language.
Apache License 2.0
1.81k stars 103 forks source link

fix: prevent stringer deadlock #116 #144

Closed nbgraham closed 4 months ago

nbgraham commented 5 months ago

Fixes #116

Problem

If your mock an interface that matches the fmt.Stringer interface:

type Stringer interface {
  String() string
}

Then your unit tests can deadlock if you provide that mock as an expected argument to a call that is not matched (i.e. fails the test).

Because, when printing the error message for the call that was not matched, it calls String() on all arguments that support it, including the mock.

But each call to a mock is protected with a mutex, and the previous call (that was not matched) has not yet exited.

Solution

The solution has two parts

  1. During mock code generation (an existing part of this library) add a unique method on mocks (ISGOMOCK)
  2. During test execution, whenever we are stringifying something that might be a mock, check if it is a mock (ISGOMOCK) that implements the String() method. If it is, just use the type name as the string value, instead of calling String() (which would cause the deadlock).
CLAassistant commented 5 months ago

CLA assistant check
All committers have signed the CLA.

JacobOaks commented 4 months ago

Hey @nbgraham thanks for looking into this and providing the fix! This looks good to me.