REGRESSION: run-webkit-tests may fail when using booted simulators
authorjbedard@apple.com <jbedard@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Dec 2018 23:21:33 +0000 (23:21 +0000)
committerjbedard@apple.com <jbedard@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Dec 2018 23:21:33 +0000 (23:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=192470
<rdar://problem/46532001>

Reviewed by Lucas Forschler.

* Scripts/webkitpy/layout_tests/controllers/manager.py:
(Manager.run): Logging uses the number of child processes to print out information about how efficiently tests
were sharded after the fact. This number is the most meaningful if it is the maximum number of child processes used.
* Scripts/webkitpy/port/base.py:
(Port.max_child_processes): By default, Ports do not support running on any specific kind of device.
* Scripts/webkitpy/port/device_port.py:
(DevicePort.default_child_processes): Rather than using the currently initialized devices as a proxy for how many
child processes are being used, check the device manager every time. Regardless of which devices are attached or
available, iOS cannot boot watchOS devices and vice-versa. dedicated_simulators is not a known argument to
device_count_for_type, use use_booted_simulator instead.
(DevicePort.max_child_processes): Simulators can boot more devices than what is specified by device_count_for_type,
but, if no devices are available, then max_child_processes should return 0 even for simulators.
* Scripts/webkitpy/port/ios_device_unittest.py:
(IOSDeviceTest):
(IOSDeviceTest.test_max_child_processes):
* Scripts/webkitpy/port/ios_simulator_unittest.py:
(IOSSimulatorTest):
(IOSSimulatorTest.test_max_child_processes):
* Scripts/webkitpy/port/port_testcase.py:
(PortTestCase):
(PortTestCase.test_max_child_processes):
* Scripts/webkitpy/port/watch_simulator_unittest.py:
(WatchSimulatorTest):
(WatchSimulatorTest.test_max_child_processes):

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

Tools/ChangeLog
Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
Tools/Scripts/webkitpy/port/base.py
Tools/Scripts/webkitpy/port/device_port.py
Tools/Scripts/webkitpy/port/ios_device_unittest.py
Tools/Scripts/webkitpy/port/ios_simulator_unittest.py
Tools/Scripts/webkitpy/port/port_testcase.py
Tools/Scripts/webkitpy/port/watch_simulator_unittest.py

index 106b685..b46e501 100644 (file)
@@ -1,5 +1,38 @@
 2018-12-06  Jonathan Bedard  <jbedard@apple.com>
 
+        REGRESSION: run-webkit-tests may fail when using booted simulators
+        https://bugs.webkit.org/show_bug.cgi?id=192470
+        <rdar://problem/46532001>
+
+        Reviewed by Lucas Forschler.
+
+        * Scripts/webkitpy/layout_tests/controllers/manager.py:
+        (Manager.run): Logging uses the number of child processes to print out information about how efficiently tests
+        were sharded after the fact. This number is the most meaningful if it is the maximum number of child processes used.
+        * Scripts/webkitpy/port/base.py:
+        (Port.max_child_processes): By default, Ports do not support running on any specific kind of device.
+        * Scripts/webkitpy/port/device_port.py:
+        (DevicePort.default_child_processes): Rather than using the currently initialized devices as a proxy for how many
+        child processes are being used, check the device manager every time. Regardless of which devices are attached or
+        available, iOS cannot boot watchOS devices and vice-versa. dedicated_simulators is not a known argument to
+        device_count_for_type, use use_booted_simulator instead.
+        (DevicePort.max_child_processes): Simulators can boot more devices than what is specified by device_count_for_type,
+        but, if no devices are available, then max_child_processes should return 0 even for simulators.
+        * Scripts/webkitpy/port/ios_device_unittest.py:
+        (IOSDeviceTest):
+        (IOSDeviceTest.test_max_child_processes):
+        * Scripts/webkitpy/port/ios_simulator_unittest.py:
+        (IOSSimulatorTest):
+        (IOSSimulatorTest.test_max_child_processes):
+        * Scripts/webkitpy/port/port_testcase.py:
+        (PortTestCase):
+        (PortTestCase.test_max_child_processes):
+        * Scripts/webkitpy/port/watch_simulator_unittest.py:
+        (WatchSimulatorTest):
+        (WatchSimulatorTest.test_max_child_processes):
+
+2018-12-06  Jonathan Bedard  <jbedard@apple.com>
+
         webkitpy: Ignore case when comparing device types (Follow-up fix)
         https://bugs.webkit.org/show_bug.cgi?id=192409
         <rdar://problem/46491558>
index f77843b..c4e2139 100644 (file)
@@ -245,6 +245,7 @@ class Manager(object):
         retry_results = None
         enabled_pixel_tests_in_retry = False
 
+        max_child_processes_for_run = 1
         child_processes_option_value = self._options.child_processes
 
         while device_type_order:
@@ -260,6 +261,8 @@ class Manager(object):
                 _log.info('')
                 continue
 
+            max_child_processes_for_run = max(self._options.child_processes, max_child_processes_for_run)
+
             # This loop looks for any less-specific device types which match the current device type
             index = 0
             while index < len(device_type_order):
@@ -281,6 +284,9 @@ class Manager(object):
             retry_results = retry_results.merge(temp_retry_results) if retry_results else temp_retry_results
             enabled_pixel_tests_in_retry |= temp_enabled_pixel_tests_in_retry
 
+        # Used for final logging, max_child_processes_for_run is most relevant here.
+        self._options.child_processes = max_child_processes_for_run
+
         self._runner.stop_servers()
 
         end_time = time.time()
index 4310829..d01b20b 100644 (file)
@@ -181,8 +181,10 @@ class Port(object):
         """Return the number of DumpRenderTree instances to use for this port."""
         return self._executive.cpu_count()
 
-    def max_child_processes(self, **kwargs):
+    def max_child_processes(self, device_type=None):
         """Forbid the user from specifying more than this number of child processes"""
+        if device_type:
+            return 0
         return float('inf')
 
     def worker_startup_delay_secs(self):
index 1734e33..967c7a8 100644 (file)
@@ -115,18 +115,25 @@ class DevicePort(DarwinPort):
     def default_child_processes(self, device_type=None):
         if not self.DEVICE_MANAGER:
             raise RuntimeError(self.NO_DEVICE_MANAGER)
-        if self.DEVICE_MANAGER.INITIALIZED_DEVICES:
-            return len(self.DEVICE_MANAGER.INITIALIZED_DEVICES)
+
+        # FIXME Checking software variant is important for simulators, otherwise an iOS port could boot a watchOS simulator.
+        # Really, the DEFAULT_DEVICE_TYPE for simulators should be a general instead of specific type, then this code would
+        # explicitly compare against device_type
+        device_type = self._device_type_with_version(device_type)
+        if device_type.software_variant and self.DEFAULT_DEVICE_TYPE.software_variant != device_type.software_variant:
+            return 0
+
         return self.DEVICE_MANAGER.device_count_for_type(
             self._device_type_with_version(device_type),
             host=self.host,
-            dedicated_simulators=not self.get_option('dedicated_simulators', False),
+            use_booted_simulator=not self.get_option('dedicated_simulators', False),
         )
 
     def max_child_processes(self, device_type=None):
-        if self.DEVICE_MANAGER == SimulatedDeviceManager:
-            return super(DevicePort, self).max_child_processes(device_type=device_type)
-        return self.default_child_processes(device_type=device_type)
+        result = self.default_child_processes(device_type=device_type)
+        if result and self.DEVICE_MANAGER == SimulatedDeviceManager:
+            return super(DevicePort, self).max_child_processes(device_type=None)
+        return result
 
     def setup_test_run(self, device_type=None):
         if not self.DEVICE_MANAGER:
index a3984b2..3f4b287 100644 (file)
@@ -112,3 +112,6 @@ class IOSDeviceTest(ios_testcase.IOSTest):
         self.assertEqual(search_path[5], '/mock-checkout/LayoutTests/platform/ios-wk2')
         self.assertEqual(search_path[6], '/mock-checkout/LayoutTests/platform/ios')
         self.assertEqual(search_path[7], '/mock-checkout/LayoutTests/platform/wk2')
+
+    def test_max_child_processes(self):
+        pass
index f59ba46..3c03e62 100644 (file)
@@ -27,6 +27,7 @@ from webkitpy.common.system.outputcapture import OutputCapture
 from webkitpy.common.version import Version
 from webkitpy.tool.mocktool import MockOptions
 from webkitpy.common.system.executive_mock import MockExecutive2, ScriptError
+from webkitpy.xcode.device_type import DeviceType
 
 
 class IOSSimulatorTest(ios_testcase.IOSTest):
@@ -115,3 +116,7 @@ class IOSSimulatorTest(ios_testcase.IOSTest):
         self.assertEqual(search_path[5], '/mock-checkout/LayoutTests/platform/ios-wk2')
         self.assertEqual(search_path[6], '/mock-checkout/LayoutTests/platform/ios')
         self.assertEqual(search_path[7], '/mock-checkout/LayoutTests/platform/wk2')
+
+    def test_max_child_processes(self):
+        port = self.make_port()
+        self.assertEqual(port.max_child_processes(DeviceType.from_string('Apple Watch')), 0)
index 2d68e5b..9cc3d7a 100644 (file)
@@ -684,3 +684,8 @@ MOCK output of child process
     def test_additional_platform_directory(self):
         port = self.make_port(options=MockOptions(additional_platform_directory=['/tmp/foo']))
         self.assertEqual(port.baseline_search_path()[0], '/tmp/foo')
+
+    def test_max_child_processes(self):
+        port = self.make_port()
+        self.assertEqual(port.max_child_processes(True), 0)
+        self.assertEqual(port.max_child_processes(), float('inf'))
index 8a77581..850941c 100644 (file)
@@ -26,6 +26,7 @@ from webkitpy.common.version import Version
 from webkitpy.port.watch_simulator import WatchSimulatorPort
 from webkitpy.port import watch_testcase
 from webkitpy.tool.mocktool import MockOptions
+from webkitpy.xcode.device_type import DeviceType
 
 
 class WatchSimulatorTest(watch_testcase.WatchTest):
@@ -74,3 +75,7 @@ class WatchSimulatorTest(watch_testcase.WatchTest):
         port._executive = MockExecutive2(run_command_fn=throwing_run_command)
         expected_stdout = "['xcrun', '--sdk', 'watchsimulator', '-find', 'test']\n"
         OutputCapture().assert_outputs(self, port.xcrun_find, args=['test', 'falling'], expected_stdout=expected_stdout)
+
+    def test_max_child_processes(self):
+        port = self.make_port()
+        self.assertEqual(port.max_child_processes(DeviceType.from_string('iPhone')), 0)