Make expectation recording thread-safe.#521
Open
fumoboy007 wants to merge 1 commit intoerikdoe:masterfrom
Open
Make expectation recording thread-safe.#521fumoboy007 wants to merge 1 commit intoerikdoe:masterfrom
fumoboy007 wants to merge 1 commit intoerikdoe:masterfrom
Conversation
To handle a mocked invocation, we do the following: 1. Get the first stub that matches the invocation. 2. If the stub is an expectation, remove the stub from the arrays of stubs and expectations. 3. Pass the invocation to the stub. The first two steps are currently not atomic, so there is a race condition. For example: 1. Add expectation 1 for method A. 2. Add expectation 2 for same method A. 3. [Thread 1] Call method A. 4. [Thread 2] Call method A. 5. [Thread 1] Get expectation 1 since it matches the invocation. 6. [Thread 2] Get expectation 1 since it matches the invocation. 7. [Thread 1] Remove expectation 1 from the arrays. 8. [Thread 2] Remove expectation 1 from the arrays. In the above example, the invocations of the same method in Thread 1 and Thread 2 both match expectation 1; expectation 2 does not get matched. The solution is to make the matching and the removal atomic. We can do so by wrapping the relevant code in `@synchronized(stubs)`. (Even though `stubForInvocation:` also performs `@synchronized(stubs)`, we can feel free to do the same in the caller without fear of deadlocks since `@synchronized` uses a recursive lock.) Added a new unit test that was failing before the fix and is now passing after the fix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
To handle a mocked invocation, we do the following:
The first two steps are currently not atomic, so there is a race condition. For example:
In the above example, the invocations of the same method in Thread 1 and Thread 2 both match expectation 1; expectation 2 does not get matched.
The solution is to make the matching and the removal atomic. We can do so by wrapping the relevant code in
@synchronized(stubs). (Even thoughstubForInvocation:also performs@synchronized(stubs), we can feel free to do the same in the caller without fear of deadlocks since@synchronizeduses a recursive lock.)Added a new unit test that was failing before the fix and is now passing after the fix.