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 |