def __init__(self, host, port_name, **kwargs): _import_android_packages_if_necessary() super(AndroidPort, self).__init__(host, port_name, **kwargs) self._operating_system = 'android' self._version = 'kitkat' self._host_port = factory.PortFactory(host).get(**kwargs) self.server_process_constructor = self._android_server_process_constructor if not self.get_option('disable_breakpad'): self._dump_reader = DumpReaderAndroid(host, self._build_path()) if self.driver_name() != self.CONTENT_SHELL_NAME: raise AssertionError( 'Layout tests on Android only support content_shell as the driver.' ) self._driver_details = ContentShellDriverDetails() # Initialize the AndroidDevices class which tracks available devices. default_devices = None if hasattr(self._options, 'adb_devices') and len( self._options.adb_devices): default_devices = self._options.adb_devices self._debug_logging = self.get_option('android_logging') self._devices = AndroidDevices(default_devices, self._debug_logging) devil_chromium.Initialize(output_directory=self._build_path(), adb_path=self._path_from_chromium_base( 'third_party', 'android_tools', 'sdk', 'platform-tools', 'adb')) devil_env.config.InitializeLogging( logging.DEBUG if self._debug_logging and self.get_option('debug_rwt_logging') else logging.WARNING) prepared_devices = self.get_option('prepared_devices', []) for serial in prepared_devices: self._devices.set_device_prepared(serial)
def __init__(self, host, port_name, **kwargs): super(AndroidPort, self).__init__(host, port_name, **kwargs) self._operating_system = 'android' self._version = 'icecreamsandwich' self._host_port = factory.PortFactory(host).get(**kwargs) self._server_process_constructor = self._android_server_process_constructor if not self.get_option('disable_breakpad'): self._dump_reader = DumpReaderAndroid(host, self._build_path()) if self.driver_name() != self.CONTENT_SHELL_NAME: raise AssertionError('Layout tests on Android only support content_shell as the driver.') self._driver_details = ContentShellDriverDetails() # Initialize the AndroidDevices class which tracks available devices. default_devices = None if hasattr(self._options, 'adb_devices') and len(self._options.adb_devices): default_devices = self._options.adb_devices self._debug_logging = self.get_option('android_logging') self._devices = AndroidDevices(default_devices, self._debug_logging) devil_chromium.Initialize( output_directory=self._build_path(), adb_path=self.path_from_chromium_base( 'third_party', 'android_tools', 'sdk', 'platform-tools', 'adb')) devil_env.config.InitializeLogging( logging.DEBUG if self._debug_logging and self.get_option('debug_rwt_logging') else logging.WARNING) prepared_devices = self.get_option('prepared_devices', []) for serial in prepared_devices: self._devices.set_device_prepared(serial)
class AndroidPort(base.Port): port_name = "android" # Avoid initializing the adb path [worker count]+1 times by storing it as a static member. _adb_path = None SUPPORTED_VERSIONS = "android" FALLBACK_PATHS = {"icecreamsandwich": ["android"] + linux.LinuxPort.latest_platform_fallback_path()} # Android has aac and mp3 codecs built in. PORT_HAS_AUDIO_CODECS_BUILT_IN = True BUILD_REQUIREMENTS_URL = "https://www.chromium.org/developers/how-tos/android-build-instructions" def __init__(self, host, port_name, **kwargs): super(AndroidPort, self).__init__(host, port_name, **kwargs) self._operating_system = "android" self._version = "icecreamsandwich" self._host_port = factory.PortFactory(host).get(**kwargs) self._server_process_constructor = self._android_server_process_constructor if not self.get_option("disable_breakpad"): self._dump_reader = DumpReaderAndroid(host, self._build_path()) if self.driver_name() != self.CONTENT_SHELL_NAME: raise AssertionError("Layout tests on Android only support content_shell as the driver.") self._driver_details = ContentShellDriverDetails() # Initialize the AndroidDevices class which tracks available devices. default_devices = None if hasattr(self._options, "adb_devices") and len(self._options.adb_devices): default_devices = self._options.adb_devices self._debug_logging = self.get_option("android_logging") self._devices = AndroidDevices(default_devices, self._debug_logging) devil_chromium.Initialize( output_directory=self._build_path(), adb_path=self.path_from_chromium_base("third_party", "android_tools", "sdk", "platform-tools", "adb"), ) devil_env.config.InitializeLogging( logging.DEBUG if self._debug_logging and self.get_option("debug_rwt_logging") else logging.WARNING ) prepared_devices = self.get_option("prepared_devices", []) for serial in prepared_devices: self._devices.set_device_prepared(serial) def default_smoke_test_only(self): return True def additional_driver_flag(self): return super(AndroidPort, self).additional_driver_flag() + self._driver_details.additional_command_line_flags( use_breakpad=not self.get_option("disable_breakpad") ) def default_timeout_ms(self): # Android platform has less computing power than desktop platforms. # Using 10 seconds allows us to pass most slow tests which are not # marked as slow tests on desktop platforms. return 10 * 1000 def driver_stop_timeout(self): # The driver doesn't respond to closing stdin, so we might as well stop the driver immediately. return 0.0 def default_child_processes(self): usable_devices = self._devices.usable_devices(self._executive) if not usable_devices: raise test_run_results.TestRunException( test_run_results.NO_DEVICES_EXIT_STATUS, "Unable to find any attached Android devices." ) return len(usable_devices) def max_drivers_per_process(self): # Android falls over when we try to run multiple content_shells per worker. # See https://codereview.chromium.org/1158323009/ return 1 def check_wdiff(self, more_logging=True): return self._host_port.check_wdiff(more_logging) def check_build(self, needs_http, printer): exit_status = super(AndroidPort, self).check_build(needs_http, printer) if exit_status: return exit_status return self._check_devices(printer) def _check_devices(self, printer): # Printer objects aren't threadsafe, so we need to protect calls to them. lock = threading.Lock() pool = None # Push the executables and other files to the devices; doing this now # means we can do this in parallel in the manager process and not mix # this in with starting and stopping workers. def setup_device(worker_number): d = self.create_driver(worker_number) serial = d._device.serial # pylint: disable=protected-access def log_safely(msg, throttled=True): if throttled: callback = printer.write_throttled_update else: callback = printer.write_update with lock: callback("[%s] %s" % (serial, msg)) log_safely("preparing device", throttled=False) try: d._setup_test(log_safely) log_safely("device prepared", throttled=False) except (ScriptError, driver.DeviceFailure) as e: with lock: _log.warning("[%s] failed to prepare_device: %s", serial, str(e)) except KeyboardInterrupt: if pool: pool.terminate() # FIXME: It would be nice if we knew how many workers we needed. num_workers = self.default_child_processes() num_child_processes = int(self.get_option("child_processes")) if num_child_processes: num_workers = min(num_workers, num_child_processes) if num_workers > 1: pool = ThreadPool(num_workers) try: pool.map(setup_device, range(num_workers)) except KeyboardInterrupt: pool.terminate() raise else: setup_device(0) if not self._devices.prepared_devices(): _log.error("Could not prepare any devices for testing.") return test_run_results.NO_DEVICES_EXIT_STATUS return test_run_results.OK_EXIT_STATUS def setup_test_run(self): super(AndroidPort, self).setup_test_run() # By setting this on the options object, we can propagate the list # of prepared devices to the workers (it is read in __init__()). if self._devices._prepared_devices: self._options.prepared_devices = self._devices.prepared_devices() else: # We were called with --no-build, so assume the devices are up to date. self._options.prepared_devices = [d.get_serial() for d in self._devices.usable_devices(self.host.executive)] def num_workers(self, requested_num_workers): return min(len(self._options.prepared_devices), requested_num_workers) def check_sys_deps(self, needs_http): for (font_dirs, font_file, package) in HOST_FONT_FILES: exists = False for font_dir in font_dirs: font_path = font_dir + font_file if self._check_file_exists(font_path, "", more_logging=False): exists = True break if not exists: _log.error( "You are missing %s under %s. Try installing %s. See build instructions.", font_file, font_dirs, package, ) return test_run_results.SYS_DEPS_EXIT_STATUS return test_run_results.OK_EXIT_STATUS def requires_http_server(self): """Chromium Android runs tests on devices, and uses the HTTP server to serve the actual layout tests to the test driver. """ return True def start_http_server(self, additional_dirs, number_of_drivers): additional_dirs[PERF_TEST_PATH_PREFIX] = self.perf_tests_dir() additional_dirs[LAYOUT_TEST_PATH_PREFIX] = self.layout_tests_dir() super(AndroidPort, self).start_http_server(additional_dirs, number_of_drivers) def create_driver(self, worker_number, no_timeout=False): return ChromiumAndroidDriver( self, worker_number, pixel_tests=self.get_option("pixel_tests"), driver_details=self._driver_details, android_devices=self._devices, # Force no timeout to avoid test driver timeouts before NRWT. no_timeout=True, ) def driver_cmd_line(self): # Override to return the actual test driver's command line. return self.create_driver(0)._android_driver_cmd_line(self.get_option("pixel_tests"), []) def clobber_old_port_specific_results(self): if not self.get_option("disable_breakpad"): self._dump_reader.clobber_old_results() # Overridden protected methods. def _build_path(self, *comps): return self._host_port._build_path(*comps) def _build_path_with_target(self, target, *comps): return self._host_port._build_path_with_target(target, *comps) def path_to_apache(self): return self._host_port.path_to_apache() def path_to_apache_config_file(self): return self._host_port.path_to_apache_config_file() def _path_to_driver(self, target=None): return self._build_path_with_target(target, self._driver_details.apk_name()) def _path_to_image_diff(self): return self._host_port._path_to_image_diff() def _path_to_wdiff(self): return self._host_port._path_to_wdiff() def _shut_down_http_server(self, pid): return self._host_port._shut_down_http_server(pid) def _driver_class(self): return ChromiumAndroidDriver # Local private methods. @staticmethod def _android_server_process_constructor(port, server_name, cmd_line, env=None, more_logging=False): # We need universal_newlines=True, because 'adb shell' for some unknown reason # does newline conversion of unix-style LF into win-style CRLF (and we need # to convert that back). This can cause headaches elsewhere because # server_process' stdout and stderr are now unicode file-like objects, # not binary file-like objects like all of the other ports are. # FIXME: crbug.com/496983. return server_process.ServerProcess( port, server_name, cmd_line, env, universal_newlines=True, treat_no_data_as_crash=True, more_logging=more_logging, )
class AndroidPort(base.Port): port_name = 'android' # Avoid initializing the adb path [worker count]+1 times by storing it as a static member. _adb_path = None SUPPORTED_VERSIONS = ('android') FALLBACK_PATHS = {'icecreamsandwich': ['android'] + linux.LinuxPort.latest_platform_fallback_path()} # Android has aac and mp3 codecs built in. PORT_HAS_AUDIO_CODECS_BUILT_IN = True BUILD_REQUIREMENTS_URL = 'https://www.chromium.org/developers/how-tos/android-build-instructions' def __init__(self, host, port_name, **kwargs): super(AndroidPort, self).__init__(host, port_name, **kwargs) self._operating_system = 'android' self._version = 'icecreamsandwich' self._host_port = factory.PortFactory(host).get(**kwargs) self._server_process_constructor = self._android_server_process_constructor if not self.get_option('disable_breakpad'): self._dump_reader = DumpReaderAndroid(host, self._build_path()) if self.driver_name() != self.CONTENT_SHELL_NAME: raise AssertionError('Layout tests on Android only support content_shell as the driver.') self._driver_details = ContentShellDriverDetails() # Initialize the AndroidDevices class which tracks available devices. default_devices = None if hasattr(self._options, 'adb_devices') and len(self._options.adb_devices): default_devices = self._options.adb_devices self._debug_logging = self.get_option('android_logging') self._devices = AndroidDevices(default_devices, self._debug_logging) devil_chromium.Initialize( output_directory=self._build_path(), adb_path=self.path_from_chromium_base( 'third_party', 'android_tools', 'sdk', 'platform-tools', 'adb')) devil_env.config.InitializeLogging( logging.DEBUG if self._debug_logging and self.get_option('debug_rwt_logging') else logging.WARNING) prepared_devices = self.get_option('prepared_devices', []) for serial in prepared_devices: self._devices.set_device_prepared(serial) def default_smoke_test_only(self): return True def additional_driver_flag(self): return super(AndroidPort, self).additional_driver_flag() + \ self._driver_details.additional_command_line_flags(use_breakpad=not self.get_option('disable_breakpad')) def default_timeout_ms(self): # Android platform has less computing power than desktop platforms. # Using 10 seconds allows us to pass most slow tests which are not # marked as slow tests on desktop platforms. return 10 * 1000 def driver_stop_timeout(self): # The driver doesn't respond to closing stdin, so we might as well stop the driver immediately. return 0.0 def default_child_processes(self): usable_devices = self._devices.usable_devices(self._executive) if not usable_devices: raise test_run_results.TestRunException(test_run_results.NO_DEVICES_EXIT_STATUS, "Unable to find any attached Android devices.") return len(usable_devices) def max_drivers_per_process(self): # Android falls over when we try to run multiple content_shells per worker. # See https://codereview.chromium.org/1158323009/ return 1 def check_wdiff(self, more_logging=True): return self._host_port.check_wdiff(more_logging) def check_build(self, needs_http, printer): exit_status = super(AndroidPort, self).check_build(needs_http, printer) if exit_status: return exit_status return self._check_devices(printer) def _check_devices(self, printer): # Printer objects aren't threadsafe, so we need to protect calls to them. lock = threading.Lock() pool = None # Push the executables and other files to the devices; doing this now # means we can do this in parallel in the manager process and not mix # this in with starting and stopping workers. def setup_device(worker_number): d = self.create_driver(worker_number) serial = d._device.serial # pylint: disable=protected-access def log_safely(msg, throttled=True): if throttled: callback = printer.write_throttled_update else: callback = printer.write_update with lock: callback("[%s] %s" % (serial, msg)) log_safely("preparing device", throttled=False) try: d._setup_test(log_safely) log_safely("device prepared", throttled=False) except (ScriptError, driver.DeviceFailure) as e: with lock: _log.warning("[%s] failed to prepare_device: %s", serial, str(e)) except KeyboardInterrupt: if pool: pool.terminate() # FIXME: It would be nice if we knew how many workers we needed. num_workers = self.default_child_processes() num_child_processes = int(self.get_option('child_processes')) if num_child_processes: num_workers = min(num_workers, num_child_processes) if num_workers > 1: pool = ThreadPool(num_workers) try: pool.map(setup_device, range(num_workers)) except KeyboardInterrupt: pool.terminate() raise else: setup_device(0) if not self._devices.prepared_devices(): _log.error('Could not prepare any devices for testing.') return test_run_results.NO_DEVICES_EXIT_STATUS return test_run_results.OK_EXIT_STATUS def setup_test_run(self): super(AndroidPort, self).setup_test_run() # By setting this on the options object, we can propagate the list # of prepared devices to the workers (it is read in __init__()). if self._devices._prepared_devices: self._options.prepared_devices = self._devices.prepared_devices() else: # We were called with --no-build, so assume the devices are up to date. self._options.prepared_devices = [d.get_serial() for d in self._devices.usable_devices(self.host.executive)] def num_workers(self, requested_num_workers): return min(len(self._options.prepared_devices), requested_num_workers) def check_sys_deps(self, needs_http): for (font_dirs, font_file, package) in HOST_FONT_FILES: exists = False for font_dir in font_dirs: font_path = font_dir + font_file if self._check_file_exists(font_path, '', more_logging=False): exists = True break if not exists: _log.error('You are missing %s under %s. Try installing %s. See build instructions.', font_file, font_dirs, package) return test_run_results.SYS_DEPS_EXIT_STATUS return test_run_results.OK_EXIT_STATUS def requires_http_server(self): """Chromium Android runs tests on devices, and uses the HTTP server to serve the actual layout tests to the test driver. """ return True def start_http_server(self, additional_dirs, number_of_drivers): additional_dirs[PERF_TEST_PATH_PREFIX] = self.perf_tests_dir() additional_dirs[LAYOUT_TEST_PATH_PREFIX] = self.layout_tests_dir() super(AndroidPort, self).start_http_server(additional_dirs, number_of_drivers) def create_driver(self, worker_number, no_timeout=False): return ChromiumAndroidDriver(self, worker_number, pixel_tests=self.get_option('pixel_tests'), driver_details=self._driver_details, android_devices=self._devices, # Force no timeout to avoid test driver timeouts before NRWT. no_timeout=True) def driver_cmd_line(self): # Override to return the actual test driver's command line. return self.create_driver(0)._android_driver_cmd_line(self.get_option('pixel_tests'), []) def clobber_old_port_specific_results(self): if not self.get_option('disable_breakpad'): self._dump_reader.clobber_old_results() # Overridden protected methods. def _build_path(self, *comps): return self._host_port._build_path(*comps) def _build_path_with_target(self, target, *comps): return self._host_port._build_path_with_target(target, *comps) def path_to_apache(self): return self._host_port.path_to_apache() def path_to_apache_config_file(self): return self._host_port.path_to_apache_config_file() def _path_to_driver(self, target=None): return self._build_path_with_target(target, self._driver_details.apk_name()) def _path_to_image_diff(self): return self._host_port._path_to_image_diff() def _path_to_wdiff(self): return self._host_port._path_to_wdiff() def _shut_down_http_server(self, pid): return self._host_port._shut_down_http_server(pid) def _driver_class(self): return ChromiumAndroidDriver # Local private methods. @staticmethod def _android_server_process_constructor(port, server_name, cmd_line, env=None, more_logging=False): # We need universal_newlines=True, because 'adb shell' for some unknown reason # does newline conversion of unix-style LF into win-style CRLF (and we need # to convert that back). This can cause headaches elsewhere because # server_process' stdout and stderr are now unicode file-like objects, # not binary file-like objects like all of the other ports are. # FIXME: crbug.com/496983. return server_process.ServerProcess(port, server_name, cmd_line, env, universal_newlines=True, treat_no_data_as_crash=True, more_logging=more_logging)
class AndroidPort(base.Port): port_name = 'android' # Avoid initializing the adb path [worker count]+1 times by storing it as a static member. _adb_path = None SUPPORTED_VERSIONS = ('android') FALLBACK_PATHS = {'kitkat': ['android'] + linux.LinuxPort.latest_platform_fallback_path()} BUILD_REQUIREMENTS_URL = 'https://www.chromium.org/developers/how-tos/android-build-instructions' def __init__(self, host, port_name, **kwargs): _import_android_packages_if_necessary() super(AndroidPort, self).__init__(host, port_name, **kwargs) self._operating_system = 'android' self._version = 'kitkat' self._host_port = factory.PortFactory(host).get(**kwargs) self.server_process_constructor = self._android_server_process_constructor if not self.get_option('disable_breakpad'): self._dump_reader = DumpReaderAndroid(host, self._build_path()) if self.driver_name() != self.CONTENT_SHELL_NAME: raise AssertionError('Layout tests on Android only support content_shell as the driver.') self._driver_details = ContentShellDriverDetails() # Initialize the AndroidDevices class which tracks available devices. default_devices = None if hasattr(self._options, 'adb_devices') and len(self._options.adb_devices): default_devices = self._options.adb_devices self._debug_logging = self.get_option('android_logging') self._devices = AndroidDevices(default_devices, self._debug_logging) devil_chromium.Initialize( output_directory=self._build_path(), adb_path=self._path_from_chromium_base( 'third_party', 'android_tools', 'sdk', 'platform-tools', 'adb')) devil_env.config.InitializeLogging( logging.DEBUG if self._debug_logging and self.get_option('debug_rwt_logging') else logging.WARNING) prepared_devices = self.get_option('prepared_devices', []) for serial in prepared_devices: self._devices.set_device_prepared(serial) def default_smoke_test_only(self): return True def additional_driver_flags(self): return super(AndroidPort, self).additional_driver_flags() + \ self._driver_details.additional_command_line_flags(use_breakpad=not self.get_option('disable_breakpad')) def default_timeout_ms(self): # Android platform has less computing power than desktop platforms. # Using 10 seconds allows us to pass most slow tests which are not # marked as slow tests on desktop platforms. return 10 * 1000 def driver_stop_timeout(self): # The driver doesn't respond to closing stdin, so we might as well stop the driver immediately. return 0.0 def default_child_processes(self): usable_devices = self._devices.usable_devices(self._executive) if not usable_devices: raise test_run_results.TestRunException(exit_codes.NO_DEVICES_EXIT_STATUS, 'Unable to find any attached Android devices.') return len(usable_devices) def max_drivers_per_process(self): # Android falls over when we try to run multiple content_shells per worker. # See https://codereview.chromium.org/1158323009/ return 1 def check_build(self, needs_http, printer): exit_status = super(AndroidPort, self).check_build(needs_http, printer) if exit_status: return exit_status return self._check_devices(printer) def _check_devices(self, printer): # Push the executables and other files to the devices; doing this now # means we can do this in parallel in the manager process and not mix # this in with starting and stopping workers. lock = threading.Lock() def log_safely(msg, throttled=True): if throttled: callback = printer.write_throttled_update else: callback = printer.write_update with lock: callback('%s' % msg) def _setup_device_impl(device): log_safely('preparing device', throttled=False) if self._devices.is_device_prepared(device.serial): return device.EnableRoot() perf_control.PerfControl(device).SetPerfProfilingMode() # Required by webkit_support::GetWebKitRootDirFilePath(). # Other directories will be created automatically by adb push. device.RunShellCommand( ['mkdir', '-p', DEVICE_SOURCE_ROOT_DIR + 'chrome'], check_return=True) # Allow the test driver to get full read and write access to the directory on the device, # as well as for the FIFOs. We'll need a world writable directory. device.RunShellCommand( ['mkdir', '-p', self._driver_details.device_directory()], check_return=True) # Make sure that the disk cache on the device resets to a clean state. device.RunShellCommand( ['rm', '-rf', self._driver_details.device_cache_directory()], check_return=True) device.EnableRoot() perf_control.PerfControl(device).SetPerfProfilingMode() # Required by webkit_support::GetWebKitRootDirFilePath(). # Other directories will be created automatically by adb push. device.RunShellCommand( ['mkdir', '-p', DEVICE_SOURCE_ROOT_DIR + 'chrome'], check_return=True) # Allow the test driver to get full read and write access to the directory on the device, # as well as for the FIFOs. We'll need a world writable directory. device.RunShellCommand( ['mkdir', '-p', self._driver_details.device_directory()], check_return=True) # Make sure that the disk cache on the device resets to a clean state. device.RunShellCommand( ['rm', '-rf', self._driver_details.device_cache_directory()], check_return=True) device_path = lambda *p: posixpath.join( self._driver_details.device_directory(), *p) device.Install(self._path_to_driver()) # Build up a list of what we want to push, including: host_device_tuples = [] # - the custom font files # TODO(sergeyu): Rename these files, they can be used on platforms # other than Android. host_device_tuples.append( (self._build_path('android_main_fonts.xml'), device_path('android_main_fonts.xml'))) host_device_tuples.append( (self._build_path('android_fallback_fonts.xml'), device_path('android_fallback_fonts.xml'))) for font_file in self._get_font_files(): host_device_tuples.append( (font_file, device_path('fonts', os.path.basename(font_file)))) # - the test resources host_device_tuples.extend( (self.host.filesystem.join(self.layout_tests_dir(), resource), posixpath.join(DEVICE_LAYOUT_TESTS_DIR, resource)) for resource in TEST_RESOURCES_TO_PUSH) # ... and then push them to the device. device.PushChangedFiles(host_device_tuples) device.RunShellCommand( ['mkdir', '-p', self._driver_details.device_fifo_directory()], check_return=True) device.RunShellCommand( ['chmod', '-R', '777', self._driver_details.device_directory()], check_return=True) device.RunShellCommand( ['chmod', '-R', '777', self._driver_details.device_fifo_directory()], check_return=True) # Mark this device as having been set up. self._devices.set_device_prepared(device.serial) log_safely('device prepared', throttled=False) def setup_device(device): try: _setup_device_impl(device) except (ScriptError, driver.DeviceFailure, device_errors.CommandFailedError, device_errors.CommandTimeoutError, device_errors.DeviceUnreachableError) as error: with lock: _log.warning('[%s] failed to prepare_device: %s', serial, error) devices = self._devices.usable_devices(self.host.executive) device_utils.DeviceUtils.parallel(devices).pMap(setup_device) if not self._devices.prepared_devices(): _log.error('Could not prepare any devices for testing.') return exit_codes.NO_DEVICES_EXIT_STATUS return exit_codes.OK_EXIT_STATUS def setup_test_run(self): super(AndroidPort, self).setup_test_run() # By setting this on the options object, we can propagate the list # of prepared devices to the workers (it is read in __init__()). if self._devices._prepared_devices: self._options.prepared_devices = self._devices.prepared_devices() else: # We were called with --no-build, so assume the devices are up to date. self._options.prepared_devices = [d.get_serial() for d in self._devices.usable_devices(self.host.executive)] def num_workers(self, requested_num_workers): return min(len(self._options.prepared_devices), requested_num_workers) def check_sys_deps(self, needs_http): # _get_font_files() will throw if any of the required fonts is missing. self._get_font_files() return exit_codes.OK_EXIT_STATUS def requires_http_server(self): """Chromium Android runs tests on devices, and uses the HTTP server to serve the actual layout tests to the test driver. """ return True def start_http_server(self, additional_dirs, number_of_drivers): additional_dirs[PERF_TEST_PATH_PREFIX] = self._perf_tests_dir() additional_dirs[LAYOUT_TEST_PATH_PREFIX] = self.layout_tests_dir() super(AndroidPort, self).start_http_server(additional_dirs, number_of_drivers) def create_driver(self, worker_number, no_timeout=False): return ChromiumAndroidDriver(self, worker_number, pixel_tests=self.get_option('pixel_tests'), driver_details=self._driver_details, android_devices=self._devices, # Force no timeout to avoid test driver timeouts before NRWT. no_timeout=True) def driver_cmd_line(self): # Override to return the actual test driver's command line. return self.create_driver(0)._android_driver_cmd_line(self.get_option('pixel_tests'), []) def clobber_old_port_specific_results(self): if not self.get_option('disable_breakpad'): self._dump_reader.clobber_old_results() # Overridden protected methods. def _build_path(self, *comps): return self._host_port._build_path(*comps) def _build_path_with_target(self, target, *comps): return self._host_port._build_path_with_target(target, *comps) def path_to_apache(self): return self._host_port.path_to_apache() def path_to_apache_config_file(self): return self._host_port.path_to_apache_config_file() def _path_to_driver(self, target=None): return self._build_path_with_target(target, self._driver_details.apk_name()) def _path_to_image_diff(self): return self._host_port._path_to_image_diff() def _shut_down_http_server(self, pid): return self._host_port._shut_down_http_server(pid) def _driver_class(self): return ChromiumAndroidDriver # Local private methods. @staticmethod def _android_server_process_constructor(port, server_name, cmd_line, env=None, more_logging=False): return server_process.ServerProcess(port, server_name, cmd_line, env, treat_no_data_as_crash=True, more_logging=more_logging)