Mechanism of operation aborting valid codepath #158

Description
gomock is jumping out of a normal code execution, causing code that would normally be executed a normal program to be bypassed. This means any clean-up after a failed mock call will have unexpected consequences such as:
- Files not being flushed or closed
- Signals not being sent over channels
- Mutexes being left in incorrect states
The last point is used as an example below. The code being tested is a series of functions that use a global mutex for synchronization.
Code to be tested:
package test
import "sync"
import "io"
var m sync.Mutex
func init() {
m = sync.Mutex{}
}
func f(a io.Writer) {
m.Lock()
a.Write([]byte{})
m.Unlock()
}
func g(a io.Writer) {
m.Lock()
a.Write([]byte{})
m.Unlock()
}
Test code
package test
import (
"testing"
"github.com/golang/mock/gomock"
)
func TestF(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mw := NewMockWriter(ctrl)
mw.EXPECT().Write([]byte{'a'})
f(mw)
}
func TestG(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mw := NewMockWriter(ctrl)
mw.EXPECT().Write([]byte{'b'})
g(mw)
}
Command to generate mock:
mockgen -package test io Writer
Output
➜ test go test .
--- FAIL: TestF (0.00s)
controller.go:150: Unexpected call to *test.MockWriter.Write([[]]) at /home/ser/workspace/src/test/test_mock.go:32 because:
Expected call at /home/ser/workspace/src/test/test_mock.go:39 doesn't match the argument at index 0.
Got: []
Want: is equal to [97]
asm_amd64.s:573: missing call(s) to *test.MockWriter.Write(is equal to [97]) /home/ser/workspace/src/test/test_mock.go:39
asm_amd64.s:573: aborting test due to missing call(s)
fatal error: all goroutines are asleep - deadlock!
(stack trace)
Expected behavior
The mutex would in practice only be left in a locked state if the mocked functions panic'd, which is not the behavior being tested. This results in incorrect execution of the tests, including in some cases tests hanging, tests being skipped, and an inability to properly execute tests.
If this is known behavior, and gomock is incompatible with some packages or requires special handling when using those functions, it'd be great to have this documented. E.g., a blurb saying that gomock uses panic
to manage code flow would help people understand what can and can't be tested using gomock.