Skip to content

Conversation

@pracucci
Copy link
Collaborator

@pracucci pracucci commented Oct 6, 2021

What this PR does:
Recently we started seeing some compactor unit tests failing because of a race. The race is caused by the mocked Get() function on the bucket.ClientMock. This PR fixes it.

The problem is that testify (the testing lib we're also using for mocking) doesn't allow to specify a dynamic return value (eg. a function that's called each time to get the return value for the mocked function) and so to mock the returned io.ReadCloser we use the following trick:

		// Since we return an ReadCloser and it can be consumed only once,
		// each time the mocked Get() is called we do create a new one, so
		// that getting the same mocked object twice works as expected.
		mockedGet := m.On("Get", mock.Anything, name)
		mockedGet.Run(func(args mock.Arguments) {
			mockedGet.Return(ioutil.NopCloser(bytes.NewReader([]byte(content))), err)
		})

However, there's a race condition that could get mockedGet to return the same reader twice and this cause some unit tests to fail from time to time.

To fix it, I've used a smart solution outlined by @colega (thanks!).

Which issue(s) this PR fixes:
N/A

Checklist

  • Tests updated
  • Documentation added
  • CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX]

Signed-off-by: Marco Pracucci <marco@pracucci.com>
@pracucci pracucci marked this pull request as draft October 6, 2021 12:28
Signed-off-by: Marco Pracucci <marco@pracucci.com>
@pracucci pracucci changed the title Show race in ClientMock.MockGet() Fix race in ClientMock.MockGet() Oct 11, 2021
@pracucci pracucci marked this pull request as ready for review October 11, 2021 14:12
@pracucci pracucci requested a review from pstibrany October 11, 2021 14:12
Copy link
Contributor

@pstibrany pstibrany left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, looks good.

@pracucci pracucci enabled auto-merge (squash) October 11, 2021 14:25
args := m.Called(ctx, name)

// Allow to mock the Get() with a function which is called each time.
if fn, ok := args.Get(0).(func(ctx context.Context, name string) (io.ReadCloser, error)); ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this go after the error check?
And do we still need the case where val is an io.ReadCloser ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this go after the error check?

I don't think so.

And do we still need the case where val is an io.ReadCloser ?

Yes. After this PR there are 2 ways to mock Get(): (1) mock the returned arguments with static values (2) mock the returned arguments with a function which is called each time Get() is called. This PR adds (2), while we should still support (1).

@pracucci pracucci merged commit b5ba459 into main Oct 11, 2021
@pracucci pracucci deleted the fix-race-in-clientmock-get branch October 11, 2021 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants