-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix a Core Data concurrency issue when CrashLogging is called from a background thread #20846
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
Changes from all commits
2fb55dd
c5c197c
04a98bc
1103f30
bc1d858
2334cb5
c188980
119b6d1
e4213fd
8ed96b6
7dcfd1a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| import XCTest | ||
| import AutomatticTracks | ||
|
|
||
| @testable import WordPress | ||
|
|
||
| final class WPCrashLoggingDataProviderTests: XCTestCase { | ||
|
|
||
| // MARK: - Testing Log Error | ||
|
|
||
| func testReadingTrackUserInMainThread() throws { | ||
| // Given | ||
| let dataProvider = self.makeCrashLoggingDataProvider() | ||
|
|
||
| // When | ||
| let user = try XCTUnwrap(dataProvider.currentUser) | ||
|
|
||
| // Then | ||
| XCTAssertEqual(user.userID, "\(Constants.defaultAccountID)") | ||
| XCTAssertEqual(user.username, Constants.defaultAccountUsername) | ||
| XCTAssertEqual(user.email, Constants.defaultAccountEmail) | ||
| } | ||
|
|
||
| func testReadingTrackUserInBackgroundThread() async { | ||
| let dataProvider = self.makeCrashLoggingDataProvider() | ||
| await withThrowingTaskGroup(of: Void.self) { group in | ||
| for _ in 1...1000 { | ||
| group.addTask { | ||
| let user = try XCTUnwrap(dataProvider.currentUser) | ||
| XCTAssertEqual(user.userID, "\(Constants.defaultAccountID)") | ||
| XCTAssertEqual(user.username, Constants.defaultAccountUsername) | ||
| XCTAssertEqual(user.email, Constants.defaultAccountEmail) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At first, I wanted to test Accomplishing that would require making changes to
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opened Automattic/Automattic-Tracks-iOS#259 to track this |
||
|
|
||
| // MARK: - Helpers | ||
|
|
||
| private func makeCrashLoggingDataProvider() -> WPCrashLoggingDataProvider { | ||
| let provider = WPCrashLoggingDataProvider(contextManager: makeCoreDataStack()) | ||
| return provider | ||
| } | ||
|
|
||
| private func makeCoreDataStack() -> ContextManager { | ||
| let contextManager = ContextManager.forTesting() | ||
| let account = AccountBuilder(contextManager) | ||
| .with(id: Constants.defaultAccountID) | ||
| .with(email: Constants.defaultAccountEmail) | ||
| .with(username: Constants.defaultAccountUsername) | ||
| .build() | ||
| UserSettings.defaultDotComUUID = account.uuid | ||
| return contextManager | ||
| } | ||
|
|
||
| // MARK: - Constants | ||
|
|
||
| private enum Constants { | ||
| static let defaultAccountID: Int64 = 123 | ||
| static let defaultAccountEmail: String = "foo@automattic.com" | ||
| static let defaultAccountUsername: String = "foobar" | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the rationale for adding 1,000 tasks? Is there something about the amount of tasks that affects the test behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mokagio Running 1000 tasks concurrently in the test is an attempt to reveal potential thread safety issues. The choice of 1000 is arbitrary; it's large enough to stress the API but allows the test to be completed in a reasonable time.