Skip to content

Commit

Permalink
Not fix a data race
Browse files Browse the repository at this point in the history
  • Loading branch information
brackendawson committed Feb 24, 2024
1 parent e2741fa commit a2de985
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 6 deletions.
15 changes: 9 additions & 6 deletions mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -928,8 +928,11 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
}

for i := 0; i < maxArgCount; i++ {
var actual, expected interface{}
var actualFmt, expectedFmt string
var (
actual, expected interface{}
actualFmt string
expectedFmt func() string
)

if len(objects) <= i {
actual = "(Missing)"
Expand All @@ -941,10 +944,10 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {

if len(args) <= i {
expected = "(Missing)"
expectedFmt = "(Missing)"
expectedFmt = func() string { return "(Missing)" }
} else {
expected = args[i]
expectedFmt = fmt.Sprintf("(%[1]T=%[1]v)", expected)
expectedFmt = func() string { return fmt.Sprintf("(%[1]T=%[1]v)", expected) }
}

if matcher, ok := expected.(argumentMatcher); ok {
Expand Down Expand Up @@ -1005,11 +1008,11 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
default:
if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
// match
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt)
output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt())
} else {
// not match
differences++
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt)
output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt())
}
}
}
Expand Down
95 changes: 95 additions & 0 deletions mock/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package mock
import (
"errors"
"fmt"
"math/rand"
"regexp"
"runtime"
"sync"
Expand Down Expand Up @@ -2146,3 +2147,97 @@ type user interface {
type mockUser struct{ Mock }

func (m *mockUser) Use(c caller) { m.Called(c) }

func TestExpectedArgIsSameStructPointer(t *testing.T) {
type Data struct {
N int
}

// Code under test receives references to instances of d
f := func(s Sender, ds ...*Data) {
for _, d := range ds {
d := d
// starts a new goroutine
go func() {
// makes an unpredictable mutation to it
d.N = rand.Int()
// then uses it in a call to a mock which has d in its
// expectations
s.Send(d)
}()
}
}

ds := []*Data{{}, {}}

m := &mockSender{}
defer m.AssertExpectations(t)

wg := &sync.WaitGroup{}
wg.Add(len(ds))
for _, d := range ds {
d := d
m.On("Send", d).Run(func(args Arguments) {
wg.Done()
}).Return().Once()
}

f(m, ds...)

wg.Wait()
}

func TestExpectedArgIsSameNestedPointers(t *testing.T) {
type Data struct {
N int
}
type Pointers struct {
D *Data
S []int
M map[string]int
}

f := func(s Sender, ps ...Pointers) {
for _, p := range ps {
p := p
go func() {
p.D.N = rand.Int()
p.S[0] = rand.Int()
p.M[""] = rand.Int()
s.Send(p)
}()
}
}

ps := []Pointers{
{D: &Data{}, S: make([]int, 1), M: make(map[string]int)},
}

m := &mockSender{}
defer m.AssertExpectations(t)

wg := &sync.WaitGroup{}
wg.Add(len(ps))
for _, p := range ps {
p := p
m.On("Send", p).Run(func(args Arguments) {
wg.Done()
}).Return().Once()
}

f(m, ps...)

wg.Wait()
}

type Sender interface {
Send(interface{})
}

type mockSender struct {
Mock
}

func (m *mockSender) Send(d interface{}) {
m.Called(d)
}

0 comments on commit a2de985

Please sign in to comment.