WebKit Bugzilla
Attachment 356618 Details for
Bug 192161
: webkitpy: Sort tests by associated device type
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for landing
bug-192161-20181205105232.patch (text/plain), 26.39 KB, created by
Jonathan Bedard
on 2018-12-05 10:52:33 PST
(
hide
)
Description:
Patch for landing
Filename:
MIME Type:
Creator:
Jonathan Bedard
Created:
2018-12-05 10:52:33 PST
Size:
26.39 KB
patch
obsolete
>Index: Tools/ChangeLog >=================================================================== >--- Tools/ChangeLog (revision 238900) >+++ Tools/ChangeLog (working copy) >@@ -1,3 +1,56 @@ >+2018-12-05 Jonathan Bedard <jbedard@apple.com> >+ >+ webkitpy: Sort tests by associated device type >+ https://bugs.webkit.org/show_bug.cgi?id=192161 >+ <rdar://problem/46345392> >+ >+ Reviewed by Lucas Forschler. >+ >+ Sort tests by device type and make an effort to run each specified device type. >+ Do not run tests if their specified device is not available. >+ >+ * Scripts/webkitpy/common/system/platforminfo.py: >+ (PlatformInfo.is_watchos): Add watchos bits to platform info. >+ (PlatformInfo._determine_os_name): Ditto. >+ * Scripts/webkitpy/layout_tests/controllers/manager.py: >+ (Manager.run): Assign each test a device type. Then, generate a list of >+ device types to sequentially iterate through. Note that a test will run >+ on the first device which matches. >+ (Manager._end_test_run): Handle the case where no devices are available and no >+ tests are run. >+ * Scripts/webkitpy/layout_tests/run_webkit_tests.py: >+ (_set_up_derived_options): Manage child processes in manager. >+ * Scripts/webkitpy/port/base.py: >+ (Port): >+ (Port.default_child_processes): Accept additional arguments. >+ (Port.max_child_processes): Add upper limit for number of child processes. >+ * Scripts/webkitpy/port/device_port.py: >+ (DevicePort): >+ (DevicePort._device_type_with_version): Adds version to the DeviceType. >+ (DevicePort.default_child_processes): Allows default_child_processes to be >+ attached to a device type. >+ (DevicePort.max_child_processes): Add upper limit to the maximum number of child processes. >+ (DevicePort.setup_test_run): Use _device_type_with_version. >+ * Scripts/webkitpy/port/ios_device.py: >+ (IOSDevicePort): >+ (IOSDevicePort.default_child_processes): Deleted. >+ * Scripts/webkitpy/port/ios_simulator.py: >+ (IOSSimulatorPort.default_child_processes): Deleted. >+ (IOSSimulatorPort.check_sys_deps): Deleted. >+ * Scripts/webkitpy/port/mac.py: >+ (MacPort.default_child_processes): Accept additional arguments. >+ * Scripts/webkitpy/port/test.py: >+ * Scripts/webkitpy/port/watch_device.py: >+ (WatchDevicePort): >+ (WatchDevicePort.default_child_processes): Deleted. >+ * Scripts/webkitpy/port/watch_simulator.py: >+ (WatchSimulatorPort.default_child_processes): Deleted. >+ (WatchSimulatorPort.check_sys_deps): Deleted. >+ * Scripts/webkitpy/xcode/simulated_device.py: >+ (SimulatedDeviceManager): >+ (SimulatedDeviceManager.device_count_for_type): Count the number of devices >+ available for a specific device type. >+ > 2018-12-05 Alicia Boya GarcÃa <aboya@igalia.com> > > [MSE][GStreamer] Remove the AppendPipeline state machine >Index: Tools/Scripts/webkitpy/common/system/platforminfo.py >=================================================================== >--- Tools/Scripts/webkitpy/common/system/platforminfo.py (revision 238900) >+++ Tools/Scripts/webkitpy/common/system/platforminfo.py (working copy) >@@ -72,6 +72,9 @@ class PlatformInfo(object): > def is_ios(self): > return self.os_name == 'ios' > >+ def is_watchos(self): >+ return self.os_name == 'watchos' >+ > def is_win(self): > return self.os_name == 'win' > >@@ -179,7 +182,7 @@ class PlatformInfo(object): > def _determine_os_name(self, sys_platform): > if sys_platform == 'darwin': > return 'mac' >- if sys_platform == 'ios': >+ if sys_platform == 'ios' or sys_platform == 'watchos': > return 'ios' > if sys_platform.startswith('linux'): > return 'linux' >Index: Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py >=================================================================== >--- Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py (revision 238900) >+++ Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py (working copy) >@@ -370,10 +370,6 @@ def _print_expectations(port, options, a > > def _set_up_derived_options(port, options): > """Sets the options values that depend on other options values.""" >- if not options.child_processes: >- options.child_processes = os.environ.get("WEBKIT_TEST_CHILD_PROCESSES", >- str(port.default_child_processes())) >- > if not options.configuration: > options.configuration = port.default_configuration() > >Index: Tools/Scripts/webkitpy/layout_tests/controllers/manager.py >=================================================================== >--- Tools/Scripts/webkitpy/layout_tests/controllers/manager.py (revision 238900) >+++ Tools/Scripts/webkitpy/layout_tests/controllers/manager.py (working copy) >@@ -104,7 +104,6 @@ class Manager(object): > return self.web_platform_test_subdir in test or self.webkit_specific_web_platform_test_subdir in test > > def _custom_device_for_test(self, test): >- # FIXME: Use available devices instead of CUSTOM_DEVICE_TYPES https://bugs.webkit.org/show_bug.cgi?id=192161 > # FIXME: This is a terrible way to do device-specific expected results https://bugs.webkit.org/show_bug.cgi?id=192162 > for device_type in self._port.CUSTOM_DEVICE_TYPES: > if device_type.hardware_family and device_type.hardware_family.lower() + self._port.TEST_PATH_SEPARATOR in test: >@@ -206,24 +205,24 @@ class Manager(object): > _log.critical('No tests to run.') > return test_run_results.RunDetails(exit_code=-1) > >- default_device_tests = [] >- > # Look for tests with custom device requirements. >- custom_device_tests = defaultdict(list) >+ test_device_mapping = defaultdict(list) > for test_file in tests_to_run: >- custom_device = self._custom_device_for_test(test_file) >- if custom_device: >- custom_device_tests[custom_device].append(test_file) >- else: >- default_device_tests.append(test_file) >+ test_device_mapping[self._custom_device_for_test(test_file) or self._port.DEFAULT_DEVICE_TYPE].append(test_file) > >- if custom_device_tests: >- for device_type, tests in custom_device_tests.iteritems(): >- _log.debug('{} tests use device {}'.format(len(tests), device_type)) >- >- initial_results = None >- retry_results = None >- enabled_pixel_tests_in_retry = False >+ # Order device types from most specific to least specific in the hopes that some of the more specific device >+ # types will match the less specific device types. >+ device_type_order = [] >+ types_with_family = [] >+ remaining_types = [] >+ for device_type in test_device_mapping.iterkeys(): >+ if device_type and device_type.hardware_family and device_type.hardware_type: >+ device_type_order.append(device_type) >+ elif device_type and device_type.hardware_family: >+ types_with_family.append(device_type) >+ else: >+ remaining_types.append(device_type) >+ device_type_order.extend(types_with_family + remaining_types) > > needs_http = any((self._is_http_test(test) and not self._needs_web_platform_test(test)) for test in tests_to_run) > needs_web_platform_test_server = any(self._needs_web_platform_test(test) for test in tests_to_run) >@@ -242,33 +241,48 @@ class Manager(object): > # Create the output directory if it doesn't already exist. > self._port.host.filesystem.maybe_make_directory(self._results_directory) > >- if default_device_tests: >- _log.info('') >- _log.info("Running %s", pluralize(len(tests_to_run), "test")) >- _log.info('') >- if not self._set_up_run(tests_to_run): >- return test_run_results.RunDetails(exit_code=-1) >+ initial_results = None >+ retry_results = None >+ enabled_pixel_tests_in_retry = False > >- initial_results, retry_results, enabled_pixel_tests_in_retry = self._run_test_subset(default_device_tests, tests_to_skip) >+ child_processes_option_value = self._options.child_processes > >- # Only use a single worker for custom device classes >- self._options.child_processes = 1 >- for device_type in custom_device_tests: >- device_tests = custom_device_tests[device_type] >- if device_tests: >- _log.info('') >- _log.info('Running %s for %s', pluralize(len(device_tests), "test"), device_type) >+ while device_type_order: >+ device_type = device_type_order[0] >+ tests = test_device_mapping[device_type] >+ del device_type_order[0] >+ >+ self._options.child_processes = min(self._port.max_child_processes(device_type=device_type), int(child_processes_option_value or self._port.default_child_processes(device_type=device_type))) >+ >+ _log.info('') >+ if not self._options.child_processes: >+ _log.info('Skipping {} because {} is not available'.format(pluralize(len(test_device_mapping[device_type]), 'test'), str(device_type))) > _log.info('') >- if not self._set_up_run(device_tests, device_type): >- return test_run_results.RunDetails(exit_code=-1) >+ continue >+ >+ # This loop looks for any less-specific device types which match the current device type >+ index = 0 >+ while index < len(device_type_order): >+ if device_type_order[index] == device_type: >+ tests.extend(test_device_mapping[device_type_order[index]]) >+ >+ # Remove devices types from device_type_order once tests associated with that type have been claimed. >+ del device_type_order[index] >+ else: >+ index += 1 > >- device_initial_results, device_retry_results, device_enabled_pixel_tests_in_retry = self._run_test_subset(device_tests, tests_to_skip) >+ _log.info('Running {}{}'.format(pluralize(len(tests), 'test'), ' for {}'.format(str(device_type)) if device_type else '')) >+ _log.info('') >+ if not self._set_up_run(tests, device_type): >+ return test_run_results.RunDetails(exit_code=-1) > >- initial_results = initial_results.merge(device_initial_results) if initial_results else device_initial_results >- retry_results = retry_results.merge(device_retry_results) if retry_results else device_retry_results >- enabled_pixel_tests_in_retry |= device_enabled_pixel_tests_in_retry >+ temp_initial_results, temp_retry_results, temp_enabled_pixel_tests_in_retry = self._run_test_subset(tests, tests_to_skip) >+ initial_results = initial_results.merge(temp_initial_results) if initial_results else temp_initial_results >+ 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 > > self._runner.stop_servers() >+ > end_time = time.time() > return self._end_test_run(start_time, end_time, initial_results, retry_results, enabled_pixel_tests_in_retry) > >@@ -298,9 +312,12 @@ class Manager(object): > return (initial_results, retry_results, enabled_pixel_tests_in_retry) > > def _end_test_run(self, start_time, end_time, initial_results, retry_results, enabled_pixel_tests_in_retry): >+ if initial_results is None: >+ _log.error('No results generated') >+ return test_run_results.RunDetails(exit_code=-1) >+ > # Some crash logs can take a long time to be written out so look > # for new logs after the test run finishes. >- > _log.debug("looking for new crash logs") > self._look_for_new_crash_logs(initial_results, start_time) > if retry_results: >Index: Tools/Scripts/webkitpy/port/base.py >=================================================================== >--- Tools/Scripts/webkitpy/port/base.py (revision 238900) >+++ Tools/Scripts/webkitpy/port/base.py (working copy) >@@ -81,6 +81,7 @@ class Port(object): > > DEFAULT_ARCHITECTURE = 'x86' > >+ DEFAULT_DEVICE_TYPE = None > CUSTOM_DEVICE_TYPES = [] > > @classmethod >@@ -176,10 +177,14 @@ class Port(object): > def should_retry_crashes(self): > return False > >- def default_child_processes(self): >+ def default_child_processes(self, **kwargs): > """Return the number of DumpRenderTree instances to use for this port.""" > return self._executive.cpu_count() > >+ def max_child_processes(self, **kwargs): >+ """Forbid the user from specifying more than this number of child processes""" >+ return float('inf') >+ > def worker_startup_delay_secs(self): > # FIXME: If we start workers up too quickly, DumpRenderTree appears > # to thrash on something and time out its first few tests. Until >Index: Tools/Scripts/webkitpy/port/device_port.py >=================================================================== >--- Tools/Scripts/webkitpy/port/device_port.py (revision 238900) >+++ Tools/Scripts/webkitpy/port/device_port.py (working copy) >@@ -23,12 +23,11 @@ > import logging > import traceback > >-from webkitpy.common.memoized import memoized > from webkitpy.layout_tests.models.test_configuration import TestConfiguration > from webkitpy.port.darwin import DarwinPort > from webkitpy.port.simulator_process import SimulatorProcess > from webkitpy.xcode.device_type import DeviceType >-from webkitpy.xcode.simulated_device import DeviceRequest >+from webkitpy.xcode.simulated_device import DeviceRequest, SimulatedDeviceManager > > > _log = logging.getLogger(__name__) >@@ -37,7 +36,6 @@ _log = logging.getLogger(__name__) > class DevicePort(DarwinPort): > > DEVICE_MANAGER = None >- DEFAULT_DEVICE_TYPE = None > NO_DEVICE_MANAGER = 'No device manager found for port' > > def __init__(self, *args, **kwargs): >@@ -59,7 +57,6 @@ class DevicePort(DarwinPort): > configurations.append(TestConfiguration(version=self.version_name(), architecture=architecture, build_type=build_type)) > return configurations > >- @memoized > def child_processes(self): > return int(self.get_option('child_processes')) > >@@ -106,17 +103,36 @@ class DevicePort(DarwinPort): > if not device.install_dylibs(self._build_path()): > raise RuntimeError('Failed to install dylibs at {} on device {}'.format(self._build_path(), device.udid)) > >- def setup_test_run(self, device_type=None): >- if not self.DEVICE_MANAGER: >- raise RuntimeError(self.NO_DEVICE_MANAGER) >- >+ def _device_type_with_version(self, device_type=None): > device_type = device_type if device_type else self.DEFAULT_DEVICE_TYPE >- device_type = DeviceType( >+ return DeviceType( > hardware_family=device_type.hardware_family, > hardware_type=device_type.hardware_type, > software_version=self.device_version(), > software_variant=device_type.software_variant, > ) >+ >+ 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) >+ 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), >+ ) >+ >+ 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) >+ >+ def setup_test_run(self, device_type=None): >+ if not self.DEVICE_MANAGER: >+ raise RuntimeError(self.NO_DEVICE_MANAGER) >+ >+ device_type = self._device_type_with_version(device_type) > _log.debug('\nCreating devices for {}'.format(device_type)) > > request = DeviceRequest( >@@ -125,7 +141,14 @@ class DevicePort(DarwinPort): > use_existing_simulator=False, > allow_incomplete_match=True, > ) >- self.DEVICE_MANAGER.initialize_devices([request] * self.child_processes(), self.host) >+ self.DEVICE_MANAGER.initialize_devices( >+ [request] * self.child_processes(), >+ self.host, >+ layout_test_dir=self.layout_tests_dir(), >+ pin=self.get_option('pin', None), >+ use_nfs=self.get_option('use_nfs', True), >+ reboot=self.get_option('reboot', False), >+ ) > > if not self.devices(): > raise RuntimeError('No devices are available for testing') >Index: Tools/Scripts/webkitpy/port/ios_device.py >=================================================================== >--- Tools/Scripts/webkitpy/port/ios_device.py (revision 238900) >+++ Tools/Scripts/webkitpy/port/ios_device.py (working copy) >@@ -44,12 +44,6 @@ class IOSDevicePort(IOSPort): > NO_ON_DEVICE_TESTING = 'On-device testing is not supported in this configuration' > NO_DEVICE_MANAGER = NO_ON_DEVICE_TESTING > >- @memoized >- def default_child_processes(self): >- if apple_additions(): >- return apple_additions().ios_device_default_child_processes(self) >- return 1 >- > def _driver_class(self): > if apple_additions(): > return apple_additions().ios_device_driver() >@@ -92,13 +86,15 @@ class IOSDevicePort(IOSPort): > if self.get_option('version'): > return Version.from_string(self.get_option('version')) > >- if not apple_additions(): >+ if not self.DEVICE_MANAGER: > raise RuntimeError(self.NO_ON_DEVICE_TESTING) > >- if not self.devices(): >+ if not self.DEVICE_MANAGER.available_devices(host=self.host): > raise RuntimeError('No devices are available') > version = None >- for device in self.devices(): >+ for device in self.DEVICE_MANAGER.available_devices(host=self.host): >+ if not device.platform.is_ios(): >+ continue > if not version: > version = device.platform.os_version > else: >Index: Tools/Scripts/webkitpy/port/ios_simulator.py >=================================================================== >--- Tools/Scripts/webkitpy/port/ios_simulator.py (revision 238900) >+++ Tools/Scripts/webkitpy/port/ios_simulator.py (working copy) >@@ -58,19 +58,6 @@ class IOSSimulatorPort(IOSPort): > return Version.from_string(self.get_option('version')) > return IOSSimulatorPort._version_from_name(self._name) if IOSSimulatorPort._version_from_name(self._name) else self.host.platform.xcode_sdk_version('iphonesimulator') > >- @memoized >- def default_child_processes(self): >- def booted_ios_devices_filter(device): >- if not device.platform_device.is_booted_or_booting(): >- return False >- return device.platform_device.device_type in DeviceType(software_variant='iOS', software_version=self.device_version()) >- >- if not self.get_option('dedicated_simulators', False): >- num_booted_sims = len(SimulatedDeviceManager.device_by_filter(booted_ios_devices_filter, host=self.host)) >- if num_booted_sims: >- return num_booted_sims >- return SimulatedDeviceManager.max_supported_simulators(self.host) >- > def clean_up_test_run(self): > super(IOSSimulatorPort, self).clean_up_test_run() > _log.debug("clean_up_test_run") >@@ -102,14 +89,6 @@ class IOSSimulatorPort(IOSPort): > def operating_system(self): > return 'ios-simulator' > >- def check_sys_deps(self): >- target_device_type = DeviceType(software_variant='iOS', software_version=self.device_version()) >- for device in SimulatedDeviceManager.available_devices(self.host): >- if device.platform_device.device_type in target_device_type: >- return super(IOSSimulatorPort, self).check_sys_deps() >- _log.error('No Simulated device matching "{}" defined in Xcode iOS SDK'.format(str(target_device_type))) >- return False >- > def reset_preferences(self): > _log.debug("reset_preferences") > SimulatedDeviceManager.tear_down(self.host) >Index: Tools/Scripts/webkitpy/port/mac.py >=================================================================== >--- Tools/Scripts/webkitpy/port/mac.py (revision 238900) >+++ Tools/Scripts/webkitpy/port/mac.py (working copy) >@@ -188,7 +188,7 @@ class MacPort(DarwinPort): > def is_mavericks(self): > return self._version == 'mavericks' > >- def default_child_processes(self): >+ def default_child_processes(self, **kwargs): > default_count = super(MacPort, self).default_child_processes() > > # FIXME: https://bugs.webkit.org/show_bug.cgi?id=95906 With too many WebProcess WK2 tests get stuck in resource contention. >Index: Tools/Scripts/webkitpy/port/test.py >=================================================================== >--- Tools/Scripts/webkitpy/port/test.py (revision 238900) >+++ Tools/Scripts/webkitpy/port/test.py (working copy) >@@ -418,7 +418,7 @@ class TestPort(Port): > } > return [self._webkit_baseline_path(d) for d in search_paths[self.name()]] > >- def default_child_processes(self): >+ def default_child_processes(self, **kwargs): > return 1 > > def worker_startup_delay_secs(self): >Index: Tools/Scripts/webkitpy/port/watch_device.py >=================================================================== >--- Tools/Scripts/webkitpy/port/watch_device.py (revision 238900) >+++ Tools/Scripts/webkitpy/port/watch_device.py (working copy) >@@ -42,12 +42,6 @@ class WatchDevicePort(WatchPort): > NO_ON_DEVICE_TESTING = 'On-device testing is not supported in this configuration' > NO_DEVICE_MANAGER = NO_ON_DEVICE_TESTING > >- @memoized >- def default_child_processes(self): >- if apple_additions(): >- return len(apple_additions().device_for_worker_number_map(self, software_variant='watchOS')) >- return 1 >- > def _driver_class(self): > if apple_additions(): > return apple_additions().device_driver() >@@ -90,13 +84,15 @@ class WatchDevicePort(WatchPort): > if self.get_option('version'): > return Version.from_string(self.get_option('version')) > >- if not apple_additions(): >+ if not self.DEVICE_MANAGER: > raise RuntimeError(self.NO_ON_DEVICE_TESTING) > >- if not apple_additions().device_for_worker_number_map(self, software_variant='watchOS'): >+ if not self.DEVICE_MANAGER.available_devices(host=self.host): > raise RuntimeError('No devices are available') > version = None >- for device in self.devices(): >+ for device in self.DEVICE_MANAGER.available_devices(host=self.host): >+ if not device.platform.is_watchos(): >+ continue > if not version: > version = device.platform.os_version > else: >Index: Tools/Scripts/webkitpy/port/watch_simulator.py >=================================================================== >--- Tools/Scripts/webkitpy/port/watch_simulator.py (revision 238900) >+++ Tools/Scripts/webkitpy/port/watch_simulator.py (working copy) >@@ -71,30 +71,9 @@ class WatchSimulatorPort(WatchPort): > new_environment[value] = inherited_env[value] > return new_environment > >- @memoized >- def default_child_processes(self): >- def filter_booted_watchos_devices(device): >- if not device.platform_device.is_booted_or_booting(): >- return False >- return device.platform_device.device_type in DeviceType(software_variant='watchOS', software_version=self.device_version()) >- >- if not self.get_option('dedicated_simulators', False): >- num_booted_sims = len(SimulatedDeviceManager.device_by_filter(filter_booted_watchos_devices, host=self.host)) >- if num_booted_sims: >- return num_booted_sims >- return SimulatedDeviceManager.max_supported_simulators(self.host) >- > def operating_system(self): > return 'watchos-simulator' > >- def check_sys_deps(self): >- target_device_type = DeviceType(software_variant='watchOS', software_version=self.device_version()) >- for device in SimulatedDeviceManager.available_devices(self.host): >- if device.platform_device.device_type in target_device_type: >- return super(WatchSimulatorPort, self).check_sys_deps() >- _log.error('No simulated device matching "{}" found in watchOS SDK'.format(str(target_device_type))) >- return False >- > def setup_environ_for_server(self, server_name=None): > _log.debug('Setting up environment for server on {}'.format(self.operating_system())) > env = super(WatchSimulatorPort, self).setup_environ_for_server(server_name) >Index: Tools/Scripts/webkitpy/xcode/simulated_device.py >=================================================================== >--- Tools/Scripts/webkitpy/xcode/simulated_device.py (revision 238900) >+++ Tools/Scripts/webkitpy/xcode/simulated_device.py (working copy) >@@ -325,6 +325,20 @@ class SimulatedDeviceManager(object): > SimulatedDeviceManager.INITIALIZED_DEVICES.append(device) > > @staticmethod >+ def device_count_for_type(device_type, host=SystemHost(), use_booted_simulator=True, **kwargs): >+ if not host.platform.is_mac(): >+ return 0 >+ >+ if SimulatedDeviceManager.device_by_filter(lambda device: device.platform_device.is_booted_or_booting(), host=host) and use_booted_simulator: >+ filter = lambda device: device.platform_device.is_booted_or_booting() and device.platform_device.device_type in device_type >+ return len(SimulatedDeviceManager.device_by_filter(filter, host=host)) >+ >+ for name in SimulatedDeviceManager._device_identifier_to_name.itervalues(): >+ if DeviceType.from_string(name) in device_type: >+ return SimulatedDeviceManager.max_supported_simulators(host) >+ return 0 >+ >+ @staticmethod > def initialize_devices(requests, host=SystemHost(), name_base='Managed', simulator_ui=True, timeout=SIMULATOR_BOOT_TIMEOUT, **kwargs): > if SimulatedDeviceManager.INITIALIZED_DEVICES is not None: > return SimulatedDeviceManager.INITIALIZED_DEVICES
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 192161
:
356439
|
356514
|
356550
|
356587
|
356608
| 356618