Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Mechanism of operation aborting valid codepath #158

Closed
@ghost

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions