Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (C) 2012 Google Inc. All rights reserved. | 1 # Copyright (C) 2012 Google Inc. All rights reserved. |
| 2 # | 2 # |
| 3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
| 5 # met: | 5 # met: |
| 6 # | 6 # |
| 7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
| 11 # in the documentation and/or other materials provided with the | 11 # in the documentation and/or other materials provided with the |
| 12 # distribution. | 12 # distribution. |
| 13 # * Neither the name of Google Inc. nor the names of its | 13 # * Neither the name of Google Inc. nor the names of its |
| 14 # contributors may be used to endorse or promote products derived from | 14 # contributors may be used to endorse or promote products derived from |
| 15 # this software without specific prior written permission. | 15 # this software without specific prior written permission. |
| 16 # | 16 # |
| 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 28 |
| 29 import itertools | |
| 29 import logging | 30 import logging |
| 30 import os | 31 import os |
| 31 import re | 32 import re |
| 32 import sys | 33 import sys |
| 33 import threading | 34 import threading |
| 34 import time | 35 import time |
| 35 | 36 |
| 36 from multiprocessing.pool import ThreadPool | 37 from multiprocessing.pool import ThreadPool |
| 37 | 38 |
| 38 from webkitpy.common.system.executive import ScriptError | 39 from webkitpy.common.system.executive import ScriptError |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 260 | 261 |
| 261 BUILD_REQUIREMENTS_URL = 'https://www.chromium.org/developers/how-tos/androi d-build-instructions' | 262 BUILD_REQUIREMENTS_URL = 'https://www.chromium.org/developers/how-tos/androi d-build-instructions' |
| 262 | 263 |
| 263 def __init__(self, host, port_name, **kwargs): | 264 def __init__(self, host, port_name, **kwargs): |
| 264 super(AndroidPort, self).__init__(host, port_name, **kwargs) | 265 super(AndroidPort, self).__init__(host, port_name, **kwargs) |
| 265 | 266 |
| 266 self._operating_system = 'android' | 267 self._operating_system = 'android' |
| 267 self._version = 'icecreamsandwich' | 268 self._version = 'icecreamsandwich' |
| 268 | 269 |
| 269 self._host_port = factory.PortFactory(host).get(**kwargs) | 270 self._host_port = factory.PortFactory(host).get(**kwargs) |
| 270 self._server_process_constructor = self._android_server_process_construc tor | 271 self.server_process_constructor = self._android_server_process_construct or |
| 271 | 272 |
| 272 if not self.get_option('disable_breakpad'): | 273 if not self.get_option('disable_breakpad'): |
| 273 self._dump_reader = DumpReaderAndroid(host, self._build_path()) | 274 self._dump_reader = DumpReaderAndroid(host, self._build_path()) |
| 274 | 275 |
| 275 if self.driver_name() != self.CONTENT_SHELL_NAME: | 276 if self.driver_name() != self.CONTENT_SHELL_NAME: |
| 276 raise AssertionError('Layout tests on Android only support content_s hell as the driver.') | 277 raise AssertionError('Layout tests on Android only support content_s hell as the driver.') |
| 277 | 278 |
| 278 self._driver_details = ContentShellDriverDetails() | 279 self._driver_details = ContentShellDriverDetails() |
| 279 | 280 |
| 280 # Initialize the AndroidDevices class which tracks available devices. | 281 # Initialize the AndroidDevices class which tracks available devices. |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 602 | 603 |
| 603 perfhost_display_patch = perfhost_path if perfhost_path else 'perfhost_l inux' | 604 perfhost_display_patch = perfhost_path if perfhost_path else 'perfhost_l inux' |
| 604 _log.debug("To view the full profile, run:") | 605 _log.debug("To view the full profile, run:") |
| 605 _log.debug(' '.join([perfhost_display_patch] + perfhost_report_command)) | 606 _log.debug(' '.join([perfhost_display_patch] + perfhost_report_command)) |
| 606 | 607 |
| 607 | 608 |
| 608 class ChromiumAndroidDriver(driver.Driver): | 609 class ChromiumAndroidDriver(driver.Driver): |
| 609 | 610 |
| 610 def __init__(self, port, worker_number, pixel_tests, driver_details, android _devices, no_timeout=False): | 611 def __init__(self, port, worker_number, pixel_tests, driver_details, android _devices, no_timeout=False): |
| 611 super(ChromiumAndroidDriver, self).__init__(port, worker_number, pixel_t ests, no_timeout) | 612 super(ChromiumAndroidDriver, self).__init__(port, worker_number, pixel_t ests, no_timeout) |
| 612 self._in_fifo_path = driver_details.device_fifo_directory() + 'stdin.fif o' | 613 self._write_stdin_process = None |
| 613 self._out_fifo_path = driver_details.device_fifo_directory() + 'test.fif o' | |
| 614 self._err_fifo_path = driver_details.device_fifo_directory() + 'stderr.f ifo' | |
| 615 self._read_stdout_process = None | 614 self._read_stdout_process = None |
| 616 self._read_stderr_process = None | 615 self._read_stderr_process = None |
| 617 self._original_kptr_restrict = None | 616 self._original_kptr_restrict = None |
| 618 | 617 |
| 619 self._android_devices = android_devices | 618 self._android_devices = android_devices |
| 620 self._device = android_devices.get_device(port._executive, worker_number ) # pylint: disable=protected-access | 619 self._device = android_devices.get_device(port._executive, worker_number ) # pylint: disable=protected-access |
| 621 self._driver_details = driver_details | 620 self._driver_details = driver_details |
| 622 self._debug_logging = self._port._debug_logging | 621 self._debug_logging = self._port._debug_logging |
| 623 self._created_cmd_line = False | 622 self._created_cmd_line = False |
| 624 self._device_failed = False | 623 self._device_failed = False |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 819 return '' | 818 return '' |
| 820 | 819 |
| 821 # Use Android tool vendor/google/tools/stack to convert the raw | 820 # Use Android tool vendor/google/tools/stack to convert the raw |
| 822 # stack trace into a human readable format, if needed. | 821 # stack trace into a human readable format, if needed. |
| 823 # It takes a long time, so don't do it here. | 822 # It takes a long time, so don't do it here. |
| 824 tombstone_contents = self._device.ReadFile( | 823 tombstone_contents = self._device.ReadFile( |
| 825 '/data/tombstones/%s' % last_tombstone[6]) | 824 '/data/tombstones/%s' % last_tombstone[6]) |
| 826 return '%s\n%s' % (' '.join(last_tombstone), tombstone_contents) | 825 return '%s\n%s' % (' '.join(last_tombstone), tombstone_contents) |
| 827 | 826 |
| 828 def _get_logcat(self): | 827 def _get_logcat(self): |
| 829 return list(self._device.adb.Logcat(dump=True, logcat_format='threadtime ')) | 828 return '\n'.join(self._device.adb.Logcat(dump=True, logcat_format='threa dtime')) |
| 830 | 829 |
| 831 def _setup_performance(self): | 830 def _setup_performance(self): |
| 832 # Disable CPU scaling and drop ram cache to reduce noise in tests | 831 # Disable CPU scaling and drop ram cache to reduce noise in tests |
| 833 perf_control.PerfControl(self._device).SetPerfProfilingMode() | 832 perf_control.PerfControl(self._device).SetPerfProfilingMode() |
| 834 | 833 |
| 835 def _teardown_performance(self): | 834 def _teardown_performance(self): |
| 836 perf_control.PerfControl(self._device).SetDefaultPerfMode() | 835 perf_control.PerfControl(self._device).SetDefaultPerfMode() |
| 837 | 836 |
| 838 def _get_crash_log(self, stdout, stderr, newer_than): | 837 def _get_crash_log(self, stdout, stderr, newer_than): |
| 839 if not stdout: | 838 if not stdout: |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 870 return driver.Driver.cmd_line(self, pixel_tests, per_test_args) | 869 return driver.Driver.cmd_line(self, pixel_tests, per_test_args) |
| 871 | 870 |
| 872 @staticmethod | 871 @staticmethod |
| 873 def _loop_with_timeout(condition, timeout_secs): | 872 def _loop_with_timeout(condition, timeout_secs): |
| 874 deadline = time.time() + timeout_secs | 873 deadline = time.time() + timeout_secs |
| 875 while time.time() < deadline: | 874 while time.time() < deadline: |
| 876 if condition(): | 875 if condition(): |
| 877 return True | 876 return True |
| 878 return False | 877 return False |
| 879 | 878 |
| 880 def _all_pipes_created(self): | |
| 881 return self._device.PathExists( | |
| 882 [self._in_fifo_path, self._out_fifo_path, self._err_fifo_path]) | |
| 883 | |
| 884 def _remove_all_pipes(self): | |
| 885 self._device.RunShellCommand( | |
| 886 ['rm', '-f', self._in_fifo_path, self._out_fifo_path, self._err_fifo _path], | |
| 887 check_return=True) | |
| 888 return (not self._device.PathExists(self._in_fifo_path) and | |
| 889 not self._device.PathExists(self._out_fifo_path) and | |
| 890 not self._device.PathExists(self._err_fifo_path)) | |
| 891 | |
| 892 def start(self, pixel_tests, per_test_args, deadline): | 879 def start(self, pixel_tests, per_test_args, deadline): |
| 893 # We override the default start() so that we can call _android_driver_cm d_line() | 880 # We override the default start() so that we can call _android_driver_cm d_line() |
| 894 # instead of cmd_line(). | 881 # instead of cmd_line(). |
| 895 new_cmd_line = self._android_driver_cmd_line(pixel_tests, per_test_args) | 882 new_cmd_line = self._android_driver_cmd_line(pixel_tests, per_test_args) |
| 896 | 883 |
| 897 # Since _android_driver_cmd_line() is different than cmd_line() we need to provide | 884 # Since _android_driver_cmd_line() is different than cmd_line() we need to provide |
| 898 # our own mechanism for detecting when the process should be stopped. | 885 # our own mechanism for detecting when the process should be stopped. |
| 899 if self._current_cmd_line is None: | 886 if self._current_cmd_line is None: |
| 900 self._current_android_cmd_line = None | 887 self._current_android_cmd_line = None |
| 901 if new_cmd_line != self._current_android_cmd_line: | 888 if new_cmd_line != self._current_android_cmd_line: |
| 902 self.stop() | 889 self.stop() |
| 903 self._current_android_cmd_line = new_cmd_line | 890 self._current_android_cmd_line = new_cmd_line |
| 904 | 891 |
| 905 super(ChromiumAndroidDriver, self).start(pixel_tests, per_test_args, dea dline) | 892 super(ChromiumAndroidDriver, self).start(pixel_tests, per_test_args, dea dline) |
| 906 | 893 |
| 907 def _start(self, pixel_tests, per_test_args): | 894 def _start(self, pixel_tests, per_test_args): |
| 908 if not self._android_devices.is_device_prepared(self._device.serial): | 895 if not self._android_devices.is_device_prepared(self._device.serial): |
| 909 raise driver.DeviceFailure("%s is not prepared in _start()" % self._ device.serial) | 896 raise driver.DeviceFailure("%s is not prepared in _start()" % self._ device.serial) |
| 910 | 897 |
| 911 for retries in range(3): | 898 for retries in range(3): |
| 912 try: | 899 try: |
| 913 if self._start_once(pixel_tests, per_test_args): | 900 if self._start_once(pixel_tests, per_test_args): |
| 914 return | 901 return |
| 915 except ScriptError as e: | 902 except ScriptError as e: |
| 916 self._abort('ScriptError("%s") in _start()' % str(e)) | 903 self._abort('ScriptError("%s") in _start()' % str(e)) |
| 917 | 904 |
| 918 self._log_error('Failed to start the content_shell application. Retr ies=%d. Log:%s' % (retries, self._get_logcat())) | 905 self._log_error('Failed to start the content_shell application. Retr ies=%d. Log:\n%s' % (retries, self._get_logcat())) |
| 919 self.stop() | 906 self.stop() |
| 920 time.sleep(2) | 907 time.sleep(2) |
| 921 self._abort('Failed to start the content_shell application multiple time s. Giving up.') | 908 self._abort('Failed to start the content_shell application multiple time s. Giving up.') |
| 922 | 909 |
| 923 def _start_once(self, pixel_tests, per_test_args): | 910 def _start_once(self, pixel_tests, per_test_args): |
| 924 super(ChromiumAndroidDriver, self)._start(pixel_tests, per_test_args, wa it_for_ready=False) | 911 super(ChromiumAndroidDriver, self)._start(pixel_tests, per_test_args, wa it_for_ready=False) |
| 925 | 912 |
| 913 self._device.adb.Logcat(clear=True) | |
| 914 | |
| 915 self._device.RunShellCommand( | |
| 916 ['rm', '-rf', self._driver_details.device_crash_dumps_directory()], | |
| 917 check_return=True) | |
| 918 self._device.RunShellCommand( | |
| 919 ['mkdir', self._driver_details.device_crash_dumps_directory()], | |
| 920 check_return=True) | |
| 921 self._device.RunShellCommand( | |
| 922 ['chmod', '-R', '777', self._driver_details.device_crash_dumps_direc tory()], | |
| 923 check_return=True) | |
| 924 | |
| 925 # Read back the shell prompt to ensure adb shell ready. | |
|
qyearsley
2016/12/02 23:35:22
s/ensure adb shell ready/ensure adb shell is ready
jbudorick
2016/12/05 14:30:38
Done.
| |
| 926 deadline = time.time() + DRIVER_START_STOP_TIMEOUT_SECS | |
| 927 self._server_process.start() | |
| 928 self._read_prompt(deadline) | |
| 929 self._log_debug('Interactive shell started') | |
| 930 | |
| 931 # Start a process to read from the stdout fifo of the test driver and pr int to stdout. | |
| 932 self._read_stdout_process, stdout_port = self._start_netcat( | |
| 933 'ReadStdout', read_from_stdin=False) | |
| 934 self._log_debug('Redirecting stdout to port %d' % stdout_port) | |
| 935 | |
| 936 # Start a process to read from the stderr fifo of the test driver and pr int to stdout. | |
|
qyearsley
2016/12/02 23:35:22
What is the meaning of fifo in this context?
jbudorick
2016/12/05 14:30:38
It means that I didn't update this comment or the
| |
| 937 self._read_stderr_process, stderr_port = self._start_netcat( | |
| 938 'ReadStderr', first_port=stdout_port + 1, read_from_stdin=False) | |
| 939 self._log_debug('Redirecting stderr to port %d' % stderr_port) | |
| 940 | |
| 941 self._write_stdin_process, stdin_port = self._start_netcat( | |
| 942 'WriteStdin', first_port=stderr_port + 1) | |
| 943 self._log_debug('Redirecting stdin to port %d' % stdin_port) | |
| 944 | |
| 945 # Combine the stdout and stderr pipes into self._server_process. | |
| 946 self._replace_server_process_streams() | |
| 947 | |
| 926 # We delay importing forwarder as long as possible because it uses fcntl , | 948 # We delay importing forwarder as long as possible because it uses fcntl , |
| 927 # which isn't available on windows. | 949 # which isn't available on windows. |
| 928 from devil.android import forwarder | 950 from devil.android import forwarder |
| 929 | 951 |
| 930 self._log_debug('Starting forwarder') | 952 self._log_debug('Starting forwarder') |
| 931 forwarder.Forwarder.Map( | 953 forwarder.Forwarder.Map( |
| 932 [(p, p) for p in FORWARD_PORTS.split()], | 954 [(p, p) for p in FORWARD_PORTS.split()], |
| 933 self._device) | 955 self._device) |
| 934 | 956 forwarder.Forwarder.Map( |
| 935 self._device.adb.Logcat(clear=True) | 957 [(0, stdout_port), (0, stderr_port), (0, stdin_port)], |
| 958 self._device) | |
| 936 | 959 |
| 937 cmd_line_file_path = self._driver_details.command_line_file() | 960 cmd_line_file_path = self._driver_details.command_line_file() |
| 938 original_cmd_line_file_path = cmd_line_file_path + '.orig' | 961 original_cmd_line_file_path = cmd_line_file_path + '.orig' |
| 939 if (self._device.PathExists(cmd_line_file_path) | 962 if (self._device.PathExists(cmd_line_file_path) |
| 940 and not self._device.PathExists(original_cmd_line_file_path)): | 963 and not self._device.PathExists(original_cmd_line_file_path)): |
| 941 # We check for both the normal path and the backup because we do not want to step | 964 # We check for both the normal path and the backup because we do not want to step |
| 942 # on the backup. Otherwise, we'd clobber the backup whenever we chan ged the | 965 # on the backup. Otherwise, we'd clobber the backup whenever we chan ged the |
| 943 # command line during the run. | 966 # command line during the run. |
| 944 self._device.RunShellCommand( | 967 self._device.RunShellCommand( |
| 945 ['mv', cmd_line_file_path, original_cmd_line_file_path], | 968 ['mv', cmd_line_file_path, original_cmd_line_file_path], |
| 946 check_return=True) | 969 check_return=True) |
| 947 | 970 |
| 971 stream_port_args = [ | |
| 972 '--android-stderr-port=%s' % forwarder.Forwarder.DevicePortForHostPo rt(stderr_port), | |
| 973 '--android-stdin-port=%s' % forwarder.Forwarder.DevicePortForHostPor t(stdin_port), | |
| 974 '--android-stdout-port=%s' % forwarder.Forwarder.DevicePortForHostPo rt(stdout_port), | |
| 975 ] | |
| 976 cmd_line_contents = self._android_driver_cmd_line(pixel_tests, per_test_ args + stream_port_args) | |
| 948 self._device.WriteFile( | 977 self._device.WriteFile( |
| 949 self._driver_details.command_line_file(), | 978 self._driver_details.command_line_file(), |
| 950 ' '.join(self._android_driver_cmd_line(pixel_tests, per_test_args))) | 979 ' '.join(cmd_line_contents)) |
| 980 self._log_debug('Command-line file contents: %s' % ' '.join(cmd_line_con tents)) | |
| 951 self._created_cmd_line = True | 981 self._created_cmd_line = True |
| 952 | 982 |
| 953 self._device.RunShellCommand( | |
| 954 ['rm', '-rf', self._driver_details.device_crash_dumps_directory()], | |
| 955 check_return=True) | |
| 956 self._device.RunShellCommand( | |
| 957 ['mkdir', self._driver_details.device_crash_dumps_directory()], | |
| 958 check_return=True) | |
| 959 self._device.RunShellCommand( | |
| 960 ['chmod', '-R', '777', self._driver_details.device_crash_dumps_direc tory()], | |
| 961 check_return=True) | |
| 962 | |
| 963 try: | 983 try: |
| 964 self._device.StartActivity( | 984 self._device.StartActivity( |
| 965 intent.Intent( | 985 intent.Intent( |
| 966 component=self._driver_details.activity_name(), | 986 component=self._driver_details.activity_name(), |
| 967 extras={'RunInSubThread': None})) | 987 extras={'RunInSubThread': None})) |
| 968 except device_errors.CommandFailedError as exc: | 988 except device_errors.CommandFailedError as exc: |
| 969 self._log_error('Failed to start the content_shell application. Exce ption:\n' + str(exc)) | 989 self._log_error('Failed to start the content_shell application. Exce ption:\n' + str(exc)) |
| 970 return False | 990 return False |
| 971 | 991 |
| 972 if not ChromiumAndroidDriver._loop_with_timeout(self._all_pipes_created, DRIVER_START_STOP_TIMEOUT_SECS): | 992 # The test driver might crash during startup. |
| 973 return False | |
| 974 | |
| 975 # Read back the shell prompt to ensure adb shell ready. | |
| 976 deadline = time.time() + DRIVER_START_STOP_TIMEOUT_SECS | |
| 977 self._server_process.start() | |
| 978 self._read_prompt(deadline) | |
| 979 self._log_debug('Interactive shell started') | |
| 980 | |
| 981 # Start a process to read from the stdout fifo of the test driver and pr int to stdout. | |
| 982 self._log_debug('Redirecting stdout to ' + self._out_fifo_path) | |
| 983 self._read_stdout_process = self._port._server_process_constructor( | |
| 984 self._port, 'ReadStdout', | |
| 985 [self._device.adb.GetAdbPath(), '-s', self._device.serial, 'shell', 'cat', self._out_fifo_path]) | |
| 986 self._read_stdout_process.start() | |
| 987 | |
| 988 # Start a process to read from the stderr fifo of the test driver and pr int to stdout. | |
| 989 self._log_debug('Redirecting stderr to ' + self._err_fifo_path) | |
| 990 self._read_stderr_process = self._port._server_process_constructor( | |
| 991 self._port, 'ReadStderr', | |
| 992 [self._device.adb.GetAdbPath(), '-s', self._device.serial, 'shell', 'cat', self._err_fifo_path]) | |
| 993 self._read_stderr_process.start() | |
| 994 | |
| 995 self._log_debug('Redirecting stdin to ' + self._in_fifo_path) | |
| 996 self._server_process.write('cat >%s\n' % self._in_fifo_path) | |
| 997 | |
| 998 # Combine the stdout and stderr pipes into self._server_process. | |
| 999 self._server_process.replace_outputs(self._read_stdout_process._proc.std out, self._read_stderr_process._proc.stdout) | |
| 1000 | |
| 1001 def deadlock_detector(processes, normal_startup_event): | |
| 1002 if not ChromiumAndroidDriver._loop_with_timeout(lambda: normal_start up_event.is_set(), DRIVER_START_STOP_TIMEOUT_SECS): | |
| 1003 # If normal_startup_event is not set in time, the main thread mu st be blocked at | |
| 1004 # reading/writing the fifo. Kill the fifo reading/writing proces ses to let the | |
| 1005 # main thread escape from the deadlocked state. After that, the main thread will | |
| 1006 # treat this as a crash. | |
| 1007 self._log_error('Deadlock detected. Processes killed.') | |
| 1008 for i in processes: | |
| 1009 i.kill() | |
| 1010 | |
| 1011 # Start a thread to kill the pipe reading/writing processes on deadlock of the fifos during startup. | |
| 1012 normal_startup_event = threading.Event() | |
| 1013 threading.Thread( | |
| 1014 name='DeadlockDetector', | |
| 1015 target=deadlock_detector, | |
| 1016 args=([self._server_process, self._read_stdout_process, self._read_s tderr_process], normal_startup_event)).start() | |
| 1017 | |
| 1018 # The test driver might crash during startup or when the deadlock detect or hits | |
| 1019 # a deadlock and kills the fifo reading/writing processes. | |
| 1020 if not self._wait_for_server_process_output(self._server_process, deadli ne, '#READY'): | 993 if not self._wait_for_server_process_output(self._server_process, deadli ne, '#READY'): |
| 1021 return False | 994 return False |
| 1022 | 995 |
| 1023 # Inform the deadlock detector that the startup is successful without de adlock. | |
| 1024 normal_startup_event.set() | |
| 1025 self._log_debug("content_shell is ready") | 996 self._log_debug("content_shell is ready") |
| 1026 return True | 997 return True |
| 1027 | 998 |
| 999 def _start_netcat(self, server_name, first_port=10201, read_from_stdin=True) : | |
| 1000 for i in itertools.count(first_port, 65536): | |
| 1001 nc_cmd = ['nc', '-l', str(i)] | |
| 1002 if not read_from_stdin: | |
| 1003 nc_cmd.append('-d') | |
| 1004 proc = self._port.server_process_constructor(self._port, server_name , nc_cmd) | |
| 1005 proc.start() | |
| 1006 self._port.host.executive.wait_limited(proc.pid(), limit_in_seconds= 1) | |
| 1007 if self._port.host.executive.check_running_pid(proc.pid()): | |
| 1008 return (proc, i) | |
| 1009 | |
| 1010 def _replace_server_process_streams(self): | |
| 1011 # pylint: disable=protected-access | |
| 1012 self._server_process.replace_input( | |
| 1013 self._write_stdin_process._proc.stdin) | |
| 1014 self._server_process.replace_outputs( | |
| 1015 self._read_stdout_process._proc.stdout, | |
| 1016 self._read_stderr_process._proc.stdout) | |
| 1017 | |
| 1028 def _pid_on_target(self): | 1018 def _pid_on_target(self): |
| 1029 pids = self._device.GetPids(self._driver_details.package_name()) | 1019 pids = self._device.GetPids(self._driver_details.package_name()) |
| 1030 return pids.get(self._driver_details.package_name()) | 1020 return pids.get(self._driver_details.package_name()) |
| 1031 | 1021 |
| 1032 def stop(self): | 1022 def stop(self): |
| 1033 if not self._device_failed: | 1023 if not self._device_failed: |
| 1034 # Do not try to stop the application if there's something wrong with the device; adb may hang. | 1024 # Do not try to stop the application if there's something wrong with the device; adb may hang. |
| 1035 # FIXME: crbug.com/305040. Figure out if it's really hanging (and wh y). | 1025 # FIXME: crbug.com/305040. Figure out if it's really hanging (and wh y). |
| 1036 self._device.ForceStop(self._driver_details.package_name()) | 1026 self._device.ForceStop(self._driver_details.package_name()) |
| 1037 | 1027 |
| 1028 if self._write_stdin_process: | |
| 1029 self._write_stdin_process.kill() | |
| 1030 self._write_stdin_process = None | |
| 1031 | |
| 1038 if self._read_stdout_process: | 1032 if self._read_stdout_process: |
| 1039 self._read_stdout_process.kill() | 1033 self._read_stdout_process.kill() |
| 1040 self._read_stdout_process = None | 1034 self._read_stdout_process = None |
| 1041 | 1035 |
| 1042 if self._read_stderr_process: | 1036 if self._read_stderr_process: |
| 1043 self._read_stderr_process.kill() | 1037 self._read_stderr_process.kill() |
| 1044 self._read_stderr_process = None | 1038 self._read_stderr_process = None |
| 1045 | 1039 |
| 1046 # We delay importing forwarder as long as possible because it uses fcntl , | 1040 # We delay importing forwarder as long as possible because it uses fcntl , |
| 1047 # which isn't available on windows. | 1041 # which isn't available on windows. |
| 1048 from devil.android import forwarder | 1042 from devil.android import forwarder |
| 1049 | 1043 |
| 1050 forwarder.Forwarder.KillDevice(self._device) | 1044 forwarder.Forwarder.KillDevice(self._device) |
| 1051 forwarder.Forwarder.KillHost() | 1045 forwarder.Forwarder.KillHost() |
| 1052 | 1046 |
| 1053 super(ChromiumAndroidDriver, self).stop() | 1047 super(ChromiumAndroidDriver, self).stop() |
| 1054 | 1048 |
| 1055 if self._android_devices.is_device_prepared(self._device.serial): | |
| 1056 if not ChromiumAndroidDriver._loop_with_timeout(self._remove_all_pip es, DRIVER_START_STOP_TIMEOUT_SECS): | |
| 1057 self._abort('Failed to remove fifo files. May be locked.') | |
| 1058 | |
| 1059 self._clean_up_cmd_line() | 1049 self._clean_up_cmd_line() |
| 1060 | 1050 |
| 1061 def _pull_crash_dumps_from_device(self): | 1051 def _pull_crash_dumps_from_device(self): |
| 1062 result = [] | 1052 result = [] |
| 1063 if not self._device.PathExists(self._driver_details.device_crash_dumps_d irectory()): | 1053 if not self._device.PathExists(self._driver_details.device_crash_dumps_d irectory()): |
| 1064 return result | 1054 return result |
| 1065 dumps = self._device.ListDirectory( | 1055 dumps = self._device.ListDirectory( |
| 1066 self._driver_details.device_crash_dumps_directory()) | 1056 self._driver_details.device_crash_dumps_directory()) |
| 1067 for dump in dumps: | 1057 for dump in dumps: |
| 1068 device_dump = '%s/%s' % (self._driver_details.device_crash_dumps_dir ectory(), dump) | 1058 device_dump = '%s/%s' % (self._driver_details.device_crash_dumps_dir ectory(), dump) |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1109 return command | 1099 return command |
| 1110 | 1100 |
| 1111 def _read_prompt(self, deadline): | 1101 def _read_prompt(self, deadline): |
| 1112 last_char = '' | 1102 last_char = '' |
| 1113 while True: | 1103 while True: |
| 1114 current_char = self._server_process.read_stdout(deadline, 1) | 1104 current_char = self._server_process.read_stdout(deadline, 1) |
| 1115 if current_char == ' ': | 1105 if current_char == ' ': |
| 1116 if last_char in ('#', '$'): | 1106 if last_char in ('#', '$'): |
| 1117 return | 1107 return |
| 1118 last_char = current_char | 1108 last_char = current_char |
| OLD | NEW |