| Index: Tools/Scripts/webkitpy/layout_tests/port/base.py
|
| diff --git a/Tools/Scripts/webkitpy/layout_tests/port/base.py b/Tools/Scripts/webkitpy/layout_tests/port/base.py
|
| index e61d656e06c14bbf50089044446173ba924e2fc8..4b1d8c82a9af635ef42112610d071f41c6f23b05 100644
|
| --- a/Tools/Scripts/webkitpy/layout_tests/port/base.py
|
| +++ b/Tools/Scripts/webkitpy/layout_tests/port/base.py
|
| @@ -39,6 +39,7 @@ import operator
|
| import optparse
|
| import re
|
| import sys
|
| +from functools import reduce
|
|
|
| try:
|
| from collections import OrderedDict
|
| @@ -70,6 +71,7 @@ _log = logging.getLogger(__name__)
|
|
|
| # FIXME: This class should merge with WebKitPort now that Chromium behaves mostly like other webkit ports.
|
| class Port(object):
|
| +
|
| """Abstract class for Port-specific hooks for the layout_test package."""
|
|
|
| # Subclasses override this. This should indicate the basic implementation
|
| @@ -107,7 +109,7 @@ class Port(object):
|
| # FIXME: Technically this should be 'arm', but adding a third architecture type breaks TestConfigurationConverter.
|
| # If we need this to be 'arm' in the future, then we first have to fix TestConfigurationConverter.
|
| ('icecreamsandwich', 'x86'),
|
| - )
|
| + )
|
|
|
| ALL_BASELINE_VARIANTS = [
|
| 'mac-mavericks', 'mac-mountainlion', 'mac-retina', 'mac-lion', 'mac-snowleopard',
|
| @@ -207,7 +209,7 @@ class Port(object):
|
| self._wdiff_available = None
|
|
|
| # FIXME: prettypatch.py knows this path, why is it copied here?
|
| - self._pretty_patch_path = self.path_from_webkit_base("Tools", "Scripts", "webkitruby", "PrettyPatch", "prettify.rb")
|
| + self._pretty_patch_path = self.path_from_webkit_base('Tools', 'Scripts', 'webkitruby', 'PrettyPatch', 'prettify.rb')
|
| self._pretty_patch_available = None
|
|
|
| if not hasattr(options, 'configuration') or not options.configuration:
|
| @@ -358,7 +360,7 @@ class Port(object):
|
| def _check_driver(self):
|
| driver_path = self._path_to_driver()
|
| if not self._filesystem.exists(driver_path):
|
| - _log.error("%s was not found at %s" % (self.driver_name(), driver_path))
|
| + _log.error('%s was not found at %s' % (self.driver_name(), driver_path))
|
| return False
|
| return True
|
|
|
| @@ -396,7 +398,7 @@ class Port(object):
|
| """This routine is used to check whether image_diff binary exists."""
|
| image_diff_path = self._path_to_image_diff()
|
| if not self._filesystem.exists(image_diff_path):
|
| - _log.error("image_diff was not found at %s" % image_diff_path)
|
| + _log.error('image_diff was not found at %s' % image_diff_path)
|
| return False
|
| return True
|
|
|
| @@ -404,7 +406,7 @@ class Port(object):
|
| """Checks whether we can use the PrettyPatch ruby script."""
|
| try:
|
| _ = self._executive.run_command(['ruby', '--version'])
|
| - except OSError, e:
|
| + except OSError as e:
|
| if e.errno in [errno.ENOENT, errno.EACCES, errno.ECHILD]:
|
| if logging:
|
| _log.warning("Ruby is not installed; can't generate pretty patches.")
|
| @@ -445,12 +447,12 @@ class Port(object):
|
| try:
|
| server_name = self._filesystem.basename(httpd_path)
|
| env = self.setup_environ_for_server(server_name)
|
| - if self._executive.run_command([httpd_path, "-v"], env=env, return_exit_code=True) != 0:
|
| - _log.error("httpd seems broken. Cannot run http tests.")
|
| + if self._executive.run_command([httpd_path, '-v'], env=env, return_exit_code=True) != 0:
|
| + _log.error('httpd seems broken. Cannot run http tests.')
|
| return False
|
| return True
|
| except OSError:
|
| - _log.error("No httpd found. Cannot run http tests.")
|
| + _log.error('No httpd found. Cannot run http tests.')
|
| return False
|
|
|
| def do_text_results_differ(self, expected_text, actual_text):
|
| @@ -474,13 +476,13 @@ class Port(object):
|
|
|
| tempdir = self._filesystem.mkdtemp()
|
|
|
| - expected_filename = self._filesystem.join(str(tempdir), "expected.png")
|
| + expected_filename = self._filesystem.join(str(tempdir), 'expected.png')
|
| self._filesystem.write_binary_file(expected_filename, expected_contents)
|
|
|
| - actual_filename = self._filesystem.join(str(tempdir), "actual.png")
|
| + actual_filename = self._filesystem.join(str(tempdir), 'actual.png')
|
| self._filesystem.write_binary_file(actual_filename, actual_contents)
|
|
|
| - diff_filename = self._filesystem.join(str(tempdir), "diff.png")
|
| + diff_filename = self._filesystem.join(str(tempdir), 'diff.png')
|
|
|
| # image_diff needs native win paths as arguments, so we need to convert them if running under cygwin.
|
| native_expected_filename = self._convert_path(expected_filename)
|
| @@ -501,8 +503,8 @@ class Port(object):
|
| elif exit_code == 1:
|
| result = self._filesystem.read_binary_file(native_diff_filename)
|
| else:
|
| - err_str = "Image diff returned an exit code of %s. See http://crbug.com/278596" % exit_code
|
| - except OSError, e:
|
| + err_str = 'Image diff returned an exit code of %s. See http://crbug.com/278596' % exit_code
|
| + except OSError as e:
|
| err_str = 'error running image diff: %s' % str(e)
|
| finally:
|
| self._filesystem.rmtree(str(tempdir))
|
| @@ -681,7 +683,7 @@ class Port(object):
|
| if not self._filesystem.exists(baseline_path):
|
| return None
|
| text = self._filesystem.read_binary_file(baseline_path)
|
| - return text.replace("\r\n", "\n")
|
| + return text.replace('\r\n', '\n')
|
|
|
| def _get_reftest_list(self, test_name):
|
| dirname = self._filesystem.join(self.layout_tests_dir(), self._filesystem.dirname(test_name))
|
| @@ -707,7 +709,15 @@ class Port(object):
|
| if len(split_line) < 3:
|
| continue
|
| expectation_type, test_file, ref_file = split_line
|
| - parsed_list.setdefault(filesystem.join(test_dirpath, test_file), []).append((expectation_type, filesystem.join(test_dirpath, ref_file)))
|
| + parsed_list.setdefault(
|
| + filesystem.join(
|
| + test_dirpath,
|
| + test_file),
|
| + []).append(
|
| + (expectation_type,
|
| + filesystem.join(
|
| + test_dirpath,
|
| + ref_file)))
|
| return parsed_list
|
|
|
| def reference_files(self, test_name):
|
| @@ -734,7 +744,13 @@ class Port(object):
|
| def _real_tests(self, paths):
|
| # When collecting test cases, skip these directories
|
| skipped_directories = set(['.svn', '_svn', 'platform', 'resources', 'support', 'script-tests', 'reference', 'reftest'])
|
| - files = find_files.find(self._filesystem, self.layout_tests_dir(), paths, skipped_directories, Port.is_test_file, self.test_key)
|
| + files = find_files.find(
|
| + self._filesystem,
|
| + self.layout_tests_dir(),
|
| + paths,
|
| + skipped_directories,
|
| + Port.is_test_file,
|
| + self.test_key)
|
| return [self.relative_test_filename(f) for f in files]
|
|
|
| # When collecting test cases, we include any file with these extensions.
|
| @@ -760,7 +776,8 @@ class Port(object):
|
|
|
| @staticmethod
|
| def is_test_file(filesystem, dirname, filename):
|
| - return Port._has_supported_extension(filesystem, filename) and not Port.is_reference_html_file(filesystem, dirname, filename)
|
| + return Port._has_supported_extension(
|
| + filesystem, filename) and not Port.is_reference_html_file(filesystem, dirname, filename)
|
|
|
| ALL_TEST_TYPES = ['audio', 'harness', 'pixel', 'ref', 'text', 'unknown']
|
|
|
| @@ -905,11 +922,11 @@ class Port(object):
|
| def _expectations_from_skipped_files(self, skipped_file_paths):
|
| tests_to_skip = []
|
| for search_path in skipped_file_paths:
|
| - filename = self._filesystem.join(self._webkit_baseline_path(search_path), "Skipped")
|
| + filename = self._filesystem.join(self._webkit_baseline_path(search_path), 'Skipped')
|
| if not self._filesystem.exists(filename):
|
| - _log.debug("Skipped does not exist: %s" % filename)
|
| + _log.debug('Skipped does not exist: %s' % filename)
|
| continue
|
| - _log.debug("Using Skipped file: %s" % filename)
|
| + _log.debug('Using Skipped file: %s' % filename)
|
| skipped_file_contents = self._filesystem.read_text_file(filename)
|
| tests_to_skip.extend(self._tests_from_skipped_file_contents(skipped_file_contents))
|
| return tests_to_skip
|
| @@ -999,7 +1016,7 @@ class Port(object):
|
| # Delete the disk cache if any to ensure a clean test run.
|
| dump_render_tree_binary_path = self._path_to_driver()
|
| cachedir = self._filesystem.dirname(dump_render_tree_binary_path)
|
| - cachedir = self._filesystem.join(cachedir, "cache")
|
| + cachedir = self._filesystem.join(cachedir, 'cache')
|
| if self._filesystem.exists(cachedir):
|
| self._filesystem.rmtree(cachedir)
|
|
|
| @@ -1093,13 +1110,13 @@ class Port(object):
|
| method."""
|
| helper_path = self._path_to_helper()
|
| if helper_path:
|
| - _log.debug("Starting layout helper %s" % helper_path)
|
| + _log.debug('Starting layout helper %s' % helper_path)
|
| # Note: Not thread safe: http://bugs.python.org/issue2320
|
| self._helper = self._executive.popen([helper_path],
|
| - stdin=self._executive.PIPE, stdout=self._executive.PIPE, stderr=None)
|
| + stdin=self._executive.PIPE, stdout=self._executive.PIPE, stderr=None)
|
| is_ready = self._helper.stdout.readline()
|
| if not is_ready.startswith('ready'):
|
| - _log.error("layout_test_helper failed to be ready")
|
| + _log.error('layout_test_helper failed to be ready')
|
|
|
| def requires_http_server(self):
|
| """Does the port require an HTTP server for running tests? This could
|
| @@ -1139,12 +1156,12 @@ class Port(object):
|
| it isn't, or it isn't available. If a port overrides start_helper()
|
| it must override this routine as well."""
|
| if self._helper:
|
| - _log.debug("Stopping layout test helper")
|
| + _log.debug('Stopping layout test helper')
|
| try:
|
| - self._helper.stdin.write("x\n")
|
| + self._helper.stdin.write('x\n')
|
| self._helper.stdin.close()
|
| self._helper.wait()
|
| - except IOError, e:
|
| + except IOError as e:
|
| pass
|
| finally:
|
| self._helper = None
|
| @@ -1294,21 +1311,21 @@ class Port(object):
|
|
|
| def _format_wdiff_output_as_html(self, wdiff):
|
| wdiff = cgi.escape(wdiff)
|
| - wdiff = wdiff.replace(self._WDIFF_DEL, "<span class=del>")
|
| - wdiff = wdiff.replace(self._WDIFF_ADD, "<span class=add>")
|
| - wdiff = wdiff.replace(self._WDIFF_END, "</span>")
|
| - html = "<head><style>.del { background: #faa; } "
|
| - html += ".add { background: #afa; }</style></head>"
|
| - html += "<pre>%s</pre>" % wdiff
|
| + wdiff = wdiff.replace(self._WDIFF_DEL, '<span class=del>')
|
| + wdiff = wdiff.replace(self._WDIFF_ADD, '<span class=add>')
|
| + wdiff = wdiff.replace(self._WDIFF_END, '</span>')
|
| + html = '<head><style>.del { background: #faa; } '
|
| + html += '.add { background: #afa; }</style></head>'
|
| + html += '<pre>%s</pre>' % wdiff
|
| return html
|
|
|
| def _wdiff_command(self, actual_filename, expected_filename):
|
| executable = self._path_to_wdiff()
|
| return [executable,
|
| - "--start-delete=%s" % self._WDIFF_DEL,
|
| - "--end-delete=%s" % self._WDIFF_END,
|
| - "--start-insert=%s" % self._WDIFF_ADD,
|
| - "--end-insert=%s" % self._WDIFF_END,
|
| + '--start-delete=%s' % self._WDIFF_DEL,
|
| + '--end-delete=%s' % self._WDIFF_END,
|
| + '--start-insert=%s' % self._WDIFF_ADD,
|
| + '--end-insert=%s' % self._WDIFF_END,
|
| actual_filename,
|
| expected_filename]
|
|
|
| @@ -1325,17 +1342,17 @@ class Port(object):
|
| # with conflicting encodings. Thus we do not decode the output.
|
| command = self._wdiff_command(actual_filename, expected_filename)
|
| wdiff = self._executive.run_command(command, decode_output=False,
|
| - error_handler=self._handle_wdiff_error)
|
| + error_handler=self._handle_wdiff_error)
|
| return self._format_wdiff_output_as_html(wdiff)
|
|
|
| - _wdiff_error_html = "Failed to run wdiff, see error log."
|
| + _wdiff_error_html = 'Failed to run wdiff, see error log.'
|
|
|
| def wdiff_text(self, actual_filename, expected_filename):
|
| """Returns a string of HTML indicating the word-level diff of the
|
| contents of the two filenames. Returns an empty string if word-level
|
| diffing isn't available."""
|
| if not self.wdiff_available():
|
| - return ""
|
| + return ''
|
| try:
|
| # It's possible to raise a ScriptError we pass wdiff invalid paths.
|
| return self._run_wdiff(actual_filename, expected_filename)
|
| @@ -1343,37 +1360,37 @@ class Port(object):
|
| if e.errno in [errno.ENOENT, errno.EACCES, errno.ECHILD]:
|
| # Silently ignore cases where wdiff is missing.
|
| self._wdiff_available = False
|
| - return ""
|
| + return ''
|
| raise
|
| except ScriptError as e:
|
| - _log.error("Failed to run wdiff: %s" % e)
|
| + _log.error('Failed to run wdiff: %s' % e)
|
| self._wdiff_available = False
|
| return self._wdiff_error_html
|
|
|
| # This is a class variable so we can test error output easily.
|
| - _pretty_patch_error_html = "Failed to run PrettyPatch, see error log."
|
| + _pretty_patch_error_html = 'Failed to run PrettyPatch, see error log.'
|
|
|
| def pretty_patch_text(self, diff_path):
|
| if self._pretty_patch_available is None:
|
| self._pretty_patch_available = self.check_pretty_patch(logging=False)
|
| if not self._pretty_patch_available:
|
| return self._pretty_patch_error_html
|
| - command = ("ruby", "-I", self._filesystem.dirname(self._pretty_patch_path),
|
| + command = ('ruby', '-I', self._filesystem.dirname(self._pretty_patch_path),
|
| self._pretty_patch_path, diff_path)
|
| try:
|
| # Diffs are treated as binary (we pass decode_output=False) as they
|
| # may contain multiple files of conflicting encodings.
|
| return self._executive.run_command(command, decode_output=False)
|
| - except OSError, e:
|
| + except OSError as e:
|
| # If the system is missing ruby log the error and stop trying.
|
| self._pretty_patch_available = False
|
| - _log.error("Failed to run PrettyPatch (%s): %s" % (command, e))
|
| + _log.error('Failed to run PrettyPatch (%s): %s' % (command, e))
|
| return self._pretty_patch_error_html
|
| - except ScriptError, e:
|
| + except ScriptError as e:
|
| # If ruby failed to run for some reason, log the command
|
| # output and stop trying.
|
| self._pretty_patch_available = False
|
| - _log.error("Failed to run PrettyPatch (%s):\n%s" % (command, e.message_with_output()))
|
| + _log.error('Failed to run PrettyPatch (%s):\n%s' % (command, e.message_with_output()))
|
| return self._pretty_patch_error_html
|
|
|
| def default_configuration(self):
|
| @@ -1434,7 +1451,7 @@ class Port(object):
|
| if self._is_debian_based():
|
| return 'debian-httpd-' + self._apache_version() + '.conf'
|
| # All platforms use apache2 except for CYGWIN (and Mac OS X Tiger and prior, which we no longer support).
|
| - return "apache2-httpd.conf"
|
| + return 'apache2-httpd.conf'
|
|
|
| def _path_to_driver(self, configuration=None):
|
| """Returns the full path to the test driver."""
|
| @@ -1463,7 +1480,7 @@ class Port(object):
|
| """Returns the full path to the wdiff binary, or None if it is not available.
|
|
|
| This is likely used only by wdiff_text()"""
|
| - for path in ("/usr/bin/wdiff", "/usr/bin/dwdiff"):
|
| + for path in ('/usr/bin/wdiff', '/usr/bin/dwdiff'):
|
| if self._filesystem.exists(path):
|
| return path
|
| return None
|
| @@ -1495,15 +1512,20 @@ class Port(object):
|
| sanitizer_filter_path = self.path_from_chromium_base('tools', 'valgrind', 'asan', 'asan_symbolize.py')
|
| sanitizer_strip_path_prefix = 'Release/../../'
|
| if self._filesystem.exists(sanitizer_filter_path):
|
| - stderr = self._executive.run_command(['flock', sys.executable, sanitizer_filter_path, sanitizer_strip_path_prefix], input=stderr, decode_output=False)
|
| + stderr = self._executive.run_command(['flock',
|
| + sys.executable,
|
| + sanitizer_filter_path,
|
| + sanitizer_strip_path_prefix],
|
| + input=stderr,
|
| + decode_output=False)
|
|
|
| name_str = name or '<unknown process name>'
|
| pid_str = str(pid or '<unknown>')
|
| stdout_lines = (stdout or '<empty>').decode('utf8', 'replace').splitlines()
|
| stderr_lines = (stderr or '<empty>').decode('utf8', 'replace').splitlines()
|
| return (stderr, 'crash log for %s (pid %s):\n%s\n%s\n' % (name_str, pid_str,
|
| - '\n'.join(('STDOUT: ' + l) for l in stdout_lines),
|
| - '\n'.join(('STDERR: ' + l) for l in stderr_lines)))
|
| + '\n'.join(('STDOUT: ' + l) for l in stdout_lines),
|
| + '\n'.join(('STDERR: ' + l) for l in stderr_lines)))
|
|
|
| def look_for_new_crash_logs(self, crashed_processes, start_time):
|
| pass
|
| @@ -1519,7 +1541,7 @@ class Port(object):
|
| # For example, to turn on force-compositing-mode in the svg/ directory:
|
| # PhysicalTestSuite('svg',
|
| # ['--force-compositing-mode']),
|
| - ]
|
| + ]
|
|
|
| def virtual_test_suites(self):
|
| return [
|
| @@ -1680,7 +1702,7 @@ class Port(object):
|
| for path_to_module in self._modules_to_search_for_symbols():
|
| try:
|
| symbols += self._executive.run_command(['nm', path_to_module], error_handler=self._executive.ignore_error)
|
| - except OSError, e:
|
| + except OSError as e:
|
| _log.warn("Failed to run nm: %s. Can't determine supported features correctly." % e)
|
| return symbols
|
|
|
| @@ -1694,8 +1716,8 @@ class Port(object):
|
| return {}
|
| else:
|
| return {
|
| - "ff_mp3_decoder": ["webaudio/codec-tests/mp3"],
|
| - "ff_aac_decoder": ["webaudio/codec-tests/aac"],
|
| + 'ff_mp3_decoder': ['webaudio/codec-tests/mp3'],
|
| + 'ff_aac_decoder': ['webaudio/codec-tests/aac'],
|
| }
|
|
|
| def _has_test_in_directories(self, directory_lists, test_list):
|
| @@ -1716,7 +1738,8 @@ class Port(object):
|
| if self._has_test_in_directories(self._missing_symbol_to_skipped_tests().values(), test_list):
|
| symbols_string = self._symbols_string()
|
| if symbols_string is not None:
|
| - return reduce(operator.add, [directories for symbol_substring, directories in self._missing_symbol_to_skipped_tests().items() if symbol_substring not in symbols_string], [])
|
| + return reduce(operator.add, [directories for symbol_substring, directories in self._missing_symbol_to_skipped_tests(
|
| + ).items() if symbol_substring not in symbols_string], [])
|
| return []
|
|
|
| def _convert_path(self, path):
|
| @@ -1735,7 +1758,7 @@ class Port(object):
|
| # fast.
|
| configuration = configuration or self.get_option('configuration')
|
| return self._static_build_path(self._filesystem, self.get_option('build_directory'),
|
| - self.path_from_chromium_base(), configuration, comps)
|
| + self.path_from_chromium_base(), configuration, comps)
|
|
|
| def _check_driver_build_up_to_date(self, configuration):
|
| if configuration in ('Debug', 'Release'):
|
| @@ -1747,7 +1770,7 @@ class Port(object):
|
| release_mtime = self._filesystem.mtime(release_path)
|
|
|
| if (debug_mtime > release_mtime and configuration == 'Release' or
|
| - release_mtime > debug_mtime and configuration == 'Debug'):
|
| + release_mtime > debug_mtime and configuration == 'Debug'):
|
| most_recent_binary = 'Release' if configuration == 'Debug' else 'Debug'
|
| _log.warning('You are running the %s binary. However the %s binary appears to be more recent. '
|
| 'Please pass --%s.', configuration, most_recent_binary, most_recent_binary.lower())
|
| @@ -1764,7 +1787,9 @@ class Port(object):
|
| platform = self.name()
|
| return self.path_from_webkit_base('LayoutTests', 'platform', platform)
|
|
|
| +
|
| class VirtualTestSuite(object):
|
| +
|
| def __init__(self, name, base, args, use_legacy_naming=False, tests=None):
|
| if use_legacy_naming:
|
| self.name = 'virtual/' + name
|
| @@ -1782,6 +1807,7 @@ class VirtualTestSuite(object):
|
|
|
|
|
| class PhysicalTestSuite(object):
|
| +
|
| def __init__(self, base, args):
|
| self.name = base
|
| self.base = base
|
|
|