| 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 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 [[MS_TRUETYPE_FONTS_DIR], 'Verdana_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE], | 114 [[MS_TRUETYPE_FONTS_DIR], 'Verdana_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE], |
| 115 # The Microsoft font EULA | 115 # The Microsoft font EULA |
| 116 [['/usr/share/doc/ttf-mscorefonts-installer/'], 'READ_ME!.gz', MS_TRUETYPE_F
ONTS_PACKAGE], | 116 [['/usr/share/doc/ttf-mscorefonts-installer/'], 'READ_ME!.gz', MS_TRUETYPE_F
ONTS_PACKAGE], |
| 117 # Other fonts: Arabic, CJK, Indic, Thai, etc. | 117 # Other fonts: Arabic, CJK, Indic, Thai, etc. |
| 118 [['/usr/share/fonts/truetype/ttf-dejavu/'], 'DejaVuSans.ttf', 'ttf-dejavu'], | 118 [['/usr/share/fonts/truetype/ttf-dejavu/'], 'DejaVuSans.ttf', 'ttf-dejavu'], |
| 119 [['/usr/share/fonts/truetype/kochi/'], 'kochi-mincho.ttf', 'ttf-kochi-mincho
'], | 119 [['/usr/share/fonts/truetype/kochi/'], 'kochi-mincho.ttf', 'ttf-kochi-mincho
'], |
| 120 [['/usr/share/fonts/truetype/ttf-indic-fonts-core/'], 'lohit_hi.ttf', 'ttf-i
ndic-fonts-core'], | 120 [['/usr/share/fonts/truetype/ttf-indic-fonts-core/'], 'lohit_hi.ttf', 'ttf-i
ndic-fonts-core'], |
| 121 [['/usr/share/fonts/truetype/ttf-indic-fonts-core/'], 'lohit_ta.ttf', 'ttf-i
ndic-fonts-core'], | 121 [['/usr/share/fonts/truetype/ttf-indic-fonts-core/'], 'lohit_ta.ttf', 'ttf-i
ndic-fonts-core'], |
| 122 [['/usr/share/fonts/truetype/ttf-indic-fonts-core/'], 'MuktiNarrow.ttf', 'tt
f-indic-fonts-core'], | 122 [['/usr/share/fonts/truetype/ttf-indic-fonts-core/'], 'MuktiNarrow.ttf', 'tt
f-indic-fonts-core'], |
| 123 [['/usr/share/fonts/truetype/thai/', '/usr/share/fonts/truetype/tlwg/'], 'Ga
ruda.ttf', 'fonts-tlwg-garuda'], | 123 [['/usr/share/fonts/truetype/thai/', '/usr/share/fonts/truetype/tlwg/'], 'Ga
ruda.ttf', 'fonts-tlwg-garuda'], |
| 124 [['/usr/share/fonts/truetype/ttf-indic-fonts-core/', '/usr/share/fonts/truet
ype/ttf-punjabi-fonts/'], 'lohit_pa.ttf', 'ttf-indic-fonts-core'], | 124 [['/usr/share/fonts/truetype/ttf-indic-fonts-core/', '/usr/share/fonts/truet
ype/ttf-punjabi-fonts/'], 'lohit_pa.ttf', |
| 125 'ttf-indic-fonts-core'], |
| 125 ] | 126 ] |
| 126 | 127 |
| 127 # Test resources that need to be accessed as files directly. | 128 # Test resources that need to be accessed as files directly. |
| 128 # Each item can be the relative path of a directory or a file. | 129 # Each item can be the relative path of a directory or a file. |
| 129 TEST_RESOURCES_TO_PUSH = [ | 130 TEST_RESOURCES_TO_PUSH = [ |
| 130 # Blob tests need to access files directly. | 131 # Blob tests need to access files directly. |
| 131 'editing/pasteboard/resources', | 132 'editing/pasteboard/resources', |
| 132 'fast/files/resources', | 133 'fast/files/resources', |
| 133 'http/tests/local/resources', | 134 'http/tests/local/resources', |
| 134 'http/tests/local/formdata/resources', | 135 'http/tests/local/formdata/resources', |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 pass | 248 pass |
| 248 return pids | 249 return pids |
| 249 | 250 |
| 250 def run(self, command, ignore_error=False): | 251 def run(self, command, ignore_error=False): |
| 251 self._log_debug('Run adb command: ' + str(command)) | 252 self._log_debug('Run adb command: ' + str(command)) |
| 252 if ignore_error: | 253 if ignore_error: |
| 253 error_handler = self._executive.ignore_error | 254 error_handler = self._executive.ignore_error |
| 254 else: | 255 else: |
| 255 error_handler = None | 256 error_handler = None |
| 256 | 257 |
| 257 result = self._executive.run_command(self.adb_command() + command, error
_handler=error_handler, debug_logging=self._debug_logging) | 258 result = self._executive.run_command(self.adb_command() + command, |
| 259 error_handler=error_handler, |
| 260 debug_logging=self._debug_logging) |
| 258 | 261 |
| 259 # We limit the length to avoid outputting too verbose commands, such as
"adb logcat". | 262 # We limit the length to avoid outputting too verbose commands, such as
"adb logcat". |
| 260 self._log_debug('Run adb result: ' + result[:80]) | 263 self._log_debug('Run adb result: ' + result[:80]) |
| 261 return result | 264 return result |
| 262 | 265 |
| 263 def get_serial(self): | 266 def get_serial(self): |
| 264 return self._device_serial | 267 return self._device_serial |
| 265 | 268 |
| 266 def adb_command(self): | 269 def adb_command(self): |
| 267 return [AndroidCommands.adb_command_path(self._executive, self._debug_lo
gging), '-s', self._device_serial] | 270 return [AndroidCommands.adb_command_path(self._executive, self._debug_lo
gging), '-s', self._device_serial] |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 _log.info('[%s] %s' % (self._device_serial, message)) | 306 _log.info('[%s] %s' % (self._device_serial, message)) |
| 304 | 307 |
| 305 def _log_debug(self, message): | 308 def _log_debug(self, message): |
| 306 if self._debug_logging: | 309 if self._debug_logging: |
| 307 _log.debug('[%s] %s' % (self._device_serial, message)) | 310 _log.debug('[%s] %s' % (self._device_serial, message)) |
| 308 | 311 |
| 309 @staticmethod | 312 @staticmethod |
| 310 def _determine_adb_version(adb_command_path, executive, debug_logging): | 313 def _determine_adb_version(adb_command_path, executive, debug_logging): |
| 311 re_version = re.compile('^.*version ([\d\.]+)') | 314 re_version = re.compile('^.*version ([\d\.]+)') |
| 312 try: | 315 try: |
| 313 output = executive.run_command([adb_command_path, 'version'], error_
handler=executive.ignore_error, | 316 output = executive.run_command([adb_command_path, 'version'], |
| 317 error_handler=executive.ignore_error, |
| 314 debug_logging=debug_logging) | 318 debug_logging=debug_logging) |
| 315 except OSError: | 319 except OSError: |
| 316 return None | 320 return None |
| 317 | 321 |
| 318 result = re_version.match(output) | 322 result = re_version.match(output) |
| 319 if not output or not result: | 323 if not output or not result: |
| 320 return None | 324 return None |
| 321 | 325 |
| 322 return [int(n) for n in result.group(1).split('.')] | 326 return [int(n) for n in result.group(1).split('.')] |
| 323 | 327 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 344 | 348 |
| 345 if self._default_device: | 349 if self._default_device: |
| 346 self._usable_devices = [AndroidCommands(executive, self._default_dev
ice, self._debug_logging)] | 350 self._usable_devices = [AndroidCommands(executive, self._default_dev
ice, self._debug_logging)] |
| 347 return self._usable_devices | 351 return self._usable_devices |
| 348 | 352 |
| 349 # Example "adb devices" command output: | 353 # Example "adb devices" command output: |
| 350 # List of devices attached | 354 # List of devices attached |
| 351 # 0123456789ABCDEF device | 355 # 0123456789ABCDEF device |
| 352 re_device = re.compile('^([a-zA-Z0-9_:.-]+)\tdevice$', re.MULTILINE) | 356 re_device = re.compile('^([a-zA-Z0-9_:.-]+)\tdevice$', re.MULTILINE) |
| 353 | 357 |
| 354 result = executive.run_command([AndroidCommands.adb_command_path(executi
ve, debug_logging=self._debug_logging), 'devices'], | 358 result = executive.run_command( |
| 355 error_handler=executive.ignore_error, deb
ug_logging=self._debug_logging) | 359 [AndroidCommands.adb_command_path(executive, |
| 360 debug_logging=self._debug_logging)
, 'devices'], |
| 361 error_handler=executive.ignore_error, |
| 362 debug_logging=self._debug_logging) |
| 356 devices = re_device.findall(result) | 363 devices = re_device.findall(result) |
| 357 if not devices: | 364 if not devices: |
| 358 return [] | 365 return [] |
| 359 | 366 |
| 360 for device_serial in sorted(devices): | 367 for device_serial in sorted(devices): |
| 361 commands = AndroidCommands(executive, device_serial, self._debug_log
ging) | 368 commands = AndroidCommands(executive, device_serial, self._debug_log
ging) |
| 362 if self._battery_level_for_device(commands) < AndroidDevices.MINIMUM
_BATTERY_PERCENTAGE: | 369 if self._battery_level_for_device(commands) < AndroidDevices.MINIMUM
_BATTERY_PERCENTAGE: |
| 363 _log.warning('Device with serial "%s" skipped because it has les
s than %d percent battery.' | 370 _log.warning('Device with serial "%s" skipped because it has les
s than %d percent battery.' % |
| 364 % (commands.get_serial(), AndroidDevices.MINIMUM_BATTERY_PER
CENTAGE)) | 371 (commands.get_serial(), AndroidDevices.MINIMUM_BATT
ERY_PERCENTAGE)) |
| 365 continue | 372 continue |
| 366 | 373 |
| 367 if not self._is_device_screen_on(commands): | 374 if not self._is_device_screen_on(commands): |
| 368 _log.warning('Device with serial "%s" skipped because the screen
must be on.' % commands.get_serial()) | 375 _log.warning('Device with serial "%s" skipped because the screen
must be on.' % commands.get_serial()) |
| 369 continue | 376 continue |
| 370 | 377 |
| 371 self._usable_devices.append(commands) | 378 self._usable_devices.append(commands) |
| 372 | 379 |
| 373 return self._usable_devices | 380 return self._usable_devices |
| 374 | 381 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 | 440 |
| 434 # Initialize the AndroidDevices class which tracks available devices. | 441 # Initialize the AndroidDevices class which tracks available devices. |
| 435 default_device = None | 442 default_device = None |
| 436 if hasattr(self._options, 'adb_device') and len(self._options.adb_device
): | 443 if hasattr(self._options, 'adb_device') and len(self._options.adb_device
): |
| 437 default_device = self._options.adb_device | 444 default_device = self._options.adb_device |
| 438 | 445 |
| 439 self._debug_logging = self.get_option('android_logging') | 446 self._debug_logging = self.get_option('android_logging') |
| 440 self._devices = AndroidDevices(self._executive, default_device, self._de
bug_logging) | 447 self._devices = AndroidDevices(self._executive, default_device, self._de
bug_logging) |
| 441 | 448 |
| 442 # Tell AndroidCommands where to search for the "adb" command. | 449 # Tell AndroidCommands where to search for the "adb" command. |
| 443 AndroidCommands.set_adb_command_path_options(['adb', | 450 AndroidCommands.set_adb_command_path_options(['adb', self.path_from_chro
mium_base('third_party', 'android_tools', 'sdk', |
| 444 self.path_from_chromium_base('third_party', 'android_tools', 'sdk',
'platform-tools', 'adb')]) | 451
'platform-tools', 'adb')]) |
| 445 | 452 |
| 446 prepared_devices = self.get_option('prepared_devices', []) | 453 prepared_devices = self.get_option('prepared_devices', []) |
| 447 for serial in prepared_devices: | 454 for serial in prepared_devices: |
| 448 self._devices.set_device_prepared(serial) | 455 self._devices.set_device_prepared(serial) |
| 449 | 456 |
| 450 def default_smoke_test_only(self): | 457 def default_smoke_test_only(self): |
| 451 return True | 458 return True |
| 452 | 459 |
| 453 # Local public methods. | 460 # Local public methods. |
| 454 def path_to_forwarder(self): | 461 def path_to_forwarder(self): |
| 455 return self._build_path('forwarder') | 462 return self._build_path('forwarder') |
| 456 | 463 |
| 457 def path_to_md5sum(self): | 464 def path_to_md5sum(self): |
| 458 return self._build_path(MD5SUM_DEVICE_FILE_NAME) | 465 return self._build_path(MD5SUM_DEVICE_FILE_NAME) |
| 459 | 466 |
| 460 def path_to_md5sum_host(self): | 467 def path_to_md5sum_host(self): |
| 461 return self._build_path(MD5SUM_HOST_FILE_NAME) | 468 return self._build_path(MD5SUM_HOST_FILE_NAME) |
| 462 | 469 |
| 463 def additional_driver_flag(self): | 470 def additional_driver_flag(self): |
| 464 return super(AndroidPort, self).additional_driver_flag() + self._driver_
details.additional_command_line_flags(use_breakpad=not self.get_option('disable_
breakpad')) | 471 return super(AndroidPort, self).additional_driver_flag() + self._driver_
details.additional_command_line_flags( |
| 472 use_breakpad=not self.get_option('disable_breakpad')) |
| 465 | 473 |
| 466 def default_timeout_ms(self): | 474 def default_timeout_ms(self): |
| 467 # Android platform has less computing power than desktop platforms. | 475 # Android platform has less computing power than desktop platforms. |
| 468 # Using 10 seconds allows us to pass most slow tests which are not | 476 # Using 10 seconds allows us to pass most slow tests which are not |
| 469 # marked as slow tests on desktop platforms. | 477 # marked as slow tests on desktop platforms. |
| 470 return 10 * 1000 | 478 return 10 * 1000 |
| 471 | 479 |
| 472 def driver_stop_timeout(self): | 480 def driver_stop_timeout(self): |
| 473 # The driver doesn't respond to closing stdin, so we might as well stop
the driver immediately. | 481 # The driver doesn't respond to closing stdin, so we might as well stop
the driver immediately. |
| 474 return 0.0 | 482 return 0.0 |
| 475 | 483 |
| 476 def default_child_processes(self): | 484 def default_child_processes(self): |
| 477 usable_devices = self._devices.usable_devices(self._executive) | 485 usable_devices = self._devices.usable_devices(self._executive) |
| 478 if not usable_devices: | 486 if not usable_devices: |
| 479 raise test_run_results.TestRunException(test_run_results.NO_DEVICES_
EXIT_STATUS, "Unable to find any attached Android devices.") | 487 raise test_run_results.TestRunException(test_run_results.NO_DEVICES_
EXIT_STATUS, |
| 488 "Unable to find any attached
Android devices.") |
| 480 return len(usable_devices) | 489 return len(usable_devices) |
| 481 | 490 |
| 482 def max_drivers_per_process(self): | 491 def max_drivers_per_process(self): |
| 483 # Android falls over when we try to run multiple content_shells per work
er. | 492 # Android falls over when we try to run multiple content_shells per work
er. |
| 484 # See https://codereview.chromium.org/1158323009/ | 493 # See https://codereview.chromium.org/1158323009/ |
| 485 return 1 | 494 return 1 |
| 486 | 495 |
| 487 def check_wdiff(self, logging=True): | 496 def check_wdiff(self, logging=True): |
| 488 return self._host_port.check_wdiff(logging) | 497 return self._host_port.check_wdiff(logging) |
| 489 | 498 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 | 601 |
| 593 def check_sys_deps(self, needs_http): | 602 def check_sys_deps(self, needs_http): |
| 594 for (font_dirs, font_file, package) in HOST_FONT_FILES: | 603 for (font_dirs, font_file, package) in HOST_FONT_FILES: |
| 595 exists = False | 604 exists = False |
| 596 for font_dir in font_dirs: | 605 for font_dir in font_dirs: |
| 597 font_path = font_dir + font_file | 606 font_path = font_dir + font_file |
| 598 if self._check_file_exists(font_path, '', logging=False): | 607 if self._check_file_exists(font_path, '', logging=False): |
| 599 exists = True | 608 exists = True |
| 600 break | 609 break |
| 601 if not exists: | 610 if not exists: |
| 602 _log.error('You are missing %s under %s. Try installing %s. See
build instructions.' % (font_file, font_dirs, package)) | 611 _log.error('You are missing %s under %s. Try installing %s. See
build instructions.' % |
| 612 (font_file, font_dirs, package)) |
| 603 return test_run_results.SYS_DEPS_EXIT_STATUS | 613 return test_run_results.SYS_DEPS_EXIT_STATUS |
| 604 return test_run_results.OK_EXIT_STATUS | 614 return test_run_results.OK_EXIT_STATUS |
| 605 | 615 |
| 606 def requires_http_server(self): | 616 def requires_http_server(self): |
| 607 """Chromium Android runs tests on devices, and uses the HTTP server to | 617 """Chromium Android runs tests on devices, and uses the HTTP server to |
| 608 serve the actual layout tests to the test driver.""" | 618 serve the actual layout tests to the test driver.""" |
| 609 return True | 619 return True |
| 610 | 620 |
| 611 def start_http_server(self, additional_dirs, number_of_drivers): | 621 def start_http_server(self, additional_dirs, number_of_drivers): |
| 612 additional_dirs[PERF_TEST_PATH_PREFIX] = self.perf_tests_dir() | 622 additional_dirs[PERF_TEST_PATH_PREFIX] = self.perf_tests_dir() |
| 613 additional_dirs[LAYOUT_TEST_PATH_PREFIX] = self.layout_tests_dir() | 623 additional_dirs[LAYOUT_TEST_PATH_PREFIX] = self.layout_tests_dir() |
| 614 super(AndroidPort, self).start_http_server(additional_dirs, number_of_dr
ivers) | 624 super(AndroidPort, self).start_http_server(additional_dirs, number_of_dr
ivers) |
| 615 | 625 |
| 616 def create_driver(self, worker_number, no_timeout=False): | 626 def create_driver(self, worker_number, no_timeout=False): |
| 617 return ChromiumAndroidDriver(self, worker_number, pixel_tests=self.get_o
ption('pixel_tests'), | 627 return ChromiumAndroidDriver(self, |
| 628 worker_number, |
| 629 pixel_tests=self.get_option('pixel_tests'), |
| 618 driver_details=self._driver_details, | 630 driver_details=self._driver_details, |
| 619 android_devices=self._devices, | 631 android_devices=self._devices, |
| 620 # Force no timeout to avoid test driver tim
eouts before NRWT. | 632 # Force no timeout to avoid test driver tim
eouts before NRWT. |
| 621 no_timeout=True) | 633 no_timeout=True) |
| 622 | 634 |
| 623 def driver_cmd_line(self): | 635 def driver_cmd_line(self): |
| 624 # Override to return the actual test driver's command line. | 636 # Override to return the actual test driver's command line. |
| 625 return self.create_driver(0)._android_driver_cmd_line(self.get_option('p
ixel_tests'), []) | 637 return self.create_driver(0)._android_driver_cmd_line(self.get_option('p
ixel_tests'), []) |
| 626 | 638 |
| 627 def clobber_old_port_specific_results(self): | 639 def clobber_old_port_specific_results(self): |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 # Local private methods. | 675 # Local private methods. |
| 664 | 676 |
| 665 @staticmethod | 677 @staticmethod |
| 666 def _android_server_process_constructor(port, server_name, cmd_line, env=Non
e, logging=False): | 678 def _android_server_process_constructor(port, server_name, cmd_line, env=Non
e, logging=False): |
| 667 # We need universal_newlines=True, because 'adb shell' for some unknown
reason | 679 # We need universal_newlines=True, because 'adb shell' for some unknown
reason |
| 668 # does newline conversion of unix-style LF into win-style CRLF (and we n
eed | 680 # does newline conversion of unix-style LF into win-style CRLF (and we n
eed |
| 669 # to convert that back). This can cause headaches elsewhere because | 681 # to convert that back). This can cause headaches elsewhere because |
| 670 # server_process' stdout and stderr are now unicode file-like objects, | 682 # server_process' stdout and stderr are now unicode file-like objects, |
| 671 # not binary file-like objects like all of the other ports are. | 683 # not binary file-like objects like all of the other ports are. |
| 672 # FIXME: crbug.com/496983. | 684 # FIXME: crbug.com/496983. |
| 673 return server_process.ServerProcess(port, server_name, cmd_line, env, | 685 return server_process.ServerProcess(port, |
| 674 universal_newlines=True, treat_no_da
ta_as_crash=True, logging=logging) | 686 server_name, |
| 687 cmd_line, |
| 688 env, |
| 689 universal_newlines=True, |
| 690 treat_no_data_as_crash=True, |
| 691 logging=logging) |
| 675 | 692 |
| 676 | 693 |
| 677 class AndroidPerf(SingleFileOutputProfiler): | 694 class AndroidPerf(SingleFileOutputProfiler): |
| 678 _cached_perf_host_path = None | 695 _cached_perf_host_path = None |
| 679 _have_searched_for_perf_host = False | 696 _have_searched_for_perf_host = False |
| 680 | 697 |
| 681 def __init__(self, host, executable_path, output_dir, android_commands, symf
s_path, kallsyms_path, identifier=None): | 698 def __init__(self, host, executable_path, output_dir, android_commands, symf
s_path, kallsyms_path, identifier=None): |
| 682 super(AndroidPerf, self).__init__(host, executable_path, output_dir, "da
ta", identifier) | 699 super(AndroidPerf, self).__init__(host, executable_path, output_dir, "da
ta", identifier) |
| 683 self._android_commands = android_commands | 700 self._android_commands = android_commands |
| 684 self._perf_process = None | 701 self._perf_process = None |
| (...skipping 29 matching lines...) Expand all Loading... |
| 714 The test driver must be built with profiling=1, make sure you've done: | 731 The test driver must be built with profiling=1, make sure you've done: |
| 715 export GYP_DEFINES="profiling=1 $GYP_DEFINES" | 732 export GYP_DEFINES="profiling=1 $GYP_DEFINES" |
| 716 update-webkit --chromium-android | 733 update-webkit --chromium-android |
| 717 build-webkit --chromium-android | 734 build-webkit --chromium-android |
| 718 | 735 |
| 719 Googlers should read: | 736 Googlers should read: |
| 720 http://goto.google.com/cr-android-perf-howto | 737 http://goto.google.com/cr-android-perf-howto |
| 721 """) | 738 """) |
| 722 | 739 |
| 723 def attach_to_pid(self, pid): | 740 def attach_to_pid(self, pid): |
| 724 assert(pid) | 741 assert (pid) |
| 725 assert(self._perf_process == None) | 742 assert (self._perf_process is None) |
| 726 # FIXME: This can't be a fixed timeout! | 743 # FIXME: This can't be a fixed timeout! |
| 727 cmd = self._android_commands.adb_command() + ['shell', 'perf', 'record',
'-g', '-p', pid, 'sleep', 30] | 744 cmd = self._android_commands.adb_command() + ['shell', 'perf', 'record',
'-g', '-p', pid, 'sleep', 30] |
| 728 self._perf_process = self._host.executive.popen(cmd) | 745 self._perf_process = self._host.executive.popen(cmd) |
| 729 | 746 |
| 730 def _perf_version_string(self, perf_path): | 747 def _perf_version_string(self, perf_path): |
| 731 try: | 748 try: |
| 732 return self._host.executive.run_command([perf_path, '--version']) | 749 return self._host.executive.run_command([perf_path, '--version']) |
| 733 except: | 750 except: |
| 734 return None | 751 return None |
| 735 | 752 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 757 perf_exitcode = self._perf_process.wait() | 774 perf_exitcode = self._perf_process.wait() |
| 758 if perf_exitcode != 0: | 775 if perf_exitcode != 0: |
| 759 _log.debug("Perf failed (exit code: %i), can't process results." % p
erf_exitcode) | 776 _log.debug("Perf failed (exit code: %i), can't process results." % p
erf_exitcode) |
| 760 return | 777 return |
| 761 | 778 |
| 762 self._android_commands.pull('/data/perf.data', self._output_path) | 779 self._android_commands.pull('/data/perf.data', self._output_path) |
| 763 | 780 |
| 764 perfhost_path = self._perfhost_path() | 781 perfhost_path = self._perfhost_path() |
| 765 perfhost_report_command = [ | 782 perfhost_report_command = [ |
| 766 'report', | 783 'report', |
| 767 '--input', self._output_path, | 784 '--input', |
| 768 '--symfs', self._symfs_path, | 785 self._output_path, |
| 769 '--kallsyms', self._kallsyms_path, | 786 '--symfs', |
| 787 self._symfs_path, |
| 788 '--kallsyms', |
| 789 self._kallsyms_path, |
| 770 ] | 790 ] |
| 771 if perfhost_path: | 791 if perfhost_path: |
| 772 perfhost_args = [perfhost_path] + perfhost_report_command + ['--call
-graph', 'none'] | 792 perfhost_args = [perfhost_path] + perfhost_report_command + ['--call
-graph', 'none'] |
| 773 perf_output = self._host.executive.run_command(perfhost_args) | 793 perf_output = self._host.executive.run_command(perfhost_args) |
| 774 # We could save off the full -g report to a file if users found that
useful. | 794 # We could save off the full -g report to a file if users found that
useful. |
| 775 _log.debug(self._first_ten_lines_of_profile(perf_output)) | 795 _log.debug(self._first_ten_lines_of_profile(perf_output)) |
| 776 else: | 796 else: |
| 777 _log.debug(""" | 797 _log.debug(""" |
| 778 Failed to find perfhost_linux binary, can't process samples from the device. | 798 Failed to find perfhost_linux binary, can't process samples from the device. |
| 779 | 799 |
| 780 perfhost_linux can be built from: | 800 perfhost_linux can be built from: |
| 781 https://android.googlesource.com/platform/external/linux-tools-perf/ | 801 https://android.googlesource.com/platform/external/linux-tools-perf/ |
| 782 also, modern versions of perf (available from apt-get install goobuntu-kernel-to
ols-common) | 802 also, modern versions of perf (available from apt-get install goobuntu-kernel-to
ols-common) |
| 783 may also be able to process the perf.data files from the device. | 803 may also be able to process the perf.data files from the device. |
| 784 | 804 |
| 785 Googlers should read: | 805 Googlers should read: |
| 786 http://goto.google.com/cr-android-perf-howto | 806 http://goto.google.com/cr-android-perf-howto |
| 787 for instructions on installing pre-built copies of perfhost_linux | 807 for instructions on installing pre-built copies of perfhost_linux |
| 788 http://crbug.com/165250 discusses making these pre-built binaries externally ava
ilable. | 808 http://crbug.com/165250 discusses making these pre-built binaries externally ava
ilable. |
| 789 """) | 809 """) |
| 790 | 810 |
| 791 perfhost_display_patch = perfhost_path if perfhost_path else 'perfhost_l
inux' | 811 perfhost_display_patch = perfhost_path if perfhost_path else 'perfhost_l
inux' |
| 792 _log.debug("To view the full profile, run:") | 812 _log.debug("To view the full profile, run:") |
| 793 _log.debug(' '.join([perfhost_display_patch] + perfhost_report_command)) | 813 _log.debug(' '.join([perfhost_display_patch] + perfhost_report_command)) |
| 794 | 814 |
| 795 | 815 |
| 796 class ChromiumAndroidDriver(driver.Driver): | 816 class ChromiumAndroidDriver(driver.Driver): |
| 797 | |
| 798 def __init__(self, port, worker_number, pixel_tests, driver_details, android
_devices, no_timeout=False): | 817 def __init__(self, port, worker_number, pixel_tests, driver_details, android
_devices, no_timeout=False): |
| 799 super(ChromiumAndroidDriver, self).__init__(port, worker_number, pixel_t
ests, no_timeout) | 818 super(ChromiumAndroidDriver, self).__init__(port, worker_number, pixel_t
ests, no_timeout) |
| 800 self._in_fifo_path = driver_details.device_fifo_directory() + 'stdin.fif
o' | 819 self._in_fifo_path = driver_details.device_fifo_directory() + 'stdin.fif
o' |
| 801 self._out_fifo_path = driver_details.device_fifo_directory() + 'test.fif
o' | 820 self._out_fifo_path = driver_details.device_fifo_directory() + 'test.fif
o' |
| 802 self._err_fifo_path = driver_details.device_fifo_directory() + 'stderr.f
ifo' | 821 self._err_fifo_path = driver_details.device_fifo_directory() + 'stderr.f
ifo' |
| 803 self._read_stdout_process = None | 822 self._read_stdout_process = None |
| 804 self._read_stderr_process = None | 823 self._read_stderr_process = None |
| 805 self._forwarder_process = None | 824 self._forwarder_process = None |
| 806 self._original_governors = {} | 825 self._original_governors = {} |
| 807 self._original_kptr_restrict = None | 826 self._original_kptr_restrict = None |
| 808 | 827 |
| 809 self._android_devices = android_devices | 828 self._android_devices = android_devices |
| 810 self._android_commands = android_devices.get_device(port._executive, wor
ker_number) | 829 self._android_commands = android_devices.get_device(port._executive, wor
ker_number) |
| 811 self._driver_details = driver_details | 830 self._driver_details = driver_details |
| 812 self._debug_logging = self._port._debug_logging | 831 self._debug_logging = self._port._debug_logging |
| 813 self._created_cmd_line = False | 832 self._created_cmd_line = False |
| 814 self._device_failed = False | 833 self._device_failed = False |
| 815 | 834 |
| 816 # FIXME: If we taught ProfileFactory about "target" devices we could | 835 # FIXME: If we taught ProfileFactory about "target" devices we could |
| 817 # just use the logic in Driver instead of duplicating it here. | 836 # just use the logic in Driver instead of duplicating it here. |
| 818 if self._port.get_option("profile"): | 837 if self._port.get_option("profile"): |
| 819 # FIXME: This should be done once, instead of per-driver! | 838 # FIXME: This should be done once, instead of per-driver! |
| 820 symfs_path = self._find_or_create_symfs() | 839 symfs_path = self._find_or_create_symfs() |
| 821 kallsyms_path = self._update_kallsyms_cache(symfs_path) | 840 kallsyms_path = self._update_kallsyms_cache(symfs_path) |
| 822 # FIXME: We should pass this some sort of "Bridge" object abstractio
n around ADB instead of a path/device pair. | 841 # FIXME: We should pass this some sort of "Bridge" object abstractio
n around ADB instead of a path/device pair. |
| 823 self._profiler = AndroidPerf(self._port.host, self._port._path_to_dr
iver(), self._port.results_directory(), | 842 self._profiler = AndroidPerf(self._port.host, self._port._path_to_dr
iver(), self._port.results_directory(), |
| 824 self._android_commands, symfs_path, kallsyms_path) | 843 self._android_commands, symfs_path, kal
lsyms_path) |
| 825 # FIXME: This is a layering violation and should be moved to Port.ch
eck_sys_deps | 844 # FIXME: This is a layering violation and should be moved to Port.ch
eck_sys_deps |
| 826 # once we have an abstraction around an adb_path/device_serial pair
to make it | 845 # once we have an abstraction around an adb_path/device_serial pair
to make it |
| 827 # easy to make these class methods on AndroidPerf. | 846 # easy to make these class methods on AndroidPerf. |
| 828 if not self._profiler.check_configuration(): | 847 if not self._profiler.check_configuration(): |
| 829 self._profiler.print_setup_instructions() | 848 self._profiler.print_setup_instructions() |
| 830 sys.exit(1) | 849 sys.exit(1) |
| 831 else: | 850 else: |
| 832 self._profiler = None | 851 self._profiler = None |
| 833 | 852 |
| 834 def __del__(self): | 853 def __del__(self): |
| (...skipping 23 matching lines...) Expand all Loading... |
| 858 fs = self._port.host.filesystem | 877 fs = self._port.host.filesystem |
| 859 | 878 |
| 860 if 'ANDROID_SYMFS' in env: | 879 if 'ANDROID_SYMFS' in env: |
| 861 symfs_path = env['ANDROID_SYMFS'] | 880 symfs_path = env['ANDROID_SYMFS'] |
| 862 else: | 881 else: |
| 863 symfs_path = fs.join(self._port.results_directory(), 'symfs') | 882 symfs_path = fs.join(self._port.results_directory(), 'symfs') |
| 864 _log.debug("ANDROID_SYMFS not set, using %s" % symfs_path) | 883 _log.debug("ANDROID_SYMFS not set, using %s" % symfs_path) |
| 865 | 884 |
| 866 # find the installed path, and the path of the symboled built library | 885 # find the installed path, and the path of the symboled built library |
| 867 # FIXME: We should get the install path from the device! | 886 # FIXME: We should get the install path from the device! |
| 868 symfs_library_path = fs.join(symfs_path, "data/app-lib/%s-1/%s" % (self.
_driver_details.package_name(), self._driver_details.library_name())) | 887 symfs_library_path = fs.join(symfs_path, "data/app-lib/%s-1/%s" % |
| 888 (self._driver_details.package_name(), self.
_driver_details.library_name())) |
| 869 built_library_path = self._port._build_path('lib', self._driver_details.
library_name()) | 889 built_library_path = self._port._build_path('lib', self._driver_details.
library_name()) |
| 870 assert(fs.exists(built_library_path)) | 890 assert (fs.exists(built_library_path)) |
| 871 | 891 |
| 872 # FIXME: Ideally we'd check the sha1's first and make a soft-link instea
d of copying (since we probably never care about windows). | 892 # FIXME: Ideally we'd check the sha1's first and make a soft-link instea
d of copying (since we probably never care about windows). |
| 873 _log.debug("Updating symfs library (%s) from built copy (%s)" % (symfs_l
ibrary_path, built_library_path)) | 893 _log.debug("Updating symfs library (%s) from built copy (%s)" % (symfs_l
ibrary_path, built_library_path)) |
| 874 fs.maybe_make_directory(fs.dirname(symfs_library_path)) | 894 fs.maybe_make_directory(fs.dirname(symfs_library_path)) |
| 875 fs.copyfile(built_library_path, symfs_library_path) | 895 fs.copyfile(built_library_path, symfs_library_path) |
| 876 | 896 |
| 877 return symfs_path | 897 return symfs_path |
| 878 | 898 |
| 879 def _setup_md5sum_and_push_data_if_needed(self, log_callback): | 899 def _setup_md5sum_and_push_data_if_needed(self, log_callback): |
| 880 self._md5sum_path = self._port.path_to_md5sum() | 900 self._md5sum_path = self._port.path_to_md5sum() |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 self._device_failed = True | 948 self._device_failed = True |
| 929 raise driver.DeviceFailure('[%s] %s' % (self._android_commands.get_seria
l(), message)) | 949 raise driver.DeviceFailure('[%s] %s' % (self._android_commands.get_seria
l(), message)) |
| 930 | 950 |
| 931 @staticmethod | 951 @staticmethod |
| 932 def _extract_hashes_from_md5sum_output(md5sum_output): | 952 def _extract_hashes_from_md5sum_output(md5sum_output): |
| 933 assert md5sum_output | 953 assert md5sum_output |
| 934 return [line.split(' ')[0] for line in md5sum_output] | 954 return [line.split(' ')[0] for line in md5sum_output] |
| 935 | 955 |
| 936 def _files_match(self, host_file, device_file): | 956 def _files_match(self, host_file, device_file): |
| 937 assert self._port.host.filesystem.exists(host_file) | 957 assert self._port.host.filesystem.exists(host_file) |
| 938 device_hashes = self._extract_hashes_from_md5sum_output( | 958 device_hashes = self._extract_hashes_from_md5sum_output(self._port.host.
executive.popen(self._android_commands.adb_command() + |
| 939 self._port.host.executive.popen(self._android_commands.adb_comma
nd() + ['shell', MD5SUM_DEVICE_PATH, device_file], | 959
['shell', MD5SUM_DEVICE_PATH, device_file], |
| 940 stdout=subprocess.PIPE).stdout) | 960
stdout=subprocess.PIPE).stdout) |
| 941 host_hashes = self._extract_hashes_from_md5sum_output( | 961 host_hashes = self._extract_hashes_from_md5sum_output(self._port.host.ex
ecutive.popen(args=['%s_host' % self._md5sum_path, |
| 942 self._port.host.executive.popen(args=['%s_host' % self._md5sum_p
ath, host_file], | 962
host_file], |
| 943 stdout=subprocess.PIPE).stdout) | 963
stdout=subprocess.PIPE).stdout) |
| 944 return host_hashes and device_hashes == host_hashes | 964 return host_hashes and device_hashes == host_hashes |
| 945 | 965 |
| 946 def _push_file_if_needed(self, host_file, device_file, log_callback): | 966 def _push_file_if_needed(self, host_file, device_file, log_callback): |
| 947 basename = self._port.host.filesystem.basename(host_file) | 967 basename = self._port.host.filesystem.basename(host_file) |
| 948 log_callback("checking %s" % basename) | 968 log_callback("checking %s" % basename) |
| 949 if not self._files_match(host_file, device_file): | 969 if not self._files_match(host_file, device_file): |
| 950 log_callback("pushing %s" % basename) | 970 log_callback("pushing %s" % basename) |
| 951 self._android_commands.push(host_file, device_file) | 971 self._android_commands.push(host_file, device_file) |
| 952 | 972 |
| 953 def _push_executable(self, log_callback): | 973 def _push_executable(self, log_callback): |
| 954 self._push_file_if_needed(self._port.path_to_forwarder(), self._driver_d
etails.device_forwarder_path(), log_callback) | 974 self._push_file_if_needed(self._port.path_to_forwarder(), self._driver_d
etails.device_forwarder_path(), log_callback) |
| 955 for resource in self._driver_details.additional_resources(): | 975 for resource in self._driver_details.additional_resources(): |
| 956 self._push_file_if_needed(self._port._build_path(resource), self._dr
iver_details.device_directory() + resource, log_callback) | 976 self._push_file_if_needed( |
| 977 self._port._build_path(resource), self._driver_details.device_di
rectory() + resource, log_callback) |
| 957 | 978 |
| 958 self._push_file_if_needed(self._port._build_path('android_main_fonts.xml
'), self._driver_details.device_directory() + 'android_main_fonts.xml', log_call
back) | 979 self._push_file_if_needed( |
| 959 self._push_file_if_needed(self._port._build_path('android_fallback_fonts
.xml'), self._driver_details.device_directory() + 'android_fallback_fonts.xml',
log_callback) | 980 self._port._build_path('android_main_fonts.xml'), self._driver_detai
ls.device_directory() + 'android_main_fonts.xml', |
| 981 log_callback) |
| 982 self._push_file_if_needed( |
| 983 self._port._build_path('android_fallback_fonts.xml'), |
| 984 self._driver_details.device_directory() + 'android_fallback_fonts.xm
l', log_callback) |
| 960 | 985 |
| 961 log_callback("checking apk") | 986 log_callback("checking apk") |
| 962 if self._files_match(self._port._build_path('apks', 'ContentShell.apk'), | 987 if self._files_match(self._port._build_path('apks', 'ContentShell.apk'),
'/data/app/org.chromium.content_shell_apk-1.apk'): |
| 963 '/data/app/org.chromium.content_shell_apk-1.apk'): | |
| 964 return | 988 return |
| 965 | 989 |
| 966 log_callback("uninstalling apk") | 990 log_callback("uninstalling apk") |
| 967 self._android_commands.run(['uninstall', self._driver_details.package_na
me()]) | 991 self._android_commands.run(['uninstall', self._driver_details.package_na
me()]) |
| 968 driver_host_path = self._port._path_to_driver() | 992 driver_host_path = self._port._path_to_driver() |
| 969 log_callback("installing apk") | 993 log_callback("installing apk") |
| 970 install_result = self._android_commands.run(['install', driver_host_path
]) | 994 install_result = self._android_commands.run(['install', driver_host_path
]) |
| 971 if install_result.find('Success') == -1: | 995 if install_result.find('Success') == -1: |
| 972 self._abort('Failed to install %s onto device: %s' % (driver_host_pa
th, install_result)) | 996 self._abort('Failed to install %s onto device: %s' % (driver_host_pa
th, install_result)) |
| 973 | 997 |
| 974 def _push_fonts(self, log_callback): | 998 def _push_fonts(self, log_callback): |
| 975 path_to_ahem_font = self._port._build_path('AHEM____.TTF') | 999 path_to_ahem_font = self._port._build_path('AHEM____.TTF') |
| 976 self._push_file_if_needed(path_to_ahem_font, self._driver_details.device
_fonts_directory() + 'AHEM____.TTF', log_callback) | 1000 self._push_file_if_needed(path_to_ahem_font, self._driver_details.device
_fonts_directory() + 'AHEM____.TTF', log_callback) |
| 977 for (host_dirs, font_file, package) in HOST_FONT_FILES: | 1001 for (host_dirs, font_file, package) in HOST_FONT_FILES: |
| 978 for host_dir in host_dirs: | 1002 for host_dir in host_dirs: |
| 979 host_font_path = host_dir + font_file | 1003 host_font_path = host_dir + font_file |
| 980 if self._port._check_file_exists(host_font_path, '', logging=Fal
se): | 1004 if self._port._check_file_exists(host_font_path, '', logging=Fal
se): |
| 981 self._push_file_if_needed(host_font_path, self._driver_detai
ls.device_fonts_directory() + font_file, log_callback) | 1005 self._push_file_if_needed(host_font_path, self._driver_detai
ls.device_fonts_directory() + font_file, |
| 1006 log_callback) |
| 982 | 1007 |
| 983 def _push_test_resources(self, log_callback): | 1008 def _push_test_resources(self, log_callback): |
| 984 for resource in TEST_RESOURCES_TO_PUSH: | 1009 for resource in TEST_RESOURCES_TO_PUSH: |
| 985 self._push_file_if_needed(self._port.layout_tests_dir() + '/' + reso
urce, DEVICE_LAYOUT_TESTS_DIR + resource, log_callback) | 1010 self._push_file_if_needed(self._port.layout_tests_dir() + '/' + reso
urce, DEVICE_LAYOUT_TESTS_DIR + resource, |
| 1011 log_callback) |
| 986 | 1012 |
| 987 def _get_last_stacktrace(self): | 1013 def _get_last_stacktrace(self): |
| 988 tombstones = self._android_commands.run(['shell', 'ls', '-n', '/data/tom
bstones/tombstone_*']) | 1014 tombstones = self._android_commands.run(['shell', 'ls', '-n', '/data/tom
bstones/tombstone_*']) |
| 989 if not tombstones or tombstones.startswith('/data/tombstones/tombstone_*
: No such file or directory'): | 1015 if not tombstones or tombstones.startswith('/data/tombstones/tombstone_*
: No such file or directory'): |
| 990 self._log_error('The driver crashed, but no tombstone found!') | 1016 self._log_error('The driver crashed, but no tombstone found!') |
| 991 return '' | 1017 return '' |
| 992 | 1018 |
| 993 if tombstones.startswith('/data/tombstones/tombstone_*: Permission denie
d'): | 1019 if tombstones.startswith('/data/tombstones/tombstone_*: Permission denie
d'): |
| 994 # FIXME: crbug.com/321489 ... figure out why this happens. | 1020 # FIXME: crbug.com/321489 ... figure out why this happens. |
| 995 self._log_error('The driver crashed, but we could not read the tombs
tones!') | 1021 self._log_error('The driver crashed, but we could not read the tombs
tones!') |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1043 if not stdout: | 1069 if not stdout: |
| 1044 stdout = '' | 1070 stdout = '' |
| 1045 stdout += '********* [%s] Logcat:\n%s' % (self._android_commands.get_ser
ial(), self._get_logcat()) | 1071 stdout += '********* [%s] Logcat:\n%s' % (self._android_commands.get_ser
ial(), self._get_logcat()) |
| 1046 if not stderr: | 1072 if not stderr: |
| 1047 stderr = '' | 1073 stderr = '' |
| 1048 stderr += '********* [%s] Tombstone file:\n%s' % (self._android_commands
.get_serial(), self._get_last_stacktrace()) | 1074 stderr += '********* [%s] Tombstone file:\n%s' % (self._android_commands
.get_serial(), self._get_last_stacktrace()) |
| 1049 | 1075 |
| 1050 if not self._port.get_option('disable_breakpad'): | 1076 if not self._port.get_option('disable_breakpad'): |
| 1051 crashes = self._pull_crash_dumps_from_device() | 1077 crashes = self._pull_crash_dumps_from_device() |
| 1052 for crash in crashes: | 1078 for crash in crashes: |
| 1053 stderr += '********* [%s] breakpad minidump %s:\n%s' % (self._po
rt.host.filesystem.basename(crash), self._android_commands.get_serial(), self._p
ort._dump_reader._get_stack_from_dump(crash)) | 1079 stderr += '********* [%s] breakpad minidump %s:\n%s' % (self._po
rt.host.filesystem.basename(crash), |
| 1080 self._an
droid_commands.get_serial(), |
| 1081 self._po
rt._dump_reader._get_stack_from_dump(crash)) |
| 1054 | 1082 |
| 1055 # The parent method expects stdout and stderr to be byte streams, but | 1083 # The parent method expects stdout and stderr to be byte streams, but |
| 1056 # since adb shell does newline conversion, we used universal_newlines | 1084 # since adb shell does newline conversion, we used universal_newlines |
| 1057 # when launching the processes, and hence our stdout and stderr are | 1085 # when launching the processes, and hence our stdout and stderr are |
| 1058 # text objects that need to be encoded back into bytes. | 1086 # text objects that need to be encoded back into bytes. |
| 1059 return super(ChromiumAndroidDriver, self)._get_crash_log( | 1087 return super(ChromiumAndroidDriver, self)._get_crash_log( |
| 1060 stdout.encode('utf8', 'replace'), | 1088 stdout.encode('utf8', 'replace'), stderr.encode('utf8', 'replace'),
newer_than) |
| 1061 stderr.encode('utf8', 'replace'), | |
| 1062 newer_than) | |
| 1063 | 1089 |
| 1064 def cmd_line(self, pixel_tests, per_test_args): | 1090 def cmd_line(self, pixel_tests, per_test_args): |
| 1065 # The returned command line is used to start _server_process. In our cas
e, it's an interactive 'adb shell'. | 1091 # The returned command line is used to start _server_process. In our cas
e, it's an interactive 'adb shell'. |
| 1066 # The command line passed to the driver process is returned by _driver_c
md_line() instead. | 1092 # The command line passed to the driver process is returned by _driver_c
md_line() instead. |
| 1067 return self._android_commands.adb_command() + ['shell'] | 1093 return self._android_commands.adb_command() + ['shell'] |
| 1068 | 1094 |
| 1069 def _android_driver_cmd_line(self, pixel_tests, per_test_args): | 1095 def _android_driver_cmd_line(self, pixel_tests, per_test_args): |
| 1070 return driver.Driver.cmd_line(self, pixel_tests, per_test_args) | 1096 return driver.Driver.cmd_line(self, pixel_tests, per_test_args) |
| 1071 | 1097 |
| 1072 @staticmethod | 1098 @staticmethod |
| 1073 def _loop_with_timeout(condition, timeout_secs): | 1099 def _loop_with_timeout(condition, timeout_secs): |
| 1074 deadline = time.time() + timeout_secs | 1100 deadline = time.time() + timeout_secs |
| 1075 while time.time() < deadline: | 1101 while time.time() < deadline: |
| 1076 if condition(): | 1102 if condition(): |
| 1077 return True | 1103 return True |
| 1078 return False | 1104 return False |
| 1079 | 1105 |
| 1080 def _all_pipes_created(self): | 1106 def _all_pipes_created(self): |
| 1081 return (self._android_commands.file_exists(self._in_fifo_path) and | 1107 return (self._android_commands.file_exists(self._in_fifo_path) and |
| 1082 self._android_commands.file_exists(self._out_fifo_path) and | 1108 self._android_commands.file_exists(self._out_fifo_path) and self
._android_commands.file_exists(self._err_fifo_path)) |
| 1083 self._android_commands.file_exists(self._err_fifo_path)) | |
| 1084 | 1109 |
| 1085 def _remove_all_pipes(self): | 1110 def _remove_all_pipes(self): |
| 1086 for file in [self._in_fifo_path, self._out_fifo_path, self._err_fifo_pat
h]: | 1111 for file in [self._in_fifo_path, self._out_fifo_path, self._err_fifo_pat
h]: |
| 1087 self._android_commands.run(['shell', 'rm', file]) | 1112 self._android_commands.run(['shell', 'rm', file]) |
| 1088 | 1113 |
| 1089 return (not self._android_commands.file_exists(self._in_fifo_path) and | 1114 return (not self._android_commands.file_exists(self._in_fifo_path) and |
| 1090 not self._android_commands.file_exists(self._out_fifo_path) and | 1115 not self._android_commands.file_exists(self._out_fifo_path) and |
| 1091 not self._android_commands.file_exists(self._err_fifo_path)) | 1116 not self._android_commands.file_exists(self._err_fifo_path)) |
| 1092 | 1117 |
| 1093 def start(self, pixel_tests, per_test_args, deadline): | 1118 def start(self, pixel_tests, per_test_args, deadline): |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1119 self._log_error('Failed to start the content_shell application. Retr
ies=%d. Log:%s' % (retries, self._get_logcat())) | 1144 self._log_error('Failed to start the content_shell application. Retr
ies=%d. Log:%s' % (retries, self._get_logcat())) |
| 1120 self.stop() | 1145 self.stop() |
| 1121 time.sleep(2) | 1146 time.sleep(2) |
| 1122 self._abort('Failed to start the content_shell application multiple time
s. Giving up.') | 1147 self._abort('Failed to start the content_shell application multiple time
s. Giving up.') |
| 1123 | 1148 |
| 1124 def _start_once(self, pixel_tests, per_test_args): | 1149 def _start_once(self, pixel_tests, per_test_args): |
| 1125 super(ChromiumAndroidDriver, self)._start(pixel_tests, per_test_args, wa
it_for_ready=False) | 1150 super(ChromiumAndroidDriver, self)._start(pixel_tests, per_test_args, wa
it_for_ready=False) |
| 1126 | 1151 |
| 1127 self._log_debug('Starting forwarder') | 1152 self._log_debug('Starting forwarder') |
| 1128 self._forwarder_process = self._port._server_process_constructor( | 1153 self._forwarder_process = self._port._server_process_constructor( |
| 1129 self._port, 'Forwarder', self._android_commands.adb_command() + ['sh
ell', '%s -no-spawn-daemon %s' % (self._driver_details.device_forwarder_path(),
FORWARD_PORTS)]) | 1154 self._port, 'Forwarder', |
| 1155 self._android_commands.adb_command() + ['shell', '%s -no-spawn-daemo
n %s' % |
| 1156 (self._driver_details.device
_forwarder_path(), FORWARD_PORTS)]) |
| 1130 self._forwarder_process.start() | 1157 self._forwarder_process.start() |
| 1131 | 1158 |
| 1132 deadline = time.time() + DRIVER_START_STOP_TIMEOUT_SECS | 1159 deadline = time.time() + DRIVER_START_STOP_TIMEOUT_SECS |
| 1133 if not self._wait_for_server_process_output(self._forwarder_process, dea
dline, 'Forwarding device port'): | 1160 if not self._wait_for_server_process_output(self._forwarder_process, dea
dline, 'Forwarding device port'): |
| 1134 return False | 1161 return False |
| 1135 | 1162 |
| 1136 self._android_commands.run(['logcat', '-c']) | 1163 self._android_commands.run(['logcat', '-c']) |
| 1137 | 1164 |
| 1138 cmd_line_file_path = self._driver_details.command_line_file() | 1165 cmd_line_file_path = self._driver_details.command_line_file() |
| 1139 original_cmd_line_file_path = cmd_line_file_path + '.orig' | 1166 original_cmd_line_file_path = cmd_line_file_path + '.orig' |
| 1140 if self._android_commands.file_exists(cmd_line_file_path) and not self._
android_commands.file_exists(original_cmd_line_file_path): | 1167 if self._android_commands.file_exists(cmd_line_file_path) and not self._
android_commands.file_exists( |
| 1168 original_cmd_line_file_path): |
| 1141 # We check for both the normal path and the backup because we do not
want to step | 1169 # We check for both the normal path and the backup because we do not
want to step |
| 1142 # on the backup. Otherwise, we'd clobber the backup whenever we chan
ged the | 1170 # on the backup. Otherwise, we'd clobber the backup whenever we chan
ged the |
| 1143 # command line during the run. | 1171 # command line during the run. |
| 1144 self._android_commands.run(['shell', 'mv', cmd_line_file_path, origi
nal_cmd_line_file_path]) | 1172 self._android_commands.run(['shell', 'mv', cmd_line_file_path, origi
nal_cmd_line_file_path]) |
| 1145 | 1173 |
| 1146 self._android_commands.run(['shell', 'echo'] + self._android_driver_cmd_
line(pixel_tests, per_test_args) + ['>', self._driver_details.command_line_file(
)]) | 1174 self._android_commands.run(['shell', 'echo'] + self._android_driver_cmd_
line(pixel_tests, per_test_args) + |
| 1175 ['>', self._driver_details.command_line_file(
)]) |
| 1147 self._created_cmd_line = True | 1176 self._created_cmd_line = True |
| 1148 | 1177 |
| 1149 self._android_commands.run(['shell', 'rm', '-rf', self._driver_details.d
evice_crash_dumps_directory()]) | 1178 self._android_commands.run(['shell', 'rm', '-rf', self._driver_details.d
evice_crash_dumps_directory()]) |
| 1150 self._android_commands.mkdir(self._driver_details.device_crash_dumps_dir
ectory(), chmod='777') | 1179 self._android_commands.mkdir(self._driver_details.device_crash_dumps_dir
ectory(), chmod='777') |
| 1151 | 1180 |
| 1152 start_result = self._android_commands.run(['shell', 'am', 'start', '-e',
'RunInSubThread', '-n', self._driver_details.activity_name()]) | 1181 start_result = self._android_commands.run(['shell', 'am', 'start', '-e',
'RunInSubThread', '-n', |
| 1182 self._driver_details.activity
_name()]) |
| 1153 if start_result.find('Exception') != -1: | 1183 if start_result.find('Exception') != -1: |
| 1154 self._log_error('Failed to start the content_shell application. Exce
ption:\n' + start_result) | 1184 self._log_error('Failed to start the content_shell application. Exce
ption:\n' + start_result) |
| 1155 return False | 1185 return False |
| 1156 | 1186 |
| 1157 if not ChromiumAndroidDriver._loop_with_timeout(self._all_pipes_created,
DRIVER_START_STOP_TIMEOUT_SECS): | 1187 if not ChromiumAndroidDriver._loop_with_timeout(self._all_pipes_created,
DRIVER_START_STOP_TIMEOUT_SECS): |
| 1158 return False | 1188 return False |
| 1159 | 1189 |
| 1160 # Read back the shell prompt to ensure adb shell ready. | 1190 # Read back the shell prompt to ensure adb shell ready. |
| 1161 deadline = time.time() + DRIVER_START_STOP_TIMEOUT_SECS | 1191 deadline = time.time() + DRIVER_START_STOP_TIMEOUT_SECS |
| 1162 self._server_process.start() | 1192 self._server_process.start() |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1186 # If normal_startup_event is not set in time, the main thread mu
st be blocked at | 1216 # If normal_startup_event is not set in time, the main thread mu
st be blocked at |
| 1187 # reading/writing the fifo. Kill the fifo reading/writing proces
ses to let the | 1217 # reading/writing the fifo. Kill the fifo reading/writing proces
ses to let the |
| 1188 # main thread escape from the deadlocked state. After that, the
main thread will | 1218 # main thread escape from the deadlocked state. After that, the
main thread will |
| 1189 # treat this as a crash. | 1219 # treat this as a crash. |
| 1190 self._log_error('Deadlock detected. Processes killed.') | 1220 self._log_error('Deadlock detected. Processes killed.') |
| 1191 for i in processes: | 1221 for i in processes: |
| 1192 i.kill() | 1222 i.kill() |
| 1193 | 1223 |
| 1194 # Start a thread to kill the pipe reading/writing processes on deadlock
of the fifos during startup. | 1224 # Start a thread to kill the pipe reading/writing processes on deadlock
of the fifos during startup. |
| 1195 normal_startup_event = threading.Event() | 1225 normal_startup_event = threading.Event() |
| 1196 threading.Thread(name='DeadlockDetector', target=deadlock_detector, | 1226 threading.Thread( |
| 1197 args=([self._server_process, self._read_stdout_process,
self._read_stderr_process], normal_startup_event)).start() | 1227 name='DeadlockDetector', |
| 1228 target=deadlock_detector, |
| 1229 args=([self._server_process, self._read_stdout_process, self._read_s
tderr_process], normal_startup_event)).start() |
| 1198 | 1230 |
| 1199 # The test driver might crash during startup or when the deadlock detect
or hits | 1231 # The test driver might crash during startup or when the deadlock detect
or hits |
| 1200 # a deadlock and kills the fifo reading/writing processes. | 1232 # a deadlock and kills the fifo reading/writing processes. |
| 1201 if not self._wait_for_server_process_output(self._server_process, deadli
ne, '#READY'): | 1233 if not self._wait_for_server_process_output(self._server_process, deadli
ne, '#READY'): |
| 1202 return False | 1234 return False |
| 1203 | 1235 |
| 1204 # Inform the deadlock detector that the startup is successful without de
adlock. | 1236 # Inform the deadlock detector that the startup is successful without de
adlock. |
| 1205 normal_startup_event.set() | 1237 normal_startup_event.set() |
| 1206 self._log_debug("content_shell is ready") | 1238 self._log_debug("content_shell is ready") |
| 1207 return True | 1239 return True |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1287 return command | 1319 return command |
| 1288 | 1320 |
| 1289 def _read_prompt(self, deadline): | 1321 def _read_prompt(self, deadline): |
| 1290 last_char = '' | 1322 last_char = '' |
| 1291 while True: | 1323 while True: |
| 1292 current_char = self._server_process.read_stdout(deadline, 1) | 1324 current_char = self._server_process.read_stdout(deadline, 1) |
| 1293 if current_char == ' ': | 1325 if current_char == ' ': |
| 1294 if last_char in ('#', '$'): | 1326 if last_char in ('#', '$'): |
| 1295 return | 1327 return |
| 1296 last_char = current_char | 1328 last_char = current_char |
| OLD | NEW |