Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mock: Diff is prone to data races #1597

Open
petergardfjall opened this issue May 14, 2024 · 0 comments
Open

mock: Diff is prone to data races #1597

petergardfjall opened this issue May 14, 2024 · 0 comments
Labels

Comments

@petergardfjall
Copy link

petergardfjall commented May 14, 2024

Description

Testify mocks are currently prone to data races when supplied a pointer argument (that may be concurrently updated elsewhere).

In several instances of our code, we have started seeing data races when running go test -race that originate from testify code. More specifically these data races occur whenever a mock pointer argument is concurrently modified. The reason being that Arguments.Diff uses the %v format specifier to get a presentable string for the argument. This also traverses the pointed-to data structure, which would lead to the data race.

We did not see these issues earlier, but they started appearing lately after we upgraded to go 1.22. Not sure if that is a coincidence, but maybe performance improved in such a way that these data races suddenly started surfacing.

We need to test our code for race conditions with go test -race, and we cannot have testify be the offender of data races.

A PR to resolve the issue is suggested in #1598.
(It should be noted that it is heavily inspired by #1229, but since that PR hasn't seen any updates in over a year I decided to start fresh).

Step To Reproduce

See test case in suggested fix PR: #1598

Expected behavior

The unit test in #1598 passes when running with go test -race.

Actual behavior

The unit test fails with a data race:

$ go test -race ./...
ok  	github.com/stretchr/testify	(cached)
ok  	github.com/stretchr/testify/assert	(cached)
ok  	github.com/stretchr/testify/assert/internal/unsafetests	(cached)
?   	github.com/stretchr/testify/http	[no test files]
==================
WARNING: DATA RACE
Write at 0x00c000591f30 by goroutine 127:
  github.com/stretchr/testify/mock.Test_CallMockWithConcurrentlyModifiedPointerArg.func1()
      /home/peterg/dev/git/testify/mock/mock_test.go:1938 +0x84

Previous read at 0x00c000591f30 by goroutine 126:
  reflect.typedmemmove()
      /opt/go/src/runtime/mbarrier.go:203 +0x0
  reflect.packEface()
      /opt/go/src/reflect/value.go:135 +0xc5
  reflect.valueInterface()
      /opt/go/src/reflect/value.go:1526 +0x179
  reflect.Value.Interface()
      /opt/go/src/reflect/value.go:1496 +0xb4
  fmt.(*pp).printValue()
      /opt/go/src/fmt/print.go:769 +0xc5
  fmt.(*pp).printValue()
      /opt/go/src/fmt/print.go:921 +0x132a
  fmt.(*pp).printArg()
      /opt/go/src/fmt/print.go:759 +0xb84
  fmt.(*pp).doPrintf()
      /opt/go/src/fmt/print.go:1174 +0x10ce
  fmt.Sprintf()
      /opt/go/src/fmt/print.go:239 +0x5c
  github.com/stretchr/testify/mock.Arguments.Diff()
      /home/peterg/dev/git/testify/mock/mock.go:950 +0x1b2
  github.com/stretchr/testify/mock.(*Mock).findExpectedCall()
      /home/peterg/dev/git/testify/mock/mock.go:368 +0x147
  github.com/stretchr/testify/mock.(*Mock).MethodCalled()
      /home/peterg/dev/git/testify/mock/mock.go:476 +0xac
  github.com/stretchr/testify/mock.(*Mock).Called()
      /home/peterg/dev/git/testify/mock/mock.go:466 +0x195
  github.com/stretchr/testify/mock.(*pointerArgMock).Question()
      /home/peterg/dev/git/testify/mock/mock_test.go:1919 +0x8c
  github.com/stretchr/testify/mock.Test_CallMockWithConcurrentlyModifiedPointerArg()
      /home/peterg/dev/git/testify/mock/mock_test.go:1943 +0x28b
  testing.tRunner()
      /opt/go/src/testing/testing.go:1689 +0x21e
  testing.(*T).Run.gowrap1()
      /opt/go/src/testing/testing.go:1742 +0x44

Goroutine 127 (running) created at:
  github.com/stretchr/testify/mock.Test_CallMockWithConcurrentlyModifiedPointerArg()
      /home/peterg/dev/git/testify/mock/mock_test.go:1936 +0x27c
  testing.tRunner()
      /opt/go/src/testing/testing.go:1689 +0x21e
  testing.(*T).Run.gowrap1()
      /opt/go/src/testing/testing.go:1742 +0x44

Goroutine 126 (running) created at:
  testing.(*T).Run()
      /opt/go/src/testing/testing.go:1742 +0x825
  testing.runTests.func1()
      /opt/go/src/testing/testing.go:2161 +0x85
  testing.tRunner()
      /opt/go/src/testing/testing.go:1689 +0x21e
  testing.runTests()
      /opt/go/src/testing/testing.go:2159 +0x8be
  testing.(*M).Run()
      /opt/go/src/testing/testing.go:2027 +0xf17
  main.main()
      _testmain.go:267 +0x2bd
==================
--- FAIL: Test_CallMockWithConcurrentlyModifiedPointerArg (0.00s)
    testing.go:1398: race detected during execution of test
FAIL
FAIL	github.com/stretchr/testify/mock	0.053s
ok  	github.com/stretchr/testify/require	(cached)
ok  	github.com/stretchr/testify/suite	(cached)
FAIL
@dolmen dolmen changed the title Mock code is prone to data races mock: Diff is prone to data races May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant