Repository navigation
test: [SDK-5733] fix flaky IAM, user switch, and FileLogStore unit tests - #1805
Conversation
- EarlyTriggerTrackingTests: pause IAM display so a prior test's queued web view build cannot stall main-queue observer callbacks. - SwitchUserIntegrationTests: pause the operation repo while queuing updates instead of relying on a 300ms poll to batch them. - FileLogStore suites: absorb the process's one-off cold start in a class-level warm-up so per-test 5s waits stay meaningful. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nan-li
left a comment
There was a problem hiding this comment.
approving since as test only and it is an improvement
One non-blocking note on the SwitchUser test. The pause is not exclusive:
OSUserExecutor.swift:538setsoperationRepo.paused = falseon every successful Create User, and login(A) produces one about 100ms after the call once the 409 turns into a create. If the test thread is still queuing past that point, a 100ms poll can land betweenaddTagandsetLanguageand split the request. The window is much smaller than before and the two sibling tests share it, so this is fine to land as is. If the test flakes again, that unpause is the first place to look.
abdulraqeeb33
left a comment
There was a problem hiding this comment.
The pause still sets isTriggerChanged before display is skipped, and the user-switch test now matches the sibling pause-and-flush. Two nits, neither blocks.
abdulraqeeb33
left a comment
There was a problem hiding this comment.
Approving. The two nits on the earlier comment are non-blocking.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@nan-li thanks, confirmed |
…rificationTests The login helper returned once the client looked idle, but the fetch the new subscription id starts can reach the client after that. A test that then invalidated the token could see that late fetch signed with the old token. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A late Fetch User from an earlier test can reach the shared mock client first, so executedRequests.first is not always the custom events request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Description
One Line Summary
Fix five flaky iOS unit tests that failed on CI across unrelated branches.
Details
Motivation
These tests failed intermittently on CI and blocked unrelated PRs (e.g. #1803):
EarlyTriggerTrackingTests: a message displayed at the end of one test built its web view on the main queue during the next test. On a cold CI simulator that held the main thread for seconds, so the next test's observer callbacks (delivered viadispatch_asyncto main) missed the 5s wait and the IAM fetch never ran. Confirmed from the CI xcresult logs.SwitchUserIntegrationTests.testAnonUser_thenIdentifyUserWithConflict_thenLogin_...: relied on a 300ms poll interval to batch each user's tag and language into one request. A poll landing betweenaddTagandsetLanguagesplit them and failed the single-request assertion.FileLogStoreRecordDatingTests: the first file-store calls in the test process stalled for about 37s on CI, so whichever tests ran first hit their 5s waits. Confirmed from the CI xcresult; the exact cold-start source (likely first Kotlin runtime use) is not pinned down.IamFetchIdentityVerificationTests.testAFetchIsHeldRatherThanSentUnsignedWhenTheUserHasNoToken: theloginhelper returned once the mock client looked idle, but the IAM fetch the new subscription id starts can reach the client after that. The test then invalidatedtoken-a, and the late fetch landed signed withtoken-ainstead of the expectedtoken-b. Seen on this PR's first CI run.CustomEventsIntegrationTests.testTrackEvent_withArrayProperties_sendsCorrectly: readexecutedRequests.firstas the custom events request, but a late Fetch User from an earlier test reached the shared mock client first. Seen on this PR's second CI run.Scope
Test-only changes:
EarlyTriggerTrackingTests: pause in-app messaging in these tests via astartPausedController()helper. TheisTriggerChangedflags are set before the pause check, so what the tests check is unchanged. Force unwraps replaced withXCTUnwrapso a failure doesn't crash and restart the whole suite.SwitchUserIntegrationTests: start, wait for the anonymous user to be created, pause the operation repo while queuing updates, then unpause and flush. This matches the sibling tests and drops the 300ms interval that leaked into later tests.IamFetchIdentityVerificationTests:loginalso waits for the fetch it triggers to be answered or held.MockOneSignalClient.firstExecutedRequest(ofType:)picks the request by type instead of position (7 call sites).FileLogStoreTestCase: class-level warm-up (up to 120s) absorbs the one-off cold start so per-test 5s timeouts stay meaningful. If the warm-up times out, each test fails in setup with a clear error.Not included:
UserJwtLifecycleTestsflakes. Every failing run predates #1794 (123cbea13), which already fixed that race, and there have been no failures since.Testing
Unit testing
On a temporary iOS 26.5 simulator, the same runtime CI uses:
-test-iterations3 to 10).UnitTestApp_TestPlan_Reducedpassed (664 tests).Because these flakes only show up under CI load, passing locally doesn't prove they're gone.
Manual testing
Not applicable; test-only change.
Affected code checklist
Checklist
Overview
Testing
Final pass
🤖 Generated with Claude Code