Repository navigation
fix: restore a green test suite and fix the bugs it exposed - #9
Merged
Merged
Conversation
Library fixes: - UIGraphicsBeginImageContextWithOptions throws NSInternalInconsistencyException for a zero width/height since iOS 17. Guard every call site whose size can be zero (UIImage color/rounded/rotated/orientationFixed/resize, UIView and UIScrollView snapshots, UITabBar) and return the existing failure value. - Date.dateFormatter hands out one shared main-thread instance, but iso8601String/re(iso8601String:) changed its locale/timeZone permanently. Reset locale/timeZone/calendar (all null_resettable) before returning it. - String.re.date/dateTime formatters were initialized from that same shared instance, so their dateFormat was overwritten by other callers. Give them their own en_US_POSIX formatters, as recommended for fixed-format parsing. - AES with an empty iv passed the empty Data's non-nil stack baseAddress to CCCrypt, which read 16 garbage bytes as the IV, so results were nondeterministic. Pass nil so an all-zero IV is used, and fix the docs that claimed ECB. Test fixes: - Pin the test action language/region to en/US in the shared schemes, pass en_US explicitly where APIs accept a locale, and skip the remaining locale-dependent tests when run elsewhere. - Use URLs that are invalid on both the pre- and post-iOS 17 URL parsers. - Stop asserting exact JPEG/PNG bytes, which change with ImageIO metadata. - Fix test bugs: attributes(at: 0) on an empty string, pushing the same view controller twice, a data race on a concurrent queue, a 0.1s debounce window. - Host UIRefreshControl tests in a window, which beginRefreshing now requires. - Compare wrapToContent against a measured height instead of TextKit 2's estimated contentSize. - Add known-answer AES vectors for the empty-iv path. Co-authored-by: Cursor <cursoragent@cursor.com>
- project.pbxproj: Xcode re-sorted the UserDefaults build file and file reference entries; no entries were added or removed. - watchOS_Example scheme: Xcode dropped the BlueprintName attribute from the runnable's BuildableReference. Co-authored-by: Cursor <cursoragent@cursor.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
The unit test suite had drifted to 24 failing tests (38 assertions) on recent Xcode/iOS. Most failures were OS behavior changes or brittle tests, but four of them pointed at real library bugs, one of which crashes apps on iOS 17+. This PR fixes those bugs and makes the suite green and stable: 768 tests, 0 failures, over repeated full runs.
Library fixes
1. Crash: zero-size graphics contexts (iOS 17+)
Since iOS 17,
UIGraphicsBeginImageContextWithOptionsraisesNSInternalInconsistencyExceptionwhen width or height is 0 (older systems returned an empty context). Snapshotting a view before layout, or processing an empty image, crashed the app.Every call site whose size can be zero now guards first and returns its existing failure value (
nilfor optionals, the original image orUIImage()otherwise):UIImage:re(color:size:),withRoundedCorners, bothrotated,orientationFixed,resize(toHeight:),resize(toWidth:)UIView.snapshotImage,UIView.snapshot(afterScreenUpdates:),UIScrollView.snapshotUITabBar(selection indicator and item images; the tab bar's frame is zero before layout)2. Shared
DateFormatterstate leaked between callsOn the main thread
Date.dateFormatterreturns one shared instance, butiso8601Stringandre(iso8601String:)set itslocale/timeZoneand never restored them. Every latertimeString,dateString,dayName, etc. useden_US_POSIXplus a fixed time zone. The getter now resetslocale,timeZoneandcalendar(allnull_resettable) before returning the instance.3.
String.re.date/dateTimeshared that same instanceTheir private static formatters were initialized from
Date.dateFormatter, so on the main thread all three were the same object, and parsing depended on whoever last setdateFormat. Each now has its own formatter withen_US_POSIX, as recommended for fixed-format parsing (QA1480). This also fixes parsing for users on Buddhist/Japanese calendars or 12-hour time.4. AES with an empty IV was nondeterministic
With the default empty
iv, the emptyData'sbaseAddressis a non-nil stack pointer, andCCCryptread 16 garbage bytes from it as the IV. Encrypt and decrypt could read different bytes, so"123"sometimes decrypted to"12". We now passnil, so CommonCrypto uses an all-zero IV.The docs claimed an empty IV meant ECB, but ECB mode was never enabled; they now describe the actual behavior. For input shorter than one block, an all-zero IV with CBC is identical to ECB. Known-answer vectors from
opensslwere added, because a round trip alone can't catch a garbage IV.Test fixes
en_USwhere the API takes a locale, and skip the remaining locale-dependent tests elsewhereURL(string:)percent-encodes"invalid url"instead of returning nil"http://exa mple.com", which is invalid under both parsers. Assert the lenientString.re.urlencoding with an input that behaves the same before and after iOS 17attributes(at: 0)on an empty string, the same VC pushed twice,count += 1on a concurrent queue, a 0.1s debounce windowUIRefreshControl.beginRefreshing()is ignored outside a window. TextKit 2 only estimatescontentSizefor off-screen textwrapToContentwith a measured heightA second commit applies Xcode 27's project format rewrites (pbxproj entry reordering only, plus a dropped
BlueprintNameattribute).Verification
ReerKit-iOS: 768 tests, 0 failures across consecutive full runstestAesandtestForEachInParallel: 200 iterations each, all passed-testLanguage zh-Hans -testRegion CNshow as skipped, not failed