Repository navigation
Stop the chosen Ethereum node test timing out after a fresh build - #1328
Open
takemiyamakoto wants to merge 1 commit into
Open
takemiyamakoto wants to merge 1 commit into
takemiyamakoto wants to merge 1 commit into
Conversation
testChosenEthereumNodeTakesEffectInSessionAndAutomaticSelectionResumesOnTheNodeMovedTo failed the Core Data release gate in runs that started right after a fresh build (10.9 s and 11.1 s against its 10 s waits) and passed on reruns from the same build. The registry was never slow: with timing probes it applied the chosen-node update 0.5 ms after the test sent it. The time went into one RunLoop.run(until: +10 ms) call in waitForValue, which took 5.5 s after a cold build and 0.07 s on a rerun. In that run-loop turn XCTest recorded the Thread Performance Checker's report from waitUntilObserverAttached (the test thread blocked on the provider's utility-QoS queue) and symbolicated it in process, building symbol data from the fresh binaries' debug maps. The deadline passed inside that turn, and the loop failed without looking at the state again. - waitForValue reads the state before it checks the deadline, so a run-loop turn that outlasts the budget cannot fail a wait the registry met meanwhile. - The test observable's attach wait polls on the run loop instead of blocking on the provider's queue, so it no longer raises the report. Test-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
ChainRegistryTests/testChosenEthereumNodeTakesEffectInSessionAndAutomaticSelectionResumesOnTheNodeMovedTofailed the Core Data release gate (scripts/ci/run-coredata-release-gate.sh, Release -O) in runs that started right after a fresh build. It took 10.9 s and 11.1 s against its 10 s waits, and 8.07 s once on the 4.2.2 line. On reruns from the same build it took 0.04–1.1 s.The registry was never the slow part, and this PR changes only the test file.
What was slow
With temporary timing probes (not in this PR), on a fresh
simctl created iPhone 17 / iOS 27.0 simulator, building with the gate's settings and runningChainRegistryTestsright after a cold build:URLSessionand provider.RunLoop.current.run(until: +10 ms)call inwaitForValuetook 5.497 s. On a rerun from the same build, that turn took 0.072 s.-[XCTestCase recordIssue:]→XCTInProcessSymbolicationService→ CoreSymbolication building symbol data from the fresh binaries' debug maps (extract_debug_map_data_from_header: 482 samples). The rerun spent 12 samples there.The issue XCTest was recording is the Thread Performance Checker's priority-inversion report from line 1035,
waitUntilObserverAttached(). There the test thread blocks on anNSConditionthat theStreamableProvidersignals from its utility-QoS queue. Every gate log has that warning. XCTest records it from the main run loop, so the symbolication lands in the test's next wait. The deadline then passes inside a single run-loop turn, andwaitForValuefailed without looking at the state again.A controlled check on the same probe build confirms this failure mode. An 11 s main-thread stall, queued right after the update was sent, makes master's
waitForValuetime out (11.63 s, one poll), although the registry applied the change 0.6 ms after the send. With this PR's helper the wait passes.Change (test-only,
ChainRegistryTests.swift)waitForValuereads the state before it checks the deadline, so a run-loop turn that outlasts the budget cannot fail a wait the registry met meanwhile. The budget is unchanged: a condition still unmet at the deadline fails as before.ChainRegistryTestObservable.waitUntilObserverAttached()polls on the run loop instead of blocking on the provider's queue (NSCondition→NSLock), so it no longer raises the checker's report.Validation (local; this project has no CI gate)
Three Core Data gate runs, each right after a full fresh build (DerivedData removed first; 3,206 compiles), on a fresh iPhone 17 / iOS 27.0 simulator, at local validation commit
7b3b9b175. That commit is #1327's head2668d3624plus this commit, tree56f4998b. Master's own gate cannot pass yet; see Merge order.With this change, the gate's only runtime warning comes from #1327's
waitUntilBlocked(). The first-issue symbolication therefore lands intestSocketStateChangeDuringChainUpdateReadsTheListOnlyAfterTheUpdate's nextwaitForCondition, as one long run-loop turn. In run 2 that turn took about 17 s against a 10 s budget. Master'swaitForValuewould have failed the test there; this PR's passed it.PR head on master (
87cd4d75b, treea95e576f): the gate's xcodebuild ran 478 tests, 478 passed, 0 failed, 0 skipped, with no runtime warnings. The gate then failed only master's existing inventory check ("expected exactly 424 tests, found 478"), which fails on master without this change too.Evidence, scripts, probe diffs, thread samples and logs are in the local report
build/reports/ios-ethereum-node-test-20261113/(Xcode 27.2 27B52).Merge order
git merge-treeshows this commit applies cleanly to master, to Stop the chain registry crashing the app on opening (4.2.2 fix for master) #1327's head2668d3624, to Consolidate every open iOS PR: 4.2.1 (2026.11.11), redesign and brand, config, subscription and test fixes #1326's head2cd1011a4and tohotfix/4.2.0-polkaswap-usability, in any order.Follow-up after #1327
#1327 adds
BlockingConnectionFactory.waitUntilBlocked(), which blocks on aDispatchSemaphoresignalled from the registry's write. It raises the same checker report, so after #1327 the first-issue symbolication lands intestSocketStateChangeDuringChainUpdateReadsTheListOnlyAfterTheUpdate, where this PR'swaitForValueabsorbs it. Making that helper poll too would leaveChainRegistryTestswith no runtime warnings at all. That change belongs on #1327's code, so it is not in this PR.🤖 Generated with Claude Code