| OLD | NEW |
| 1 # Copyright (C) 2010 Google Inc. All rights reserved. | 1 # Copyright (C) 2010 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 Google name nor the names of its | 13 # * Neither the Google name 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 | |
| 29 """Abstract base class of Port-specific entry points for the layout tests | 28 """Abstract base class of Port-specific entry points for the layout tests |
| 30 test infrastructure (the Port and Driver classes).""" | 29 test infrastructure (the Port and Driver classes).""" |
| 31 | 30 |
| 32 import cgi | 31 import cgi |
| 33 import difflib | 32 import difflib |
| 34 import errno | 33 import errno |
| 35 import itertools | 34 import itertools |
| 36 import json | 35 import json |
| 37 import logging | 36 import logging |
| 38 import os | 37 import os |
| 39 import operator | 38 import operator |
| 40 import optparse | 39 import optparse |
| 41 import re | 40 import re |
| 42 import sys | 41 import sys |
| 43 | 42 |
| 44 try: | 43 try: |
| 45 from collections import OrderedDict | 44 from collections import OrderedDict |
| 46 except ImportError: | 45 except ImportError: |
| 47 # Needed for Python < 2.7 | 46 # Needed for Python < 2.7 |
| 48 from webkitpy.thirdparty.ordered_dict import OrderedDict | 47 from webkitpy.thirdparty.ordered_dict import OrderedDict |
| 49 | 48 |
| 50 | |
| 51 from webkitpy.common import find_files | 49 from webkitpy.common import find_files |
| 52 from webkitpy.common import read_checksum_from_png | 50 from webkitpy.common import read_checksum_from_png |
| 53 from webkitpy.common.memoized import memoized | 51 from webkitpy.common.memoized import memoized |
| 54 from webkitpy.common.system import path | 52 from webkitpy.common.system import path |
| 55 from webkitpy.common.system.executive import ScriptError | 53 from webkitpy.common.system.executive import ScriptError |
| 56 from webkitpy.common.system.path import cygpath | 54 from webkitpy.common.system.path import cygpath |
| 57 from webkitpy.common.system.systemhost import SystemHost | 55 from webkitpy.common.system.systemhost import SystemHost |
| 58 from webkitpy.common.webkit_finder import WebKitFinder | 56 from webkitpy.common.webkit_finder import WebKitFinder |
| 59 from webkitpy.layout_tests.layout_package.bot_test_expectations import BotTestEx
pectationsFactory | 57 from webkitpy.layout_tests.layout_package.bot_test_expectations import BotTestEx
pectationsFactory |
| 60 from webkitpy.layout_tests.models import test_run_results | 58 from webkitpy.layout_tests.models import test_run_results |
| (...skipping 29 matching lines...) Expand all Loading... |
| 90 | 88 |
| 91 # True if the port as aac and mp3 codecs built in. | 89 # True if the port as aac and mp3 codecs built in. |
| 92 PORT_HAS_AUDIO_CODECS_BUILT_IN = False | 90 PORT_HAS_AUDIO_CODECS_BUILT_IN = False |
| 93 | 91 |
| 94 ALL_SYSTEMS = ( | 92 ALL_SYSTEMS = ( |
| 95 | 93 |
| 96 # FIXME: We treat Retina (High-DPI) devices as if they are running | 94 # FIXME: We treat Retina (High-DPI) devices as if they are running |
| 97 # a different operating system version. This isn't accurate, but will wo
rk until | 95 # a different operating system version. This isn't accurate, but will wo
rk until |
| 98 # we need to test and support baselines across multiple O/S versions. | 96 # we need to test and support baselines across multiple O/S versions. |
| 99 ('retina', 'x86'), | 97 ('retina', 'x86'), |
| 100 | |
| 101 ('mac10.9', 'x86'), | 98 ('mac10.9', 'x86'), |
| 102 ('mac10.10', 'x86'), | 99 ('mac10.10', 'x86'), |
| 103 ('mac10.11', 'x86'), | 100 ('mac10.11', 'x86'), |
| 104 ('win7', 'x86'), | 101 ('win7', 'x86'), |
| 105 ('win10', 'x86'), | 102 ('win10', 'x86'), |
| 106 ('precise', 'x86_64'), | 103 ('precise', 'x86_64'), |
| 107 ('trusty', 'x86_64'), | 104 ('trusty', 'x86_64'), |
| 108 # FIXME: Technically this should be 'arm', but adding a third architectu
re type breaks TestConfigurationConverter. | 105 # FIXME: Technically this should be 'arm', but adding a third architectu
re type breaks TestConfigurationConverter. |
| 109 # If we need this to be 'arm' in the future, then we first have to fix T
estConfigurationConverter. | 106 # If we need this to be 'arm' in the future, then we first have to fix T
estConfigurationConverter. |
| 110 ('icecreamsandwich', 'x86'), | 107 ('icecreamsandwich', 'x86'), ) |
| 111 ) | |
| 112 | 108 |
| 113 CONFIGURATION_SPECIFIER_MACROS = { | 109 CONFIGURATION_SPECIFIER_MACROS = { |
| 114 'mac': ['retina', 'mac10.9', 'mac10.10', 'mac10.11'], | 110 'mac': ['retina', 'mac10.9', 'mac10.10', 'mac10.11'], |
| 115 'win': ['win7', 'win10'], | 111 'win': ['win7', 'win10'], |
| 116 'linux': ['precise', 'trusty'], | 112 'linux': ['precise', 'trusty'], |
| 117 'android': ['icecreamsandwich'], | 113 'android': ['icecreamsandwich'], |
| 118 } | 114 } |
| 119 | 115 |
| 120 DEFAULT_BUILD_DIRECTORIES = ('out',) | 116 DEFAULT_BUILD_DIRECTORIES = ('out', ) |
| 121 | 117 |
| 122 # overridden in subclasses. | 118 # overridden in subclasses. |
| 123 FALLBACK_PATHS = {} | 119 FALLBACK_PATHS = {} |
| 124 | 120 |
| 125 SUPPORTED_VERSIONS = [] | 121 SUPPORTED_VERSIONS = [] |
| 126 | 122 |
| 127 # URL to the build requirements page. | 123 # URL to the build requirements page. |
| 128 BUILD_REQUIREMENTS_URL = '' | 124 BUILD_REQUIREMENTS_URL = '' |
| 129 | 125 |
| 130 @classmethod | 126 @classmethod |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 if not hasattr(options, 'configuration') or not options.configuration: | 206 if not hasattr(options, 'configuration') or not options.configuration: |
| 211 self.set_option_default('configuration', self.default_configuration(
)) | 207 self.set_option_default('configuration', self.default_configuration(
)) |
| 212 if not hasattr(options, 'target') or not options.target: | 208 if not hasattr(options, 'target') or not options.target: |
| 213 self.set_option_default('target', self._options.configuration) | 209 self.set_option_default('target', self._options.configuration) |
| 214 self._test_configuration = None | 210 self._test_configuration = None |
| 215 self._reftest_list = {} | 211 self._reftest_list = {} |
| 216 self._results_directory = None | 212 self._results_directory = None |
| 217 self._virtual_test_suites = None | 213 self._virtual_test_suites = None |
| 218 | 214 |
| 219 def __str__(self): | 215 def __str__(self): |
| 220 return "Port{name=%s, version=%s, architecture=%s, test_configuration=%s
}" % (self._name, self._version, self._architecture, self._test_configuration) | 216 return "Port{name=%s, version=%s, architecture=%s, test_configuration=%s
}" % (self._name, self._version, self._architecture, |
| 217
self._test_configuration) |
| 221 | 218 |
| 222 def buildbot_archives_baselines(self): | 219 def buildbot_archives_baselines(self): |
| 223 return True | 220 return True |
| 224 | 221 |
| 225 def additional_driver_flag(self): | 222 def additional_driver_flag(self): |
| 226 if self.driver_name() == self.CONTENT_SHELL_NAME: | 223 if self.driver_name() == self.CONTENT_SHELL_NAME: |
| 227 return ['--run-layout-test'] | 224 return ['--run-layout-test'] |
| 228 return [] | 225 return [] |
| 229 | 226 |
| 230 def supports_per_test_timeout(self): | 227 def supports_per_test_timeout(self): |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 return map(self._webkit_baseline_path, self.FALLBACK_PATHS[self.version(
)]) | 310 return map(self._webkit_baseline_path, self.FALLBACK_PATHS[self.version(
)]) |
| 314 | 311 |
| 315 @memoized | 312 @memoized |
| 316 def _compare_baseline(self): | 313 def _compare_baseline(self): |
| 317 factory = PortFactory(self.host) | 314 factory = PortFactory(self.host) |
| 318 target_port = self.get_option('compare_port') | 315 target_port = self.get_option('compare_port') |
| 319 if target_port: | 316 if target_port: |
| 320 return factory.get(target_port).default_baseline_search_path() | 317 return factory.get(target_port).default_baseline_search_path() |
| 321 return [] | 318 return [] |
| 322 | 319 |
| 323 def _check_file_exists(self, path_to_file, file_description, | 320 def _check_file_exists(self, path_to_file, file_description, override_step=N
one, logging=True): |
| 324 override_step=None, logging=True): | |
| 325 """Verify the file is present where expected or log an error. | 321 """Verify the file is present where expected or log an error. |
| 326 | 322 |
| 327 Args: | 323 Args: |
| 328 file_name: The (human friendly) name or description of the file | 324 file_name: The (human friendly) name or description of the file |
| 329 you're looking for (e.g., "HTTP Server"). Used for error logging
. | 325 you're looking for (e.g., "HTTP Server"). Used for error logging
. |
| 330 override_step: An optional string to be logged if the check fails. | 326 override_step: An optional string to be logged if the check fails. |
| 331 logging: Whether or not log the error messages.""" | 327 logging: Whether or not log the error messages.""" |
| 332 if not self._filesystem.exists(path_to_file): | 328 if not self._filesystem.exists(path_to_file): |
| 333 if logging: | 329 if logging: |
| 334 _log.error('Unable to find %s' % file_description) | 330 _log.error('Unable to find %s' % file_description) |
| 335 _log.error(' at %s' % path_to_file) | 331 _log.error(' at %s' % path_to_file) |
| 336 if override_step: | 332 if override_step: |
| 337 _log.error(' %s' % override_step) | 333 _log.error(' %s' % override_step) |
| 338 _log.error('') | 334 _log.error('') |
| 339 return False | 335 return False |
| 340 return True | 336 return True |
| 341 | 337 |
| 342 def check_build(self, needs_http, printer): | 338 def check_build(self, needs_http, printer): |
| 343 result = True | 339 result = True |
| 344 | 340 |
| 345 dump_render_tree_binary_path = self._path_to_driver() | 341 dump_render_tree_binary_path = self._path_to_driver() |
| 346 result = self._check_file_exists(dump_render_tree_binary_path, | 342 result = self._check_file_exists(dump_render_tree_binary_path, 'test dri
ver') and result |
| 347 'test driver') and result | |
| 348 if not result and self.get_option('build'): | 343 if not result and self.get_option('build'): |
| 349 result = self._check_driver_build_up_to_date( | 344 result = self._check_driver_build_up_to_date(self.get_option('config
uration')) |
| 350 self.get_option('configuration')) | |
| 351 else: | 345 else: |
| 352 _log.error('') | 346 _log.error('') |
| 353 | 347 |
| 354 helper_path = self._path_to_helper() | 348 helper_path = self._path_to_helper() |
| 355 if helper_path: | 349 if helper_path: |
| 356 result = self._check_file_exists(helper_path, | 350 result = self._check_file_exists(helper_path, 'layout test helper')
and result |
| 357 'layout test helper') and result | |
| 358 | 351 |
| 359 if self.get_option('pixel_tests'): | 352 if self.get_option('pixel_tests'): |
| 360 result = self.check_image_diff( | 353 result = self.check_image_diff('To override, invoke with --no-pixel-
tests') and result |
| 361 'To override, invoke with --no-pixel-tests') and result | |
| 362 | 354 |
| 363 # It's okay if pretty patch and wdiff aren't available, but we will at l
east log messages. | 355 # It's okay if pretty patch and wdiff aren't available, but we will at l
east log messages. |
| 364 self._pretty_patch_available = self.check_pretty_patch() | 356 self._pretty_patch_available = self.check_pretty_patch() |
| 365 self._wdiff_available = self.check_wdiff() | 357 self._wdiff_available = self.check_wdiff() |
| 366 | 358 |
| 367 if self._dump_reader: | 359 if self._dump_reader: |
| 368 result = self._dump_reader.check_is_functional() and result | 360 result = self._dump_reader.check_is_functional() and result |
| 369 | 361 |
| 370 if needs_http: | 362 if needs_http: |
| 371 result = self.check_httpd() and result | 363 result = self.check_httpd() and result |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 """Returns a string containing the diff of the two text strings | 524 """Returns a string containing the diff of the two text strings |
| 533 in 'unified diff' format.""" | 525 in 'unified diff' format.""" |
| 534 | 526 |
| 535 # The filenames show up in the diff output, make sure they're | 527 # The filenames show up in the diff output, make sure they're |
| 536 # raw bytes and not unicode, so that they don't trigger join() | 528 # raw bytes and not unicode, so that they don't trigger join() |
| 537 # trying to decode the input. | 529 # trying to decode the input. |
| 538 def to_raw_bytes(string_value): | 530 def to_raw_bytes(string_value): |
| 539 if isinstance(string_value, unicode): | 531 if isinstance(string_value, unicode): |
| 540 return string_value.encode('utf-8') | 532 return string_value.encode('utf-8') |
| 541 return string_value | 533 return string_value |
| 534 |
| 542 expected_filename = to_raw_bytes(expected_filename) | 535 expected_filename = to_raw_bytes(expected_filename) |
| 543 actual_filename = to_raw_bytes(actual_filename) | 536 actual_filename = to_raw_bytes(actual_filename) |
| 544 diff = difflib.unified_diff(expected_text.splitlines(True), | 537 diff = difflib.unified_diff( |
| 545 actual_text.splitlines(True), | 538 expected_text.splitlines(True), actual_text.splitlines(True), expect
ed_filename, actual_filename) |
| 546 expected_filename, | |
| 547 actual_filename) | |
| 548 | 539 |
| 549 # The diff generated by the difflib is incorrect if one of the files | 540 # The diff generated by the difflib is incorrect if one of the files |
| 550 # does not have a newline at the end of the file and it is present in | 541 # does not have a newline at the end of the file and it is present in |
| 551 # the diff. Relevant Python issue: http://bugs.python.org/issue2142 | 542 # the diff. Relevant Python issue: http://bugs.python.org/issue2142 |
| 552 def diff_fixup(diff): | 543 def diff_fixup(diff): |
| 553 for line in diff: | 544 for line in diff: |
| 554 yield line | 545 yield line |
| 555 if not line.endswith('\n'): | 546 if not line.endswith('\n'): |
| 556 yield '\n\ No newline at end of file\n' | 547 yield '\n\ No newline at end of file\n' |
| 557 | 548 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 for line in reftest_list_file.split('\n'): | 710 for line in reftest_list_file.split('\n'): |
| 720 line = re.sub('#.+$', '', line) | 711 line = re.sub('#.+$', '', line) |
| 721 split_line = line.split() | 712 split_line = line.split() |
| 722 if len(split_line) == 4: | 713 if len(split_line) == 4: |
| 723 # FIXME: Probably one of mozilla's extensions in the reftest.lis
t format. Do we need to support this? | 714 # FIXME: Probably one of mozilla's extensions in the reftest.lis
t format. Do we need to support this? |
| 724 _log.warning("unsupported reftest.list line '%s' in %s" % (line,
reftest_list_path)) | 715 _log.warning("unsupported reftest.list line '%s' in %s" % (line,
reftest_list_path)) |
| 725 continue | 716 continue |
| 726 if len(split_line) < 3: | 717 if len(split_line) < 3: |
| 727 continue | 718 continue |
| 728 expectation_type, test_file, ref_file = split_line | 719 expectation_type, test_file, ref_file = split_line |
| 729 parsed_list.setdefault(filesystem.join(test_dirpath, test_file), [])
.append((expectation_type, filesystem.join(test_dirpath, ref_file))) | 720 parsed_list.setdefault( |
| 721 filesystem.join(test_dirpath, test_file), []).append((expectatio
n_type, filesystem.join(test_dirpath, ref_file))) |
| 730 return parsed_list | 722 return parsed_list |
| 731 | 723 |
| 732 def reference_files(self, test_name): | 724 def reference_files(self, test_name): |
| 733 """Return a list of expectation (== or !=) and filename pairs""" | 725 """Return a list of expectation (== or !=) and filename pairs""" |
| 734 | 726 |
| 735 reftest_list = self._get_reftest_list(test_name) | 727 reftest_list = self._get_reftest_list(test_name) |
| 736 if not reftest_list: | 728 if not reftest_list: |
| 737 reftest_list = [] | 729 reftest_list = [] |
| 738 for expectation, prefix in (('==', ''), ('!=', '-mismatch')): | 730 for expectation, prefix in (('==', ''), ('!=', '-mismatch')): |
| 739 for extension in Port._supported_file_extensions: | 731 for extension in Port._supported_file_extensions: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 751 suites = self.virtual_test_suites() | 743 suites = self.virtual_test_suites() |
| 752 if paths: | 744 if paths: |
| 753 tests.extend(self._virtual_tests_matching_paths(paths, suites)) | 745 tests.extend(self._virtual_tests_matching_paths(paths, suites)) |
| 754 else: | 746 else: |
| 755 tests.extend(self._all_virtual_tests(suites)) | 747 tests.extend(self._all_virtual_tests(suites)) |
| 756 return tests | 748 return tests |
| 757 | 749 |
| 758 def _real_tests(self, paths): | 750 def _real_tests(self, paths): |
| 759 # When collecting test cases, skip these directories | 751 # When collecting test cases, skip these directories |
| 760 skipped_directories = set(['.svn', '_svn', 'platform', 'resources', 'sup
port', 'script-tests', 'reference', 'reftest']) | 752 skipped_directories = set(['.svn', '_svn', 'platform', 'resources', 'sup
port', 'script-tests', 'reference', 'reftest']) |
| 761 files = find_files.find(self._filesystem, self.layout_tests_dir(), paths
, skipped_directories, Port.is_test_file, self.test_key) | 753 files = find_files.find(self._filesystem, self.layout_tests_dir(), paths
, skipped_directories, Port.is_test_file, |
| 754 self.test_key) |
| 762 return [self.relative_test_filename(f) for f in files] | 755 return [self.relative_test_filename(f) for f in files] |
| 763 | 756 |
| 764 # When collecting test cases, we include any file with these extensions. | 757 # When collecting test cases, we include any file with these extensions. |
| 765 _supported_file_extensions = set(['.html', '.xml', '.xhtml', '.xht', '.pl', | 758 _supported_file_extensions = set(['.html', '.xml', '.xhtml', '.xht', '.pl',
'.htm', '.php', '.svg', '.mht', '.pdf']) |
| 766 '.htm', '.php', '.svg', '.mht', '.pdf']) | |
| 767 | 759 |
| 768 @staticmethod | 760 @staticmethod |
| 761 |
| 769 # If any changes are made here be sure to update the isUsedInReftest method
in old-run-webkit-tests as well. | 762 # If any changes are made here be sure to update the isUsedInReftest method
in old-run-webkit-tests as well. |
| 770 def is_reference_html_file(filesystem, dirname, filename): | 763 def is_reference_html_file(filesystem, dirname, filename): |
| 771 if filename.startswith('ref-') or filename.startswith('notref-'): | 764 if filename.startswith('ref-') or filename.startswith('notref-'): |
| 772 return True | 765 return True |
| 773 filename_wihout_ext, unused = filesystem.splitext(filename) | 766 filename_wihout_ext, unused = filesystem.splitext(filename) |
| 774 for suffix in ['-expected', '-expected-mismatch', '-ref', '-notref']: | 767 for suffix in ['-expected', '-expected-mismatch', '-ref', '-notref']: |
| 775 if filename_wihout_ext.endswith(suffix): | 768 if filename_wihout_ext.endswith(suffix): |
| 776 return True | 769 return True |
| 777 return False | 770 return False |
| 778 | 771 |
| 779 @staticmethod | 772 @staticmethod |
| 780 def _has_supported_extension(filesystem, filename): | 773 def _has_supported_extension(filesystem, filename): |
| 781 """Return true if filename is one of the file extensions we want to run
a test on.""" | 774 """Return true if filename is one of the file extensions we want to run
a test on.""" |
| 782 extension = filesystem.splitext(filename)[1] | 775 extension = filesystem.splitext(filename)[1] |
| 783 return extension in Port._supported_file_extensions | 776 return extension in Port._supported_file_extensions |
| 784 | 777 |
| 785 @staticmethod | 778 @staticmethod |
| 786 def is_test_file(filesystem, dirname, filename): | 779 def is_test_file(filesystem, dirname, filename): |
| 787 return Port._has_supported_extension(filesystem, filename) and not Port.
is_reference_html_file(filesystem, dirname, filename) | 780 return Port._has_supported_extension(filesystem, filename) and not Port.
is_reference_html_file(filesystem, dirname, |
| 781
filename) |
| 788 | 782 |
| 789 ALL_TEST_TYPES = ['audio', 'harness', 'pixel', 'ref', 'text', 'unknown'] | 783 ALL_TEST_TYPES = ['audio', 'harness', 'pixel', 'ref', 'text', 'unknown'] |
| 790 | 784 |
| 791 def test_type(self, test_name): | 785 def test_type(self, test_name): |
| 792 fs = self._filesystem | 786 fs = self._filesystem |
| 793 if fs.exists(self.expected_filename(test_name, '.png')): | 787 if fs.exists(self.expected_filename(test_name, '.png')): |
| 794 return 'pixel' | 788 return 'pixel' |
| 795 if fs.exists(self.expected_filename(test_name, '.wav')): | 789 if fs.exists(self.expected_filename(test_name, '.wav')): |
| 796 return 'audio' | 790 return 'audio' |
| 797 if self.reference_files(test_name): | 791 if self.reference_files(test_name): |
| (...skipping 18 matching lines...) Expand all Loading... |
| 816 dirname, basename = self.split_test(test_name) | 810 dirname, basename = self.split_test(test_name) |
| 817 return (self._natural_sort_key(dirname + self.TEST_PATH_SEPARATOR), self
._natural_sort_key(basename)) | 811 return (self._natural_sort_key(dirname + self.TEST_PATH_SEPARATOR), self
._natural_sort_key(basename)) |
| 818 | 812 |
| 819 def _natural_sort_key(self, string_to_split): | 813 def _natural_sort_key(self, string_to_split): |
| 820 """ Turns a string into a list of string and number chunks, i.e. "z23a"
-> ["z", 23, "a"] | 814 """ Turns a string into a list of string and number chunks, i.e. "z23a"
-> ["z", 23, "a"] |
| 821 | 815 |
| 822 This can be used to implement "natural sort" order. See: | 816 This can be used to implement "natural sort" order. See: |
| 823 http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort
-order.html | 817 http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort
-order.html |
| 824 http://nedbatchelder.com/blog/200712.html#e20071211T054956 | 818 http://nedbatchelder.com/blog/200712.html#e20071211T054956 |
| 825 """ | 819 """ |
| 820 |
| 826 def tryint(val): | 821 def tryint(val): |
| 827 try: | 822 try: |
| 828 return int(val) | 823 return int(val) |
| 829 except ValueError: | 824 except ValueError: |
| 830 return val | 825 return val |
| 831 | 826 |
| 832 return [tryint(chunk) for chunk in re.split('(\d+)', string_to_split)] | 827 return [tryint(chunk) for chunk in re.split('(\d+)', string_to_split)] |
| 833 | 828 |
| 834 def test_dirs(self): | 829 def test_dirs(self): |
| 835 """Returns the list of top-level test directories.""" | 830 """Returns the list of top-level test directories.""" |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1068 clean_env[name] = os.environ[name] | 1063 clean_env[name] = os.environ[name] |
| 1069 | 1064 |
| 1070 def setup_environ_for_server(self, server_name=None): | 1065 def setup_environ_for_server(self, server_name=None): |
| 1071 # We intentionally copy only a subset of os.environ when | 1066 # We intentionally copy only a subset of os.environ when |
| 1072 # launching subprocesses to ensure consistent test results. | 1067 # launching subprocesses to ensure consistent test results. |
| 1073 clean_env = { | 1068 clean_env = { |
| 1074 'LOCAL_RESOURCE_ROOT': self.layout_tests_dir(), # FIXME: Is this us
ed? | 1069 'LOCAL_RESOURCE_ROOT': self.layout_tests_dir(), # FIXME: Is this us
ed? |
| 1075 } | 1070 } |
| 1076 variables_to_copy = [ | 1071 variables_to_copy = [ |
| 1077 'WEBKIT_TESTFONTS', # FIXME: Is this still used? | 1072 'WEBKIT_TESTFONTS', # FIXME: Is this still used? |
| 1078 'WEBKITOUTPUTDIR', # FIXME: Is this still used? | 1073 'WEBKITOUTPUTDIR', # FIXME: Is this still used? |
| 1079 'CHROME_DEVEL_SANDBOX', | 1074 'CHROME_DEVEL_SANDBOX', |
| 1080 'CHROME_IPC_LOGGING', | 1075 'CHROME_IPC_LOGGING', |
| 1081 'ASAN_OPTIONS', | 1076 'ASAN_OPTIONS', |
| 1082 'TSAN_OPTIONS', | 1077 'TSAN_OPTIONS', |
| 1083 'MSAN_OPTIONS', | 1078 'MSAN_OPTIONS', |
| 1084 'LSAN_OPTIONS', | 1079 'LSAN_OPTIONS', |
| 1085 'UBSAN_OPTIONS', | 1080 'UBSAN_OPTIONS', |
| 1086 'VALGRIND_LIB', | 1081 'VALGRIND_LIB', |
| 1087 'VALGRIND_LIB_INNER', | 1082 'VALGRIND_LIB_INNER', |
| 1088 ] | 1083 ] |
| 1089 if self.host.platform.is_linux() or self.host.platform.is_freebsd(): | 1084 if self.host.platform.is_linux() or self.host.platform.is_freebsd(): |
| 1090 variables_to_copy += [ | 1085 variables_to_copy += ['XAUTHORITY', 'HOME', 'LANG', 'LD_LIBRARY_PATH
', 'DBUS_SESSION_BUS_ADDRESS', 'XDG_DATA_DIRS', ] |
| 1091 'XAUTHORITY', | |
| 1092 'HOME', | |
| 1093 'LANG', | |
| 1094 'LD_LIBRARY_PATH', | |
| 1095 'DBUS_SESSION_BUS_ADDRESS', | |
| 1096 'XDG_DATA_DIRS', | |
| 1097 ] | |
| 1098 clean_env['DISPLAY'] = self._value_or_default_from_environ('DISPLAY'
, ':1') | 1086 clean_env['DISPLAY'] = self._value_or_default_from_environ('DISPLAY'
, ':1') |
| 1099 if self.host.platform.is_mac(): | 1087 if self.host.platform.is_mac(): |
| 1100 clean_env['DYLD_LIBRARY_PATH'] = self._build_path() | 1088 clean_env['DYLD_LIBRARY_PATH'] = self._build_path() |
| 1101 variables_to_copy += [ | 1089 variables_to_copy += ['HOME', ] |
| 1102 'HOME', | |
| 1103 ] | |
| 1104 if self.host.platform.is_win(): | 1090 if self.host.platform.is_win(): |
| 1105 variables_to_copy += [ | 1091 variables_to_copy += [ |
| 1106 'PATH', | 1092 'PATH', |
| 1107 'GYP_DEFINES', # Required to locate win sdk. | 1093 'GYP_DEFINES', # Required to locate win sdk. |
| 1108 ] | 1094 ] |
| 1109 if self.host.platform.is_cygwin(): | 1095 if self.host.platform.is_cygwin(): |
| 1110 variables_to_copy += [ | 1096 variables_to_copy += ['HOMEDRIVE', 'HOMEPATH', '_NT_SYMBOL_PATH', ] |
| 1111 'HOMEDRIVE', | |
| 1112 'HOMEPATH', | |
| 1113 '_NT_SYMBOL_PATH', | |
| 1114 ] | |
| 1115 | 1097 |
| 1116 for variable in variables_to_copy: | 1098 for variable in variables_to_copy: |
| 1117 self._copy_value_from_environ_if_set(clean_env, variable) | 1099 self._copy_value_from_environ_if_set(clean_env, variable) |
| 1118 | 1100 |
| 1119 for string_variable in self.get_option('additional_env_var', []): | 1101 for string_variable in self.get_option('additional_env_var', []): |
| 1120 [name, value] = string_variable.split('=', 1) | 1102 [name, value] = string_variable.split('=', 1) |
| 1121 clean_env[name] = value | 1103 clean_env[name] = value |
| 1122 | 1104 |
| 1123 return clean_env | 1105 return clean_env |
| 1124 | 1106 |
| 1125 def show_results_html_file(self, results_filename): | 1107 def show_results_html_file(self, results_filename): |
| 1126 """This routine should display the HTML file pointed at by | 1108 """This routine should display the HTML file pointed at by |
| 1127 results_filename in a users' browser.""" | 1109 results_filename in a users' browser.""" |
| 1128 return self.host.user.open_url(path.abspath_to_uri(self.host.platform, r
esults_filename)) | 1110 return self.host.user.open_url(path.abspath_to_uri(self.host.platform, r
esults_filename)) |
| 1129 | 1111 |
| 1130 def create_driver(self, worker_number, no_timeout=False): | 1112 def create_driver(self, worker_number, no_timeout=False): |
| 1131 """Return a newly created Driver subclass for starting/stopping the test
driver.""" | 1113 """Return a newly created Driver subclass for starting/stopping the test
driver.""" |
| 1132 return self._driver_class()(self, worker_number, pixel_tests=self.get_op
tion('pixel_tests'), no_timeout=no_timeout) | 1114 return self._driver_class()(self, worker_number, pixel_tests=self.get_op
tion('pixel_tests'), no_timeout=no_timeout) |
| 1133 | 1115 |
| 1134 def start_helper(self): | 1116 def start_helper(self): |
| 1135 """If a port needs to reconfigure graphics settings or do other | 1117 """If a port needs to reconfigure graphics settings or do other |
| 1136 things to ensure a known test configuration, it should override this | 1118 things to ensure a known test configuration, it should override this |
| 1137 method.""" | 1119 method.""" |
| 1138 helper_path = self._path_to_helper() | 1120 helper_path = self._path_to_helper() |
| 1139 if helper_path: | 1121 if helper_path: |
| 1140 _log.debug("Starting layout helper %s" % helper_path) | 1122 _log.debug("Starting layout helper %s" % helper_path) |
| 1141 # Note: Not thread safe: http://bugs.python.org/issue2320 | 1123 # Note: Not thread safe: http://bugs.python.org/issue2320 |
| 1142 self._helper = self._executive.popen([helper_path], | 1124 self._helper = self._executive.popen([helper_path], |
| 1143 stdin=self._executive.PIPE, stdout=self._executive.PIPE, stderr=
None) | 1125 stdin=self._executive.PIPE, |
| 1126 stdout=self._executive.PIPE, |
| 1127 stderr=None) |
| 1144 is_ready = self._helper.stdout.readline() | 1128 is_ready = self._helper.stdout.readline() |
| 1145 if not is_ready.startswith('ready'): | 1129 if not is_ready.startswith('ready'): |
| 1146 _log.error("layout_test_helper failed to be ready") | 1130 _log.error("layout_test_helper failed to be ready") |
| 1147 | 1131 |
| 1148 def requires_http_server(self): | 1132 def requires_http_server(self): |
| 1149 """Does the port require an HTTP server for running tests? This could | 1133 """Does the port require an HTTP server for running tests? This could |
| 1150 be the case when the tests aren't run on the host platform.""" | 1134 be the case when the tests aren't run on the host platform.""" |
| 1151 return False | 1135 return False |
| 1152 | 1136 |
| 1153 def start_http_server(self, additional_dirs, number_of_drivers): | 1137 def start_http_server(self, additional_dirs, number_of_drivers): |
| 1154 """Start a web server. Raise an error if it can't start or is already ru
nning. | 1138 """Start a web server. Raise an error if it can't start or is already ru
nning. |
| 1155 | 1139 |
| 1156 Ports can stub this out if they don't need a web server to be running.""
" | 1140 Ports can stub this out if they don't need a web server to be running.""
" |
| 1157 assert not self._http_server, 'Already running an http server.' | 1141 assert not self._http_server, 'Already running an http server.' |
| 1158 | 1142 |
| 1159 server = apache_http.ApacheHTTP(self, self.results_directory(), | 1143 server = apache_http.ApacheHTTP(self, |
| 1144 self.results_directory(), |
| 1160 additional_dirs=additional_dirs, | 1145 additional_dirs=additional_dirs, |
| 1161 number_of_servers=(number_of_drivers * 4
)) | 1146 number_of_servers=(number_of_drivers * 4
)) |
| 1162 server.start() | 1147 server.start() |
| 1163 self._http_server = server | 1148 self._http_server = server |
| 1164 | 1149 |
| 1165 def start_websocket_server(self): | 1150 def start_websocket_server(self): |
| 1166 """Start a web server. Raise an error if it can't start or is already ru
nning. | 1151 """Start a web server. Raise an error if it can't start or is already ru
nning. |
| 1167 | 1152 |
| 1168 Ports can stub this out if they don't need a websocket server to be runn
ing.""" | 1153 Ports can stub this out if they don't need a websocket server to be runn
ing.""" |
| 1169 assert not self._websocket_server, 'Already running a websocket server.' | 1154 assert not self._websocket_server, 'Already running a websocket server.' |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1327 | 1312 |
| 1328 ignore_mode = self.get_option('ignore_flaky_tests') | 1313 ignore_mode = self.get_option('ignore_flaky_tests') |
| 1329 if ignore_mode == 'very-flaky' or ignore_mode == 'maybe-flaky': | 1314 if ignore_mode == 'very-flaky' or ignore_mode == 'maybe-flaky': |
| 1330 return expectations.flakes_by_path(ignore_mode == 'very-flaky') | 1315 return expectations.flakes_by_path(ignore_mode == 'very-flaky') |
| 1331 if ignore_mode == 'unexpected': | 1316 if ignore_mode == 'unexpected': |
| 1332 return expectations.unexpected_results_by_path() | 1317 return expectations.unexpected_results_by_path() |
| 1333 _log.warning("Unexpected ignore mode: '%s'." % ignore_mode) | 1318 _log.warning("Unexpected ignore mode: '%s'." % ignore_mode) |
| 1334 return {} | 1319 return {} |
| 1335 | 1320 |
| 1336 def expectations_files(self): | 1321 def expectations_files(self): |
| 1337 return ([self.path_to_generic_test_expectations_file()] + | 1322 return ([self.path_to_generic_test_expectations_file()] + self._port_spe
cific_expectations_files() + |
| 1338 self._port_specific_expectations_files() + | |
| 1339 self._flag_specific_expectations_files()) | 1323 self._flag_specific_expectations_files()) |
| 1340 | 1324 |
| 1341 def repository_path(self): | 1325 def repository_path(self): |
| 1342 """Returns the repository path for the chromium code base.""" | 1326 """Returns the repository path for the chromium code base.""" |
| 1343 return self.path_from_chromium_base('build') | 1327 return self.path_from_chromium_base('build') |
| 1344 | 1328 |
| 1345 _WDIFF_DEL = '##WDIFF_DEL##' | 1329 _WDIFF_DEL = '##WDIFF_DEL##' |
| 1346 _WDIFF_ADD = '##WDIFF_ADD##' | 1330 _WDIFF_ADD = '##WDIFF_ADD##' |
| 1347 _WDIFF_END = '##WDIFF_END##' | 1331 _WDIFF_END = '##WDIFF_END##' |
| 1348 | 1332 |
| 1349 def _format_wdiff_output_as_html(self, wdiff): | 1333 def _format_wdiff_output_as_html(self, wdiff): |
| 1350 wdiff = cgi.escape(wdiff) | 1334 wdiff = cgi.escape(wdiff) |
| 1351 wdiff = wdiff.replace(self._WDIFF_DEL, "<span class=del>") | 1335 wdiff = wdiff.replace(self._WDIFF_DEL, "<span class=del>") |
| 1352 wdiff = wdiff.replace(self._WDIFF_ADD, "<span class=add>") | 1336 wdiff = wdiff.replace(self._WDIFF_ADD, "<span class=add>") |
| 1353 wdiff = wdiff.replace(self._WDIFF_END, "</span>") | 1337 wdiff = wdiff.replace(self._WDIFF_END, "</span>") |
| 1354 html = "<head><style>.del { background: #faa; } " | 1338 html = "<head><style>.del { background: #faa; } " |
| 1355 html += ".add { background: #afa; }</style></head>" | 1339 html += ".add { background: #afa; }</style></head>" |
| 1356 html += "<pre>%s</pre>" % wdiff | 1340 html += "<pre>%s</pre>" % wdiff |
| 1357 return html | 1341 return html |
| 1358 | 1342 |
| 1359 def _wdiff_command(self, actual_filename, expected_filename): | 1343 def _wdiff_command(self, actual_filename, expected_filename): |
| 1360 executable = self._path_to_wdiff() | 1344 executable = self._path_to_wdiff() |
| 1361 return [executable, | 1345 return [executable, "--start-delete=%s" % self._WDIFF_DEL, "--end-delete
=%s" % self._WDIFF_END, |
| 1362 "--start-delete=%s" % self._WDIFF_DEL, | 1346 "--start-insert=%s" % self._WDIFF_ADD, "--end-insert=%s" % self.
_WDIFF_END, actual_filename, expected_filename] |
| 1363 "--end-delete=%s" % self._WDIFF_END, | |
| 1364 "--start-insert=%s" % self._WDIFF_ADD, | |
| 1365 "--end-insert=%s" % self._WDIFF_END, | |
| 1366 actual_filename, | |
| 1367 expected_filename] | |
| 1368 | 1347 |
| 1369 @staticmethod | 1348 @staticmethod |
| 1370 def _handle_wdiff_error(script_error): | 1349 def _handle_wdiff_error(script_error): |
| 1371 # Exit 1 means the files differed, any other exit code is an error. | 1350 # Exit 1 means the files differed, any other exit code is an error. |
| 1372 if script_error.exit_code != 1: | 1351 if script_error.exit_code != 1: |
| 1373 raise script_error | 1352 raise script_error |
| 1374 | 1353 |
| 1375 def _run_wdiff(self, actual_filename, expected_filename): | 1354 def _run_wdiff(self, actual_filename, expected_filename): |
| 1376 """Runs wdiff and may throw exceptions. | 1355 """Runs wdiff and may throw exceptions. |
| 1377 This is mostly a hook for unit testing.""" | 1356 This is mostly a hook for unit testing.""" |
| 1378 # Diffs are treated as binary as they may include multiple files | 1357 # Diffs are treated as binary as they may include multiple files |
| 1379 # with conflicting encodings. Thus we do not decode the output. | 1358 # with conflicting encodings. Thus we do not decode the output. |
| 1380 command = self._wdiff_command(actual_filename, expected_filename) | 1359 command = self._wdiff_command(actual_filename, expected_filename) |
| 1381 wdiff = self._executive.run_command(command, decode_output=False, | 1360 wdiff = self._executive.run_command(command, decode_output=False, error_
handler=self._handle_wdiff_error) |
| 1382 error_handler=self._handle_wdiff_error) | |
| 1383 return self._format_wdiff_output_as_html(wdiff) | 1361 return self._format_wdiff_output_as_html(wdiff) |
| 1384 | 1362 |
| 1385 _wdiff_error_html = "Failed to run wdiff, see error log." | 1363 _wdiff_error_html = "Failed to run wdiff, see error log." |
| 1386 | 1364 |
| 1387 def wdiff_text(self, actual_filename, expected_filename): | 1365 def wdiff_text(self, actual_filename, expected_filename): |
| 1388 """Returns a string of HTML indicating the word-level diff of the | 1366 """Returns a string of HTML indicating the word-level diff of the |
| 1389 contents of the two filenames. Returns an empty string if word-level | 1367 contents of the two filenames. Returns an empty string if word-level |
| 1390 diffing isn't available.""" | 1368 diffing isn't available.""" |
| 1391 if not self.wdiff_available(): | 1369 if not self.wdiff_available(): |
| 1392 return "" | 1370 return "" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1405 return self._wdiff_error_html | 1383 return self._wdiff_error_html |
| 1406 | 1384 |
| 1407 # This is a class variable so we can test error output easily. | 1385 # This is a class variable so we can test error output easily. |
| 1408 _pretty_patch_error_html = "Failed to run PrettyPatch, see error log." | 1386 _pretty_patch_error_html = "Failed to run PrettyPatch, see error log." |
| 1409 | 1387 |
| 1410 def pretty_patch_text(self, diff_path): | 1388 def pretty_patch_text(self, diff_path): |
| 1411 if self._pretty_patch_available is None: | 1389 if self._pretty_patch_available is None: |
| 1412 self._pretty_patch_available = self.check_pretty_patch(logging=False
) | 1390 self._pretty_patch_available = self.check_pretty_patch(logging=False
) |
| 1413 if not self._pretty_patch_available: | 1391 if not self._pretty_patch_available: |
| 1414 return self._pretty_patch_error_html | 1392 return self._pretty_patch_error_html |
| 1415 command = ("ruby", "-I", self._filesystem.dirname(self._pretty_patch_pat
h), | 1393 command = ("ruby", "-I", self._filesystem.dirname(self._pretty_patch_pat
h), self._pretty_patch_path, diff_path) |
| 1416 self._pretty_patch_path, diff_path) | |
| 1417 try: | 1394 try: |
| 1418 # Diffs are treated as binary (we pass decode_output=False) as they | 1395 # Diffs are treated as binary (we pass decode_output=False) as they |
| 1419 # may contain multiple files of conflicting encodings. | 1396 # may contain multiple files of conflicting encodings. |
| 1420 return self._executive.run_command(command, decode_output=False) | 1397 return self._executive.run_command(command, decode_output=False) |
| 1421 except OSError, e: | 1398 except OSError, e: |
| 1422 # If the system is missing ruby log the error and stop trying. | 1399 # If the system is missing ruby log the error and stop trying. |
| 1423 self._pretty_patch_available = False | 1400 self._pretty_patch_available = False |
| 1424 _log.error("Failed to run PrettyPatch (%s): %s" % (command, e)) | 1401 _log.error("Failed to run PrettyPatch (%s): %s" % (command, e)) |
| 1425 return self._pretty_patch_error_html | 1402 return self._pretty_patch_error_html |
| 1426 except ScriptError, e: | 1403 except ScriptError, e: |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1531 return 'AddressSanitizer' | 1508 return 'AddressSanitizer' |
| 1532 if 'MemorySanitizer' in output: | 1509 if 'MemorySanitizer' in output: |
| 1533 return 'MemorySanitizer' | 1510 return 'MemorySanitizer' |
| 1534 return None | 1511 return None |
| 1535 | 1512 |
| 1536 def _get_crash_log(self, name, pid, stdout, stderr, newer_than): | 1513 def _get_crash_log(self, name, pid, stdout, stderr, newer_than): |
| 1537 if self.output_contains_sanitizer_messages(stderr): | 1514 if self.output_contains_sanitizer_messages(stderr): |
| 1538 # Running the symbolizer script can take a lot of memory, so we need
to | 1515 # Running the symbolizer script can take a lot of memory, so we need
to |
| 1539 # serialize access to it across all the concurrently running drivers
. | 1516 # serialize access to it across all the concurrently running drivers
. |
| 1540 | 1517 |
| 1541 llvm_symbolizer_path = self.path_from_chromium_base('third_party', '
llvm-build', 'Release+Asserts', 'bin', 'llvm-symbolizer') | 1518 llvm_symbolizer_path = self.path_from_chromium_base('third_party', '
llvm-build', 'Release+Asserts', 'bin', |
| 1519 'llvm-symbolizer
') |
| 1542 if self._filesystem.exists(llvm_symbolizer_path): | 1520 if self._filesystem.exists(llvm_symbolizer_path): |
| 1543 env = os.environ.copy() | 1521 env = os.environ.copy() |
| 1544 env['LLVM_SYMBOLIZER_PATH'] = llvm_symbolizer_path | 1522 env['LLVM_SYMBOLIZER_PATH'] = llvm_symbolizer_path |
| 1545 else: | 1523 else: |
| 1546 env = None | 1524 env = None |
| 1547 sanitizer_filter_path = self.path_from_chromium_base('tools', 'valgr
ind', 'asan', 'asan_symbolize.py') | 1525 sanitizer_filter_path = self.path_from_chromium_base('tools', 'valgr
ind', 'asan', 'asan_symbolize.py') |
| 1548 sanitizer_strip_path_prefix = 'Release/../../' | 1526 sanitizer_strip_path_prefix = 'Release/../../' |
| 1549 if self._filesystem.exists(sanitizer_filter_path): | 1527 if self._filesystem.exists(sanitizer_filter_path): |
| 1550 stderr = self._executive.run_command(['flock', sys.executable, s
anitizer_filter_path, sanitizer_strip_path_prefix], input=stderr, decode_output=
False, env=env) | 1528 stderr = self._executive.run_command( |
| 1529 ['flock', sys.executable, sanitizer_filter_path, sanitizer_s
trip_path_prefix], |
| 1530 input=stderr, |
| 1531 decode_output=False, |
| 1532 env=env) |
| 1551 | 1533 |
| 1552 name_str = name or '<unknown process name>' | 1534 name_str = name or '<unknown process name>' |
| 1553 pid_str = str(pid or '<unknown>') | 1535 pid_str = str(pid or '<unknown>') |
| 1554 | 1536 |
| 1555 # We require stdout and stderr to be bytestrings, not character strings. | 1537 # We require stdout and stderr to be bytestrings, not character strings. |
| 1556 if stdout: | 1538 if stdout: |
| 1557 assert isinstance(stdout, str) | 1539 assert isinstance(stdout, str) |
| 1558 stdout_lines = stdout.decode('utf8', 'replace').splitlines() | 1540 stdout_lines = stdout.decode('utf8', 'replace').splitlines() |
| 1559 else: | 1541 else: |
| 1560 stdout_lines = [u'<empty>'] | 1542 stdout_lines = [u'<empty>'] |
| 1561 if stderr: | 1543 if stderr: |
| 1562 assert isinstance(stderr, str) | 1544 assert isinstance(stderr, str) |
| 1563 stderr_lines = stderr.decode('utf8', 'replace').splitlines() | 1545 stderr_lines = stderr.decode('utf8', 'replace').splitlines() |
| 1564 else: | 1546 else: |
| 1565 stderr_lines = [u'<empty>'] | 1547 stderr_lines = [u'<empty>'] |
| 1566 | 1548 |
| 1567 return (stderr, 'crash log for %s (pid %s):\n%s\n%s\n' % (name_str, pid_
str, | 1549 return (stderr, 'crash log for %s (pid %s):\n%s\n%s\n' % (name_str, pid_
str, '\n'.join(('STDOUT: ' + l) |
| 1568 '\n'.join(('STDOUT: ' + l) for l in stdout_lines), | 1550
for l in stdout_lines), |
| 1569 '\n'.join(('STDERR: ' + l) for l in stderr_lines))) | 1551 '\n'.join(('ST
DERR: ' + l) for l in stderr_lines))) |
| 1570 | 1552 |
| 1571 def look_for_new_crash_logs(self, crashed_processes, start_time): | 1553 def look_for_new_crash_logs(self, crashed_processes, start_time): |
| 1572 pass | 1554 pass |
| 1573 | 1555 |
| 1574 def look_for_new_samples(self, unresponsive_processes, start_time): | 1556 def look_for_new_samples(self, unresponsive_processes, start_time): |
| 1575 pass | 1557 pass |
| 1576 | 1558 |
| 1577 def sample_process(self, name, pid): | 1559 def sample_process(self, name, pid): |
| 1578 pass | 1560 pass |
| 1579 | 1561 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1685 | 1667 |
| 1686 # Ports which use compile-time feature detection should define this method a
nd return | 1668 # Ports which use compile-time feature detection should define this method a
nd return |
| 1687 # a dictionary mapping from symbol substrings to possibly disabled test dire
ctories. | 1669 # a dictionary mapping from symbol substrings to possibly disabled test dire
ctories. |
| 1688 # When the symbol substrings are not matched, the directories will be skippe
d. | 1670 # When the symbol substrings are not matched, the directories will be skippe
d. |
| 1689 # If ports don't ever enable certain features, then those directories can ju
st be | 1671 # If ports don't ever enable certain features, then those directories can ju
st be |
| 1690 # in the Skipped list instead of compile-time-checked here. | 1672 # in the Skipped list instead of compile-time-checked here. |
| 1691 def _missing_symbol_to_skipped_tests(self): | 1673 def _missing_symbol_to_skipped_tests(self): |
| 1692 if self.PORT_HAS_AUDIO_CODECS_BUILT_IN: | 1674 if self.PORT_HAS_AUDIO_CODECS_BUILT_IN: |
| 1693 return {} | 1675 return {} |
| 1694 else: | 1676 else: |
| 1695 return { | 1677 return {"ff_mp3_decoder": ["webaudio/codec-tests/mp3"], "ff_aac_deco
der": ["webaudio/codec-tests/aac"], } |
| 1696 "ff_mp3_decoder": ["webaudio/codec-tests/mp3"], | |
| 1697 "ff_aac_decoder": ["webaudio/codec-tests/aac"], | |
| 1698 } | |
| 1699 | 1678 |
| 1700 def _has_test_in_directories(self, directory_lists, test_list): | 1679 def _has_test_in_directories(self, directory_lists, test_list): |
| 1701 if not test_list: | 1680 if not test_list: |
| 1702 return False | 1681 return False |
| 1703 | 1682 |
| 1704 directories = itertools.chain.from_iterable(directory_lists) | 1683 directories = itertools.chain.from_iterable(directory_lists) |
| 1705 for directory, test in itertools.product(directories, test_list): | 1684 for directory, test in itertools.product(directories, test_list): |
| 1706 if test.startswith(directory): | 1685 if test.startswith(directory): |
| 1707 return True | 1686 return True |
| 1708 return False | 1687 return False |
| 1709 | 1688 |
| 1710 def _skipped_tests_for_unsupported_features(self, test_list): | 1689 def _skipped_tests_for_unsupported_features(self, test_list): |
| 1711 # Only check the symbols of there are tests in the test_list that might
get skipped. | 1690 # Only check the symbols of there are tests in the test_list that might
get skipped. |
| 1712 # This is a performance optimization to avoid the calling nm. | 1691 # This is a performance optimization to avoid the calling nm. |
| 1713 # Runtime feature detection not supported, fallback to static detection: | 1692 # Runtime feature detection not supported, fallback to static detection: |
| 1714 # Disable any tests for symbols missing from the executable or libraries
. | 1693 # Disable any tests for symbols missing from the executable or libraries
. |
| 1715 if self._has_test_in_directories(self._missing_symbol_to_skipped_tests()
.values(), test_list): | 1694 if self._has_test_in_directories(self._missing_symbol_to_skipped_tests()
.values(), test_list): |
| 1716 symbols_string = self._symbols_string() | 1695 symbols_string = self._symbols_string() |
| 1717 if symbols_string is not None: | 1696 if symbols_string is not None: |
| 1718 return reduce(operator.add, [directories for symbol_substring, d
irectories in self._missing_symbol_to_skipped_tests().items() if symbol_substrin
g not in symbols_string], []) | 1697 return reduce(operator.add, [directories |
| 1698 for symbol_substring, directories i
n self._missing_symbol_to_skipped_tests().items() |
| 1699 if symbol_substring not in symbols_
string], []) |
| 1719 return [] | 1700 return [] |
| 1720 | 1701 |
| 1721 def _convert_path(self, path): | 1702 def _convert_path(self, path): |
| 1722 """Handles filename conversion for subprocess command line args.""" | 1703 """Handles filename conversion for subprocess command line args.""" |
| 1723 # See note above in diff_image() for why we need this. | 1704 # See note above in diff_image() for why we need this. |
| 1724 if sys.platform == 'cygwin': | 1705 if sys.platform == 'cygwin': |
| 1725 return cygpath(path) | 1706 return cygpath(path) |
| 1726 return path | 1707 return path |
| 1727 | 1708 |
| 1728 def _build_path(self, *comps): | 1709 def _build_path(self, *comps): |
| 1729 return self._build_path_with_target(self._options.target, *comps) | 1710 return self._build_path_with_target(self._options.target, *comps) |
| 1730 | 1711 |
| 1731 def _build_path_with_target(self, target, *comps): | 1712 def _build_path_with_target(self, target, *comps): |
| 1732 # Note that we don't do the option caching that the | 1713 # Note that we don't do the option caching that the |
| 1733 # base class does, because finding the right directory is relatively | 1714 # base class does, because finding the right directory is relatively |
| 1734 # fast. | 1715 # fast. |
| 1735 target = target or self.get_option('target') | 1716 target = target or self.get_option('target') |
| 1736 return self._static_build_path(self._filesystem, self.get_option('build_
directory'), | 1717 return self._static_build_path(self._filesystem, self.get_option('build_
directory'), self.path_from_chromium_base(), target, |
| 1737 self.path_from_chromium_base(), target, c
omps) | 1718 comps) |
| 1738 | 1719 |
| 1739 def _check_driver_build_up_to_date(self, target): | 1720 def _check_driver_build_up_to_date(self, target): |
| 1740 # We should probably get rid of this check altogether as it has | 1721 # We should probably get rid of this check altogether as it has |
| 1741 # outlived its usefulness in a GN-based world, but for the moment | 1722 # outlived its usefulness in a GN-based world, but for the moment |
| 1742 # we will just check things if they are using the standard | 1723 # we will just check things if they are using the standard |
| 1743 # Debug or Release target directories. | 1724 # Debug or Release target directories. |
| 1744 if target not in ('Debug', 'Release'): | 1725 if target not in ('Debug', 'Release'): |
| 1745 return True | 1726 return True |
| 1746 | 1727 |
| 1747 try: | 1728 try: |
| 1748 debug_path = self._path_to_driver('Debug') | 1729 debug_path = self._path_to_driver('Debug') |
| 1749 release_path = self._path_to_driver('Release') | 1730 release_path = self._path_to_driver('Release') |
| 1750 | 1731 |
| 1751 debug_mtime = self._filesystem.mtime(debug_path) | 1732 debug_mtime = self._filesystem.mtime(debug_path) |
| 1752 release_mtime = self._filesystem.mtime(release_path) | 1733 release_mtime = self._filesystem.mtime(release_path) |
| 1753 | 1734 |
| 1754 if (debug_mtime > release_mtime and target == 'Release' or | 1735 if (debug_mtime > release_mtime and target == 'Release' or release_m
time > debug_mtime and target == 'Debug'): |
| 1755 release_mtime > debug_mtime and target == 'Debug'): | |
| 1756 most_recent_binary = 'Release' if target == 'Debug' else 'Debug' | 1736 most_recent_binary = 'Release' if target == 'Debug' else 'Debug' |
| 1757 _log.warning('You are running the %s binary. However the %s bina
ry appears to be more recent. ' | 1737 _log.warning('You are running the %s binary. However the %s bina
ry appears to be more recent. ' |
| 1758 'Please pass --%s.', target, most_recent_binary, mo
st_recent_binary.lower()) | 1738 'Please pass --%s.', target, most_recent_binary, mo
st_recent_binary.lower()) |
| 1759 _log.warning('') | 1739 _log.warning('') |
| 1760 # This will fail if we don't have both a debug and release binary. | 1740 # This will fail if we don't have both a debug and release binary. |
| 1761 # That's fine because, in this case, we must already be running the | 1741 # That's fine because, in this case, we must already be running the |
| 1762 # most up-to-date one. | 1742 # most up-to-date one. |
| 1763 except OSError: | 1743 except OSError: |
| 1764 pass | 1744 pass |
| 1765 return True | 1745 return True |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1788 class PhysicalTestSuite(object): | 1768 class PhysicalTestSuite(object): |
| 1789 def __init__(self, base, args, reference_args=None): | 1769 def __init__(self, base, args, reference_args=None): |
| 1790 self.name = base | 1770 self.name = base |
| 1791 self.base = base | 1771 self.base = base |
| 1792 self.args = args | 1772 self.args = args |
| 1793 self.reference_args = args if reference_args is None else reference_args | 1773 self.reference_args = args if reference_args is None else reference_args |
| 1794 self.tests = set() | 1774 self.tests = set() |
| 1795 | 1775 |
| 1796 def __repr__(self): | 1776 def __repr__(self): |
| 1797 return "PhysicalTestSuite('%s', '%s', %s, %s)" % (self.name, self.base,
self.args, self.reference_args) | 1777 return "PhysicalTestSuite('%s', '%s', %s, %s)" % (self.name, self.base,
self.args, self.reference_args) |
| OLD | NEW |