Changeset 256297 in webkit


Ignore:
Timestamp:
Feb 11, 2020 12:24:47 AM (4 years ago)
Author:
Wenson Hsieh
Message:

[iOS] Non-internal API test runners frequently crash due to Objective-C exceptions
https://bugs.webkit.org/show_bug.cgi?id=207525
<rdar://problem/59110543>

Reviewed by Tim Horton.

After the fix for <rdar://problem/56301207>, some scroll view content offset changes will attempt to call into
CoreAnalytics API to try and report data about scrolling velocities. In the iOS 13.3 simulator, this involves
creating a dictionary, of which one of the keys is the bundle identifier of the application. The value is
unconditionally inserted into the dictionary. Since TestWebKitAPI does not run in the context of a
UIApplication, the bundle identifier (that is, NSBundle.mainBundle.bundleIdentifier) ends up being nil,
causing us to crash upon trying to create the dictionary.

While it would make things easier, we can't just swizzle -bundleIdentifier for the entirely of every test, since
some tests expect the bundle identifier to be nil (or call into system frameworks that expect the bundle
identifier to be nil). These tests fail or time out when -bundleIdentifier is unconditionally swizzled
throughout the test run. To work around this bug for the time being, simply pretend that we have a bundle
identifier when running API tests on iOS, by swizzling -[NSBundle bundleIdentifier] to return a string at the
beginning of each API test.

  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/cocoa/TestWKWebView.mm:

(overrideBundleIdentifier):

Move this to the top of the file, so it can be shared.

(+[WKWebView initialize]):

At the start of each test, force UIKit to cache a fake value for _UIMainBundleIdentifier() by invoking an
internal class method that calls into the internal helper function, with no other side effects.

  • TestWebKitAPI/ios/UIKitSPI.h:
Location:
trunk/Tools
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r256237 r256297  
     12020-02-11  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] Non-internal API test runners frequently crash due to Objective-C exceptions
     4        https://bugs.webkit.org/show_bug.cgi?id=207525
     5        <rdar://problem/59110543>
     6
     7        Reviewed by Tim Horton.
     8
     9        After the fix for <rdar://problem/56301207>, some scroll view content offset changes will attempt to call into
     10        CoreAnalytics API to try and report data about scrolling velocities. In the iOS 13.3 simulator, this involves
     11        creating a dictionary, of which one of the keys is the bundle identifier of the application. The value is
     12        unconditionally inserted into the dictionary. Since TestWebKitAPI does not run in the context of a
     13        UIApplication, the bundle identifier (that is, `NSBundle.mainBundle.bundleIdentifier`) ends up being nil,
     14        causing us to crash upon trying to create the dictionary.
     15
     16        While it would make things easier, we can't just swizzle -bundleIdentifier for the entirely of every test, since
     17        some tests expect the bundle identifier to be nil (or call into system frameworks that expect the bundle
     18        identifier to be nil). These tests fail or time out when -bundleIdentifier is unconditionally swizzled
     19        throughout the test run. To work around this bug for the time being, simply pretend that we have a bundle
     20        identifier when running API tests on iOS, by swizzling `-[NSBundle bundleIdentifier]` to return a string at the
     21        beginning of each API test.
     22
     23        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     24        * TestWebKitAPI/cocoa/TestWKWebView.mm:
     25        (overrideBundleIdentifier):
     26
     27        Move this to the top of the file, so it can be shared.
     28
     29        (+[WKWebView initialize]):
     30
     31        At the start of each test, force UIKit to cache a fake value for `_UIMainBundleIdentifier()` by invoking an
     32        internal class method that calls into the internal helper function, with no other side effects.
     33
     34        * TestWebKitAPI/ios/UIKitSPI.h:
     35
    1362020-02-10  Jonathan Bedard  <jbedard@apple.com>
    237
  • trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm

    r256079 r256297  
    5252SOFT_LINK_CLASS(UIKit, UIWindow)
    5353
     54static NSString *overrideBundleIdentifier(id, SEL)
     55{
     56    return @"com.apple.TestWebKitAPI";
     57}
     58
    5459@implementation WKWebView (WKWebViewTestingQuirks)
    5560
     
    6671
    6772@implementation WKWebView (TestWebKitAPI)
     73
     74#if PLATFORM(IOS_FAMILY)
     75
     76+ (void)initialize
     77{
     78    // FIXME: This hack should no longer be necessary on builds that have the fix for <rdar://problem/56790195>.
     79    // Calling +displayIdentifier will guarantee a call to an internal UIKit helper method that caches the fake
     80    // bundle name "com.apple.TestWebKitAPI" for the rest of the process' lifetime. This allows us to avoid crashing
     81    // under -[UIScrollView setContentOffset:animated:] due to telemetry code that requires a bundle identifier.
     82    // Note that this swizzling is temporary, since unconditionally swizzling -[NSBundle bundleIdentifier] for the
     83    // entirely of the test causes other tests to fail or time out.
     84    InstanceMethodSwizzler bundleIdentifierSwizzler(NSBundle.class, @selector(bundleIdentifier), reinterpret_cast<IMP>(overrideBundleIdentifier));
     85    [UIApplication displayIdentifier];
     86}
     87
     88#endif // PLATFORM(IOS_FAMILY)
    6889
    6990- (void)loadTestPageNamed:(NSString *)pageName
     
    312333static NeverDestroyed<std::unique_ptr<InstanceMethodSwizzler>> gApplicationKeyWindowSwizzler;
    313334static NeverDestroyed<std::unique_ptr<InstanceMethodSwizzler>> gSharedApplicationSwizzler;
    314 
    315 static NSString *overrideBundleIdentifier()
    316 {
    317     return @"com.apple.TestWebKitAPI";
    318 }
    319335
    320336static void setOverriddenApplicationKeyWindow(UIWindow *window)
  • trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h

    r256000 r256297  
    262262@end
    263263
     264@interface UIApplication (Internal)
     265+ (NSString *)displayIdentifier;
     266@end
     267
    264268#endif // PLATFORM(IOS_FAMILY)
Note: See TracChangeset for help on using the changeset viewer.