Add debug flag to WebKitTestRunner to show where touches are being generated
authormegan_gardner@apple.com <megan_gardner@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Sep 2017 20:41:37 +0000 (20:41 +0000)
committermegan_gardner@apple.com <megan_gardner@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Sep 2017 20:41:37 +0000 (20:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=177583

Reviewed by Tim Horton and Wenson Hsieh.

Add a flag, and the ability to paint a dot where the HIDEventGenerator is creating fake touches to
send through UIKit. This will help in debugging touch tests, because it will be easier to see if
one is actually sending the touches at the locations that they expect. This will help differentiate between
problems in the locations of the touches, and other problems that can come up when writing tests.

* Scripts/webkitpy/layout_tests/run_webkit_tests.py:
(parse_args):
* Scripts/webkitpy/port/driver.py:
(Driver.cmd_line):
* WebKitTestRunner/Options.cpp:
(WTR::Options::Options):
(WTR::handleOptionShowTouches):
(WTR::OptionsHandler::OptionsHandler):
* WebKitTestRunner/Options.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::initialize):
* WebKitTestRunner/TestController.h:
(WTR::TestController::shouldShowTouches const):
* WebKitTestRunner/TestOptions.h:
* WebKitTestRunner/ios/HIDEventGenerator.h:
* WebKitTestRunner/ios/HIDEventGenerator.mm:
(-[DebugTouchView pointInside:withEvent:]):
(-[HIDEventGenerator setShouldShowTouches:]):
(-[HIDEventGenerator initDebugViews]):
(-[HIDEventGenerator updateDebugUI:withPoint:isTouching:]):
(-[HIDEventGenerator _createIOHIDEventWithInfo:]):
(-[HIDEventGenerator _createIOHIDEventType:]):
(-[HIDEventGenerator _updateTouchPoints:count:]):
(-[HIDEventGenerator touchDownAtPoints:touchCount:]):
(-[HIDEventGenerator liftUpAtPoints:touchCount:]):
(-[HIDEventGenerator moveToPoints:touchCount:duration:]):
(-[HIDEventGenerator markerEventReceived:]):
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::updatePlatformSpecificTestOptionsForTest const):
* WebKitTestRunner/ios/mainIOS.mm:
(-[WebKitTestRunnerApp _runTestController]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@222631 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
Tools/Scripts/webkitpy/port/driver.py
Tools/WebKitTestRunner/Options.cpp
Tools/WebKitTestRunner/Options.h
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestController.h
Tools/WebKitTestRunner/TestOptions.h
Tools/WebKitTestRunner/ios/HIDEventGenerator.h
Tools/WebKitTestRunner/ios/HIDEventGenerator.mm
Tools/WebKitTestRunner/ios/TestControllerIOS.mm

index a39b418..d7a06b1 100644 (file)
@@ -1,3 +1,47 @@
+2017-09-28  Megan Gardner  <megan_gardner@apple.com>
+
+        Add debug flag to WebKitTestRunner to show where touches are being generated
+        https://bugs.webkit.org/show_bug.cgi?id=177583
+
+        Reviewed by Tim Horton and Wenson Hsieh.
+
+        Add a flag, and the ability to paint a dot where the HIDEventGenerator is creating fake touches to
+        send through UIKit. This will help in debugging touch tests, because it will be easier to see if
+        one is actually sending the touches at the locations that they expect. This will help differentiate between
+        problems in the locations of the touches, and other problems that can come up when writing tests.
+
+        * Scripts/webkitpy/layout_tests/run_webkit_tests.py:
+        (parse_args):
+        * Scripts/webkitpy/port/driver.py:
+        (Driver.cmd_line):
+        * WebKitTestRunner/Options.cpp:
+        (WTR::Options::Options):
+        (WTR::handleOptionShowTouches):
+        (WTR::OptionsHandler::OptionsHandler):
+        * WebKitTestRunner/Options.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::initialize):
+        * WebKitTestRunner/TestController.h:
+        (WTR::TestController::shouldShowTouches const):
+        * WebKitTestRunner/TestOptions.h:
+        * WebKitTestRunner/ios/HIDEventGenerator.h:
+        * WebKitTestRunner/ios/HIDEventGenerator.mm:
+        (-[DebugTouchView pointInside:withEvent:]):
+        (-[HIDEventGenerator setShouldShowTouches:]):
+        (-[HIDEventGenerator initDebugViews]):
+        (-[HIDEventGenerator updateDebugUI:withPoint:isTouching:]):
+        (-[HIDEventGenerator _createIOHIDEventWithInfo:]):
+        (-[HIDEventGenerator _createIOHIDEventType:]):
+        (-[HIDEventGenerator _updateTouchPoints:count:]):
+        (-[HIDEventGenerator touchDownAtPoints:touchCount:]):
+        (-[HIDEventGenerator liftUpAtPoints:touchCount:]):
+        (-[HIDEventGenerator moveToPoints:touchCount:duration:]):
+        (-[HIDEventGenerator markerEventReceived:]):
+        * WebKitTestRunner/ios/TestControllerIOS.mm:
+        (WTR::TestController::updatePlatformSpecificTestOptionsForTest const):
+        * WebKitTestRunner/ios/mainIOS.mm:
+        (-[WebKitTestRunnerApp _runTestController]):
+
 2017-09-28  Mark Lam  <mark.lam@apple.com>
 
         [Re-landing] Turn on exception scope verification for JSC tests.
index 8b11a46..977eb71 100755 (executable)
@@ -299,6 +299,7 @@ def parse_args(args):
         optparse.make_option('--device-type', help='iOS Simulator device type identifier (default: i386 -> iPhone 5, x86_64 -> iPhone 5s)'),
         optparse.make_option('--dedicated-simulators', action="store_true", default=False,
             help="If set, dedicated iOS simulators will always be created.  If not set, the script will attempt to use any currently running simulator."),
+        optparse.make_option('--show-touches', action="store_true", default=False, help="If set, a small dot will be shown where the generated touches are. Helpful for debugging touch tests."),
     ]))
 
     option_group_definitions.append(("Miscellaneous Options", [
index 4e305a4..8d4c8d4 100644 (file)
@@ -423,6 +423,8 @@ class Driver(object):
             cmd.append('--threaded')
         if self._no_timeout:
             cmd.append('--no-timeout')
+        if self._port.get_option('show_touches'):
+            cmd.append('--show-touches')
 
         for allowed_host in self._port.allowed_hosts():
             cmd.append('--allowed-host')
index 53f0253..4508cf2 100644 (file)
@@ -43,6 +43,7 @@ Options::Options()
     , shouldUseAcceleratedDrawing(false)
     , shouldUseRemoteLayerTree(false)
     , shouldShowWebView(false)
+    , shouldShowTouches(false)
 {
 }
 
@@ -100,6 +101,12 @@ bool handleOptionShowWebView(Options& options, const char*, const char*)
     options.shouldShowWebView = true;
     return true;
 }
+    
+bool handleOptionShowTouches(Options& options, const char*, const char*)
+{
+    options.shouldShowTouches = true;
+    return true;
+}
 
 bool handleOptionAllowedHost(Options& options, const char*, const char* host)
 {
@@ -128,7 +135,8 @@ OptionsHandler::OptionsHandler(Options& o)
     optionList.append(Option("--accelerated-drawing", "Use accelerated drawing.", handleOptionAcceleratedDrawing));
     optionList.append(Option("--remote-layer-tree", "Use remote layer tree.", handleOptionRemoteLayerTree));
     optionList.append(Option("--allowed-host", "Allows access to the specified host from tests.", handleOptionAllowedHost, true));
-    optionList.append(Option("--show-webview", "Show the WebView during test runs (for Debugging)", handleOptionShowWebView));
+    optionList.append(Option("--show-webview", "Show the WebView during test runs (for debugging)", handleOptionShowWebView));
+    optionList.append(Option("--show-touches", "Show the touches during test runs (for debugging)", handleOptionShowTouches));
 
     optionList.append(Option(0, 0, handleOptionUnmatched));
 }
index 5549fe4..9f0717c 100644 (file)
@@ -48,6 +48,7 @@ struct Options {
     bool shouldUseAcceleratedDrawing;
     bool shouldUseRemoteLayerTree;
     bool shouldShowWebView;
+    bool shouldShowTouches;
     std::vector<std::string> paths;
     std::vector<std::string> allowedHosts;
 };
index 2f0f922..2580daf 100644 (file)
@@ -369,6 +369,7 @@ void TestController::initialize(int argc, const char* argv[])
     m_paths = options.paths;
     m_allowedHosts = options.allowedHosts;
     m_shouldShowWebView = options.shouldShowWebView;
+    m_shouldShowTouches = options.shouldShowTouches;
 
     if (options.printSupportedFeatures) {
         // FIXME: On Windows, DumpRenderTree uses this to expose whether it supports 3d
index eec0892..a989d5d 100644 (file)
@@ -85,6 +85,8 @@ public:
     bool usingServerMode() const { return m_usingServerMode; }
     void configureViewForTest(const TestInvocation&);
     
+    bool shouldShowTouches() const { return m_shouldShowTouches; }
+    
     bool beforeUnloadReturnValue() const { return m_beforeUnloadReturnValue; }
     void setBeforeUnloadReturnValue(bool value) { m_beforeUnloadReturnValue = value; }
 
@@ -390,6 +392,8 @@ private:
     bool m_shouldLogHistoryClientCallbacks { false };
     bool m_shouldShowWebView { false };
     
+    bool m_shouldShowTouches { false };
+    
     bool m_shouldDecideNavigationPolicyAfterDelay { false };
 
     WKRetainPtr<WKArrayRef> m_openPanelFileURLs;
index d491af4..6cdcb22 100644 (file)
@@ -50,6 +50,7 @@ struct TestOptions {
     bool enableCredentialManagement { false };
     bool enableIsSecureContextAttribute { true };
     bool enableInspectorAdditions { false };
+    bool shouldShowTouches { false };
 
     float deviceScaleFactor { 1 };
     Vector<String> overrideLanguages;
index 34e7917..f6e0cb1 100644 (file)
@@ -67,6 +67,8 @@ extern NSString* const HIDEventPhaseCanceled;
 
 @interface HIDEventGenerator : NSObject
 
+@property (nonatomic, assign) BOOL shouldShowTouches;
+
 + (HIDEventGenerator *)sharedHIDEventGenerator;
 
 // Touches
index 87b8406..57dae72 100644 (file)
@@ -80,6 +80,9 @@ static const IOHIDFloat defaultPathPressure = 0;
 static const NSUInteger maxTouchCount = 5;
 static const long nanosecondsPerSecond = 1e9;
 
+static const NSUInteger debugTouchDotRadius = 5;
+static const NSUInteger debugTouchDotSize = debugTouchDotRadius * 2;
+
 static int fingerIdentifiers[maxTouchCount] = { 2, 3, 4, 5, 1 };
 
 typedef enum {
@@ -149,6 +152,7 @@ static void delayBetweenMove(int eventIndex, double elapsed)
 
 @interface HIDEventGenerator ()
 @property (nonatomic, strong) NSMutableDictionary *eventCallbacks;
+@property (nonatomic, strong) NSArray<UIView *> *debugTouchViews;
 @end
 
 @implementation HIDEventGenerator {
@@ -186,6 +190,32 @@ static void delayBetweenMove(int eventIndex, double elapsed)
     return self;
 }
 
+- (void)dealloc
+{
+    [_eventCallbacks release];
+    [_debugTouchViews release];
+    [super dealloc];
+}
+
+- (void)initDebugViewsIfNeeded
+{
+    if (!self.shouldShowTouches || self.debugTouchViews)
+        return;
+
+    NSMutableArray *debugViews = [NSMutableArray arrayWithCapacity:maxTouchCount];
+    
+    for (NSUInteger i = 0; i < maxTouchCount; ++i) {
+        auto newView = adoptNS([[UIView alloc] initWithFrame:CGRectMake(10, 10, debugTouchDotSize, debugTouchDotSize)]);
+        [newView setUserInteractionEnabled:NO];
+        [newView layer].cornerRadius = debugTouchDotRadius;
+        [newView setBackgroundColor:[UIColor colorWithRed:1.0-i*.05 green:0.0 blue:1.0-i*.05 alpha:0.5]];
+        [newView setHidden:YES];
+        debugViews[i] = newView.get();
+        [[[UIApplication sharedApplication] keyWindow] addSubview:debugViews[i]];
+    }
+    self.debugTouchViews = [NSArray arrayWithArray:debugViews];
+}
+
 - (void)_sendIOHIDKeyboardEvent:(uint64_t)timestamp usage:(uint32_t)usage isKeyDown:(bool)isKeyDown
 {
     RetainPtr<IOHIDEventRef> eventRef = adoptCF(IOHIDEventCreateKeyboardEvent(kCFAllocatorDefault,
@@ -273,6 +303,14 @@ static InterpolationType interpolationFromString(NSString *string)
     return 0;
 }
 
+- (void)updateDebugIndicatorForTouch:(NSUInteger)index withPoint:(CGPoint)point isTouching:(BOOL)isTouching
+{
+    [self initDebugViewsIfNeeded];
+    
+    self.debugTouchViews[index].hidden = !isTouching;
+    self.debugTouchViews[index].center = point;
+}
+
 // FIXME: callers of _createIOHIDEventType could switch to this.
 - (IOHIDEventRef)_createIOHIDEventWithInfo:(NSDictionary *)info
 {
@@ -303,7 +341,9 @@ static InterpolationType interpolationFromString(NSString *string)
 
     NSArray *childEvents = info[HIDEventTouchesKey];
     for (NSDictionary *touchInfo in childEvents) {
-
+        if (self.shouldShowTouches)
+            [self updateDebugIndicatorForTouch:[touchInfo[HIDEventTouchIDKey] intValue] withPoint:CGPointMake([touchInfo[HIDEventXKey] floatValue], [touchInfo[HIDEventYKey] floatValue]) isTouching:(BOOL)touch];
+        
         IOHIDDigitizerEventMask childEventMask = 0;
 
         UITouchPhase phase = phaseFromString(touchInfo[HIDEventPhaseKey]);
@@ -390,6 +430,9 @@ static InterpolationType interpolationFromString(NSString *string)
 
         CGPoint point = pointInfo->point;
         point = CGPointMake(roundf(point.x), roundf(point.y));
+        if (self.shouldShowTouches)
+            [self updateDebugIndicatorForTouch:i withPoint:point isTouching:isTouching];
+
         RetainPtr<IOHIDEventRef> subEvent;
         if (pointInfo->isStylus) {
             if (eventType == StylusEventTouched) {
@@ -504,8 +547,11 @@ static InterpolationType interpolationFromString(NSString *string)
     _activePointCount = count;
 
     // Update point locations.
-    for (NSUInteger i = 0; i < count; ++i)
+    for (NSUInteger i = 0; i < count; ++i) {
         _activePoints[i].point = points[i];
+        if (self.shouldShowTouches)
+            [self updateDebugIndicatorForTouch:i withPoint:points[i] isTouching:YES];
+    }
     
     RetainPtr<IOHIDEventRef> eventRef = adoptCF([self _createIOHIDEventType:handEventType]);
     [self _sendHIDEvent:eventRef.get()];
@@ -520,6 +566,9 @@ static InterpolationType interpolationFromString(NSString *string)
     for (NSUInteger index = 0; index < touchCount; ++index) {
         _activePoints[index].point = locations[index];
         _activePoints[index].isStylus = NO;
+        
+        if (self.shouldShowTouches)
+            [self updateDebugIndicatorForTouch:index withPoint:locations[index] isTouching:YES];
     }
 
     RetainPtr<IOHIDEventRef> eventRef = adoptCF([self _createIOHIDEventType:HandEventTouched]);
@@ -550,8 +599,11 @@ static InterpolationType interpolationFromString(NSString *string)
 
     NSUInteger newPointCount = _activePointCount - touchCount;
 
-    for (NSUInteger index = 0; index < touchCount; ++index)
+    for (NSUInteger index = 0; index < touchCount; ++index) {
         _activePoints[newPointCount + index].point = locations[index];
+        if (self.shouldShowTouches)
+            self.debugTouchViews[index].hidden = YES;
+    }
     
     RetainPtr<IOHIDEventRef> eventRef = adoptCF([self _createIOHIDEventType:HandEventLifted]);
     [self _sendHIDEvent:eventRef.get()];
index ba90acc..0b1e3b8 100644 (file)
@@ -127,8 +127,11 @@ void TestController::platformConfigureViewForTest(const TestInvocation& test)
     // WKBundlePageSetUseTestingViewportConfiguration(false).
 }
 
-void TestController::updatePlatformSpecificTestOptionsForTest(TestOptions&, const std::string&) const
+void TestController::updatePlatformSpecificTestOptionsForTest(TestOptions& options, const std::string&) const
 {
+    
+    options.shouldShowTouches = shouldShowTouches();
+    [[HIDEventGenerator sharedHIDEventGenerator] setShouldShowTouches:options.shouldShowTouches];
 }
 
 void TestController::platformInitializeContext()