{"action":"created","issue":{"url":"https://api.github.com/repos/stretchr/testify/issues/423","repository_url":"https://api.github.com/repos/stretchr/testify","labels_url":"https://api.github.com/repos/stretchr/testify/issues/423/labels{/name}","comments_url":"https://api.github.com/repos/stretchr/testify/issues/423/comments","events_url":"https://api.github.com/repos/stretchr/testify/issues/423/events","html_url":"https://github.com/stretchr/testify/issues/423","id":219453077,"node_id":"MDU6SXNzdWUyMTk0NTMwNzc=","number":423,"title":"Using mock struct as arg to mocked method causes data race","user":{"login":"lance-burton","id":1485923,"node_id":"MDQ6VXNlcjE0ODU5MjM=","avatar_url":"https://avatars1.githubusercontent.com/u/1485923?v=4","gravatar_id":"","url":"https://api.github.com/users/lance-burton","html_url":"https://github.com/lance-burton","followers_url":"https://api.github.com/users/lance-burton/followers","following_url":"https://api.github.com/users/lance-burton/following{/other_user}","gists_url":"https://api.github.com/users/lance-burton/gists{/gist_id}","starred_url":"https://api.github.com/users/lance-burton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lance-burton/subscriptions","organizations_url":"https://api.github.com/users/lance-burton/orgs","repos_url":"https://api.github.com/users/lance-burton/repos","events_url":"https://api.github.com/users/lance-burton/events{/privacy}","received_events_url":"https://api.github.com/users/lance-burton/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2017-04-05T03:04:24Z","updated_at":"2019-05-13T23:24:30Z","closed_at":null,"author_association":"NONE","body":"If a mock struct with a method is passed as an argument to a method on another mock struct, and both methods are invoked simultaneously in separate goroutines, a data race occurs. In one goroutine, the first mock instance is written to update call counts or the list of calls on its method, while in another goroutine the second mock instance is logging its arguments, which includes a walk of all the data on the first instance.\r\n\r\nFor example, test the following files with `go test -race`:\r\n\r\nmain.go\r\n```\r\npackage main\r\n\r\nimport \"sync\"\r\n\r\ntype IInterface1 interface {\r\n\tSomeFunc1() error\r\n}\r\n\r\ntype IInterface2 interface {\r\n\tSomeFunc2(IInterface1) error\r\n}\r\n\r\ntype Implementation1 struct {\r\n}\r\n\r\nfunc (i Implementation1) SomeFunc1() error {\r\n\treturn nil\r\n}\r\n\r\ntype Implementation2 struct {\r\n}\r\n\r\nfunc (i Implementation2) SomeFunc2(i1 IInterface1) error {\r\n\treturn nil\r\n}\r\n\r\nfunc DoSomeStuff(i1 IInterface1, i2 IInterface2) error {\r\n\tvar wg sync.WaitGroup\r\n\twg.Add(1)\r\n\tgo func() {\r\n\t\tfor j := 0; j < 10000; j++ {\r\n\t\t\ti2.SomeFunc2(i1)\r\n\t\t}\r\n\t\twg.Done()\r\n\t}()\r\n\tfor i := 0; i < 10000; i++ {\r\n\t\ti1.SomeFunc1()\r\n\t}\r\n\twg.Wait()\r\n\treturn nil\r\n}\r\n\r\nfunc main() {\r\n\tvar i1 Implementation1\r\n\tvar i2 Implementation2\r\n\t_ = DoSomeStuff(i1, i2)\r\n}\r\n```\r\n\r\nmain_test.go\r\n```\r\npackage main\r\n\r\nimport (\r\n\t\"testing\"\r\n\r\n\t\"github.com/stretchr/testify/mock\"\r\n\t\"github.com/stretchr/testify/suite\"\r\n)\r\n\r\ntype (\r\n\tMockBugTestSuite struct {\r\n\t\tsuite.Suite\r\n\t}\r\n)\r\n\r\ntype IInterface1Mock struct {\r\n\tmock.Mock\r\n}\r\n\r\nfunc (_m IInterface1Mock) SomeFunc1() error {\r\n\tret := _m.Called()\r\n\r\n\tvar r0 error\r\n\tif rf, ok := ret.Get(0).(func() error); ok {\r\n\t\tr0 = rf()\r\n\t} else {\r\n\t\tr0 = ret.Error(0)\r\n\t}\r\n\r\n\treturn r0\r\n}\r\n\r\ntype IInterface2Mock struct {\r\n\tmock.Mock\r\n}\r\n\r\nfunc (_m IInterface2Mock) SomeFunc2(i1 IInterface1) error {\r\n\tret := _m.Called(i1)\r\n\r\n\tvar r0 error\r\n\tif rf, ok := ret.Get(0).(func(IInterface1) error); ok {\r\n\t\tr0 = rf(i1)\r\n\t} else {\r\n\t\tr0 = ret.Error(0)\r\n\t}\r\n\r\n\treturn r0\r\n}\r\n\r\nfunc (s *MockBugTestSuite) TestDoSomeStuff() {\r\n\tvar i1 IInterface1Mock\r\n\tvar i2 IInterface2Mock\r\n\r\n\ti1.On(\"SomeFunc1\").Return(nil)\r\n\ti2.On(\"SomeFunc2\", mock.Anything).Return(nil)\r\n\terr := DoSomeStuff(i1, i2)\r\n\ts.Nil(err)\r\n}\r\n\r\nfunc TestPermTestSuite(t *testing.T) {\r\n\tsuite.Run(t, new(MockBugTestSuite))\r\n}\r\n```\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/stretchr/testify/issues/comments/492021894","html_url":"https://github.com/stretchr/testify/issues/423#issuecomment-492021894","issue_url":"https://api.github.com/repos/stretchr/testify/issues/423","id":492021894,"node_id":"MDEyOklzc3VlQ29tbWVudDQ5MjAyMTg5NA==","user":{"login":"georgelesica-wf","id":7902990,"node_id":"MDQ6VXNlcjc5MDI5OTA=","avatar_url":"https://avatars0.githubusercontent.com/u/7902990?v=4","gravatar_id":"","url":"https://api.github.com/users/georgelesica-wf","html_url":"https://github.com/georgelesica-wf","followers_url":"https://api.github.com/users/georgelesica-wf/followers","following_url":"https://api.github.com/users/georgelesica-wf/following{/other_user}","gists_url":"https://api.github.com/users/georgelesica-wf/gists{/gist_id}","starred_url":"https://api.github.com/users/georgelesica-wf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/georgelesica-wf/subscriptions","organizations_url":"https://api.github.com/users/georgelesica-wf/orgs","repos_url":"https://api.github.com/users/georgelesica-wf/repos","events_url":"https://api.github.com/users/georgelesica-wf/events{/privacy}","received_events_url":"https://api.github.com/users/georgelesica-wf/received_events","type":"User","site_admin":false},"created_at":"2019-05-13T23:24:30Z","updated_at":"2019-05-13T23:24:30Z","author_association":"COLLABORATOR","body":"Sure, I'll take a look this evening or tomorrow morning.\n\nOn Mon, May 13, 2019, 16:53 Kshitij Gupta <notifications@github.com> wrote:\n\n> @georgelesica-wf <https://github.com/georgelesica-wf>\n> Can you please check this out?\n> This issue and corresponding PR seem to have a consistent repro and fix.\n> The consistent repro is very similar to what I'm stumbling in my codebase\n> (nested mocks across go routines)\n>\n> Note: This repro doesn't seem to be fixed with the patch proposed in:\n> 365386c\n> <https://github.com/stretchr/testify/commit/365386cb02c44b632277e859d737c3456b1630a2>\n>\n> —\n> You are receiving this because you were mentioned.\n> Reply to this email directly, view it on GitHub\n> <https://github.com/stretchr/testify/issues/423?email_source=notifications&email_token=AB4JODSVFXAXD2JB3PLCOH3PVHWPVA5CNFSM4DGOYROKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVJY7AQ#issuecomment-492015490>,\n> or mute the thread\n> <https://github.com/notifications/unsubscribe-auth/AB4JODRJAMHGMTSWNIGABFTPVHWPVANCNFSM4DGOYROA>\n> .\n>\n"}}
{"actor":{"display_login":"georgelesica-wf"}}