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 |