Title: [289169] trunk/Tools
Revision
289169
Author
wenson_hs...@apple.com
Date
2022-02-06 08:14:09 -0800 (Sun, 06 Feb 2022)

Log Message

Adjust `platformResetStateToConsistentValues` to avoid grabbing the general pasteboard when possible
https://bugs.webkit.org/show_bug.cgi?id=236196

Reviewed by Darin Adler.

For reasons that are still unknown, when running layout tests in the iOS 15.4 simulator, the iOS simulator's
`pasted` sometimes gets into a state where the work queue (com.apple.pasteboard.PBPasteboardModel-work-queue)
gets permanently stuck while attempting to save pasteboard items.

Once in this state, all subsequent layout tests will time out (regardless of whether the tests themselves
exercise copy and paste), since the process of resetting the harness to a consistent state always tries to clear
the general pasteboard by setting `items` to an empty array. This means that every layout test that tries to
start after getting into the above state will hang during state reset, before it even gets a chance to load the
layout test.

To avoid this, only clear the general pasteboard if the test actually attempted to add data to the pasteboard.
While this doesn't fix a large number of editing and copy/paste-related layout tests on iOS 15.4, it does allow
us to skip these tests for now and continue running the remaining layout tests.

* WebKitTestRunner/TestController.h:
* WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
(WTR::TestController::pasteboardConsistencyEnforcer):
* WebKitTestRunner/ios/UIPasteboardConsistencyEnforcer.h: Added.

Add a helper class that listens for notifications whenever the contents of any pasteboard changes; if the name
of the changed pasteboard matches, we clear out its items when `-clearPasteboard` is invoked. It's critical to
pass only a pasteboard name here instead of a pasteboard itself, since even calling `+generalPasteboard` causes
the test to hang.

* WebKitTestRunner/ios/UIPasteboardConsistencyEnforcer.mm: Added.
(-[UIPasteboardConsistencyEnforcer initWithPasteboardName:]):
(-[UIPasteboardConsistencyEnforcer clearPasteboard]):
(-[UIPasteboardConsistencyEnforcer pasteboardChanged:]):

Modified Paths

Added Paths

Diff

Modified: trunk/Tools/ChangeLog (289168 => 289169)


--- trunk/Tools/ChangeLog	2022-02-06 15:39:56 UTC (rev 289168)
+++ trunk/Tools/ChangeLog	2022-02-06 16:14:09 UTC (rev 289169)
@@ -1,3 +1,41 @@
+2022-02-06  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Adjust `platformResetStateToConsistentValues` to avoid grabbing the general pasteboard when possible
+        https://bugs.webkit.org/show_bug.cgi?id=236196
+
+        Reviewed by Darin Adler.
+
+        For reasons that are still unknown, when running layout tests in the iOS 15.4 simulator, the iOS simulator's
+        `pasted` sometimes gets into a state where the work queue (com.apple.pasteboard.PBPasteboardModel-work-queue)
+        gets permanently stuck while attempting to save pasteboard items.
+
+        Once in this state, all subsequent layout tests will time out (regardless of whether the tests themselves
+        exercise copy and paste), since the process of resetting the harness to a consistent state always tries to clear
+        the general pasteboard by setting `items` to an empty array. This means that every layout test that tries to
+        start after getting into the above state will hang during state reset, before it even gets a chance to load the
+        layout test.
+
+        To avoid this, only clear the general pasteboard if the test actually attempted to add data to the pasteboard.
+        While this doesn't fix a large number of editing and copy/paste-related layout tests on iOS 15.4, it does allow
+        us to skip these tests for now and continue running the remaining layout tests.
+
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
+        * WebKitTestRunner/ios/TestControllerIOS.mm:
+        (WTR::TestController::platformResetStateToConsistentValues):
+        (WTR::TestController::pasteboardConsistencyEnforcer):
+        * WebKitTestRunner/ios/UIPasteboardConsistencyEnforcer.h: Added.
+
+        Add a helper class that listens for notifications whenever the contents of any pasteboard changes; if the name
+        of the changed pasteboard matches, we clear out its items when `-clearPasteboard` is invoked. It's critical to
+        pass only a pasteboard name here instead of a pasteboard itself, since even calling `+generalPasteboard` causes
+        the test to hang.
+
+        * WebKitTestRunner/ios/UIPasteboardConsistencyEnforcer.mm: Added.
+        (-[UIPasteboardConsistencyEnforcer initWithPasteboardName:]):
+        (-[UIPasteboardConsistencyEnforcer clearPasteboard]):
+        (-[UIPasteboardConsistencyEnforcer pasteboardChanged:]):
+
 2022-02-05  Yusuke Suzuki  <ysuz...@apple.com>
 
         Thread suspend and resume should take a global lock to avoid deadlock

Modified: trunk/Tools/WebKitTestRunner/TestController.h (289168 => 289169)


--- trunk/Tools/WebKitTestRunner/TestController.h	2022-02-06 15:39:56 UTC (rev 289168)
+++ trunk/Tools/WebKitTestRunner/TestController.h	2022-02-06 16:14:09 UTC (rev 289169)
@@ -47,6 +47,7 @@
 
 OBJC_CLASS NSString;
 OBJC_CLASS UIKeyboardInputMode;
+OBJC_CLASS UIPasteboardConsistencyEnforcer;
 OBJC_CLASS WKWebViewConfiguration;
 
 namespace WTR {
@@ -431,6 +432,10 @@
     void decidePolicyForGeolocationPermissionRequestIfPossible();
     void decidePolicyForUserMediaPermissionRequestIfPossible();
 
+#if PLATFORM(IOS_FAMILY)
+    UIPasteboardConsistencyEnforcer *pasteboardConsistencyEnforcer();
+#endif
+
     // WKContextInjectedBundleClient
     static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef messageBody, const void*);
     static void didReceiveSynchronousMessageFromInjectedBundleWithListener(WKContextRef, WKStringRef messageName, WKTypeRef messageBody, WKMessageListenerRef, const void*);
@@ -575,6 +580,7 @@
 
 #if PLATFORM(IOS_FAMILY)
     Vector<std::unique_ptr<InstanceMethodSwizzler>> m_inputModeSwizzlers;
+    RetainPtr<UIPasteboardConsistencyEnforcer> m_pasteboardConsistencyEnforcer;
     RetainPtr<UIKeyboardInputMode> m_overriddenKeyboardInputMode;
     Vector<std::unique_ptr<InstanceMethodSwizzler>> m_presentPopoverSwizzlers;
 #endif

Modified: trunk/Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj (289168 => 289169)


--- trunk/Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj	2022-02-06 15:39:56 UTC (rev 289168)
+++ trunk/Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj	2022-02-06 16:14:09 UTC (rev 289169)
@@ -160,6 +160,8 @@
 		E132AA3D17CE776F00611DF0 /* WebKitTestRunnerEvent.mm in Sources */ = {isa = PBXBuildFile; fileRef = E132AA3B17CE776F00611DF0 /* WebKitTestRunnerEvent.mm */; };
 		E1C642C617CBCD4C00D66A3C /* WebKitTestRunnerPasteboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = E1C642C417CBCD4C00D66A3C /* WebKitTestRunnerPasteboard.mm */; };
 		F4010B7E24DA205300A876E2 /* PoseAsClass.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4010B7C24DA204800A876E2 /* PoseAsClass.mm */; };
+		F415C22C27AF52D30028F505 /* UIPasteboardConsistencyEnforcer.h in Headers */ = {isa = PBXBuildFile; fileRef = F415C22A27AF52D30028F505 /* UIPasteboardConsistencyEnforcer.h */; };
+		F415C23527AF5B390028F505 /* UIPasteboardConsistencyEnforcer.mm in Sources */ = {isa = PBXBuildFile; fileRef = F415C22B27AF52D30028F505 /* UIPasteboardConsistencyEnforcer.mm */; };
 		F44A531721B899E200DBB99C /* ClassMethodSwizzler.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44A531421B899DA00DBB99C /* ClassMethodSwizzler.mm */; };
 		F44A531821B899E500DBB99C /* InstanceMethodSwizzler.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44A531621B899DA00DBB99C /* InstanceMethodSwizzler.mm */; };
 		F46240B1217013E500917B16 /* UIScriptControllerCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = F46240AF2170128300917B16 /* UIScriptControllerCocoa.mm */; };
@@ -436,6 +438,8 @@
 		E1C642C517CBCD4C00D66A3C /* WebKitTestRunnerPasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitTestRunnerPasteboard.h; sourceTree = "<group>"; };
 		F4010B7C24DA204800A876E2 /* PoseAsClass.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PoseAsClass.mm; path = ../TestRunnerShared/cocoa/PoseAsClass.mm; sourceTree = "<group>"; };
 		F4010B7D24DA204800A876E2 /* PoseAsClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PoseAsClass.h; path = ../TestRunnerShared/cocoa/PoseAsClass.h; sourceTree = "<group>"; };
+		F415C22A27AF52D30028F505 /* UIPasteboardConsistencyEnforcer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIPasteboardConsistencyEnforcer.h; sourceTree = "<group>"; };
+		F415C22B27AF52D30028F505 /* UIPasteboardConsistencyEnforcer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UIPasteboardConsistencyEnforcer.mm; sourceTree = "<group>"; };
 		F44A531321B899DA00DBB99C /* InstanceMethodSwizzler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InstanceMethodSwizzler.h; path = ../TestRunnerShared/cocoa/InstanceMethodSwizzler.h; sourceTree = "<group>"; };
 		F44A531421B899DA00DBB99C /* ClassMethodSwizzler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ClassMethodSwizzler.mm; path = ../TestRunnerShared/cocoa/ClassMethodSwizzler.mm; sourceTree = "<group>"; };
 		F44A531521B899DA00DBB99C /* ClassMethodSwizzler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClassMethodSwizzler.h; path = ../TestRunnerShared/cocoa/ClassMethodSwizzler.h; sourceTree = "<group>"; };
@@ -744,6 +748,8 @@
 				0FEBF8591BB61DF20028722D /* HIDEventGenerator.mm */,
 				2EE52D131890A9FB0010ED21 /* PlatformWebViewIOS.mm */,
 				2EE52D141890A9FB0010ED21 /* TestControllerIOS.mm */,
+				F415C22A27AF52D30028F505 /* UIPasteboardConsistencyEnforcer.h */,
+				F415C22B27AF52D30028F505 /* UIPasteboardConsistencyEnforcer.mm */,
 				2D0BEE1722EAD1360092B738 /* UIScriptControllerIOS.h */,
 				0F73B55B1BA89042004B3EF4 /* UIScriptControllerIOS.mm */,
 			);
@@ -991,6 +997,7 @@
 				0F73B5521BA78968004B3EF4 /* JSUIScriptController.h in Headers */,
 				2DFA98481D7F70CF00AFF2C9 /* SharedEventStreamsMac.h in Headers */,
 				2904FA1E265CC5D900A7EBC9 /* StringFunctionsCocoa.h in Headers */,
+				F415C22C27AF52D30028F505 /* UIPasteboardConsistencyEnforcer.h in Headers */,
 				2D058E0922E2EE2200E4C145 /* UIScriptControllerCocoa.h in Headers */,
 				2D058E0B22E2EF6D00E4C145 /* UIScriptControllerMac.h in Headers */,
 			);
@@ -1222,6 +1229,7 @@
 				2E63ED941891ADAD002A7AFC /* mainIOS.mm in Sources */,
 				2E63ED911891ADAD002A7AFC /* PlatformWebViewIOS.mm in Sources */,
 				2E63ED921891ADAD002A7AFC /* TestControllerIOS.mm in Sources */,
+				F415C23527AF5B390028F505 /* UIPasteboardConsistencyEnforcer.mm in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: trunk/Tools/WebKitTestRunner/ios/TestControllerIOS.mm (289168 => 289169)


--- trunk/Tools/WebKitTestRunner/ios/TestControllerIOS.mm	2022-02-06 15:39:56 UTC (rev 289168)
+++ trunk/Tools/WebKitTestRunner/ios/TestControllerIOS.mm	2022-02-06 16:14:09 UTC (rev 289169)
@@ -34,6 +34,7 @@
 #import "TestRunnerWKWebView.h"
 #import "TextInputSPI.h"
 #import "UIKitSPI.h"
+#import "UIPasteboardConsistencyEnforcer.h"
 #import <Foundation/Foundation.h>
 #import <UIKit/UIKit.h>
 #import <WebKit/WKPreferencesPrivate.h>
@@ -154,7 +155,7 @@
     cocoaResetStateToConsistentValues(options);
 
     [UIKeyboardImpl.activeInstance setCorrectionLearningAllowed:NO];
-    [UIPasteboard generalPasteboard].items = @[ ];
+    [pasteboardConsistencyEnforcer() clearPasteboard];
     [[UIApplication sharedApplication] _cancelAllTouches];
     [[UIDevice currentDevice] setOrientation:UIDeviceOrientationPortrait animated:NO];
 
@@ -384,4 +385,11 @@
     [UIKeyboardImpl.sharedInstance prepareKeyboardInputModeFromPreferences:nil];
 }
 
+UIPasteboardConsistencyEnforcer *TestController::pasteboardConsistencyEnforcer()
+{
+    if (!m_pasteboardConsistencyEnforcer)
+        m_pasteboardConsistencyEnforcer = adoptNS([[UIPasteboardConsistencyEnforcer alloc] initWithPasteboardName:UIPasteboardNameGeneral]);
+    return m_pasteboardConsistencyEnforcer.get();
+}
+
 } // namespace WTR

Added: trunk/Tools/WebKitTestRunner/ios/UIPasteboardConsistencyEnforcer.h (0 => 289169)


--- trunk/Tools/WebKitTestRunner/ios/UIPasteboardConsistencyEnforcer.h	                        (rev 0)
+++ trunk/Tools/WebKitTestRunner/ios/UIPasteboardConsistencyEnforcer.h	2022-02-06 16:14:09 UTC (rev 289169)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if PLATFORM(IOS_FAMILY)
+
+#import <UIKit/UIPasteboard.h>
+
+@interface UIPasteboardConsistencyEnforcer : NSObject
+
+- (instancetype)initWithPasteboardName:(UIPasteboardName)pasteboardName;
+- (void)clearPasteboard;
+
+@end
+
+#endif // PLATFORM(IOS_FAMILY)

Added: trunk/Tools/WebKitTestRunner/ios/UIPasteboardConsistencyEnforcer.mm (0 => 289169)


--- trunk/Tools/WebKitTestRunner/ios/UIPasteboardConsistencyEnforcer.mm	                        (rev 0)
+++ trunk/Tools/WebKitTestRunner/ios/UIPasteboardConsistencyEnforcer.mm	2022-02-06 16:14:09 UTC (rev 289169)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "UIPasteboardConsistencyEnforcer.h"
+
+#if PLATFORM(IOS_FAMILY)
+
+#import <UIKit/UIKit.h>
+#import <wtf/RetainPtr.h>
+
+@implementation UIPasteboardConsistencyEnforcer {
+    RetainPtr<UIPasteboard> _pasteboardToReset;
+    RetainPtr<UIPasteboardName> _pasteboardName;
+}
+
+- (instancetype)initWithPasteboardName:(UIPasteboardName)pasteboardName
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _pasteboardName = pasteboardName;
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pasteboardChanged:) name:UIPasteboardChangedNotification object:nil];
+    return self;
+}
+
+- (void)clearPasteboard
+{
+    [std::exchange(_pasteboardToReset, nil) setItems:@[ ]];
+}
+
+- (void)pasteboardChanged:(NSNotification *)notification
+{
+    if (_pasteboardToReset)
+        return;
+
+    auto pasteboard = dynamic_objc_cast<UIPasteboard>(notification.object);
+    if (![_pasteboardName isEqualToString:pasteboard.name])
+        return;
+
+    auto userInfoDictionary = dynamic_objc_cast<NSDictionary>(notification.userInfo);
+    if ([dynamic_objc_cast<NSArray>([userInfoDictionary objectForKey:UIPasteboardChangedTypesAddedKey]) count])
+        _pasteboardToReset = pasteboard;
+}
+
+@end
+
+#endif // PLATFORM(IOS_FAMILY)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to