diff options
Diffstat (limited to 'WebKitTools/Scripts/webkitpy/layout_tests/port/base.py')
-rw-r--r-- | WebKitTools/Scripts/webkitpy/layout_tests/port/base.py | 197 |
1 files changed, 69 insertions, 128 deletions
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py index a98b858..632806f 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py @@ -30,10 +30,7 @@ """Abstract base class of Port-specific entrypoints for the layout tests test infrastructure (the Port and Driver classes).""" -from __future__ import with_statement - import cgi -import codecs import difflib import errno import os @@ -42,15 +39,17 @@ import sys import time import apache_http_server +import config as port_config import http_lock import http_server import test_files import websocket_server -from webkitpy.common.memoized import memoized +from webkitpy.common import system +from webkitpy.common.system import filesystem from webkitpy.common.system import logutils +from webkitpy.common.system import path from webkitpy.common.system.executive import Executive, ScriptError -from webkitpy.common.system.path import abspath_to_uri from webkitpy.common.system.user import User @@ -75,27 +74,26 @@ class DummyOptions(object): # FIXME: This class should merge with webkitpy.webkit_port at some point. class Port(object): - """Abstract class for Port-specific hooks for the layout_test package. - """ - - @staticmethod - def flag_from_configuration(configuration): - flags_by_configuration = { - "Debug": "--debug", - "Release": "--release", - } - return flags_by_configuration[configuration] - - def __init__(self, **kwargs): - self._name = kwargs.get('port_name', None) - self._options = kwargs.get('options') + """Abstract class for Port-specific hooks for the layout_test package.""" + + def __init__(self, port_name=None, options=None, + executive=None, + user=None, + filesystem=None, + config=None, + **kwargs): + self._name = port_name + self._options = options if self._options is None: # FIXME: Ideally we'd have a package-wide way to get a # well-formed options object that had all of the necessary # options defined on it. self._options = DummyOptions() - self._executive = kwargs.get('executive', Executive()) - self._user = kwargs.get('user', User()) + self._executive = executive or Executive() + self._user = user or User() + self._filesystem = filesystem or system.filesystem.FileSystem() + self._config = config or port_config.Config(self._executive, + self._filesystem) self._helper = None self._http_server = None self._webkit_base_dir = None @@ -118,7 +116,7 @@ class Port(object): self._wdiff_available = True self._pretty_patch_path = self.path_from_webkit_base("BugsSite", - "PrettyPatch", "prettify.rb") + "PrettyPatch", "prettify.rb") self._pretty_patch_available = True self.set_option_default('configuration', None) if self._options.configuration is None: @@ -265,7 +263,8 @@ class Port(object): baselines = [] for platform_dir in baseline_search_path: - if os.path.exists(os.path.join(platform_dir, baseline_filename)): + if self.path_exists(self._filesystem.join(platform_dir, + baseline_filename)): baselines.append((platform_dir, baseline_filename)) if not all_baselines and baselines: @@ -274,7 +273,8 @@ class Port(object): # If it wasn't found in a platform directory, return the expected # result in the test directory, even if no such file actually exists. platform_dir = self.layout_tests_dir() - if os.path.exists(os.path.join(platform_dir, baseline_filename)): + if self.path_exists(self._filesystem.join(platform_dir, + baseline_filename)): baselines.append((platform_dir, baseline_filename)) if baselines: @@ -304,35 +304,32 @@ class Port(object): platform_dir, baseline_filename = self.expected_baselines( filename, suffix)[0] if platform_dir: - return os.path.join(platform_dir, baseline_filename) - return os.path.join(self.layout_tests_dir(), baseline_filename) - - def _expected_file_contents(self, test, extension, encoding): - path = self.expected_filename(test, extension) - if not os.path.exists(path): - return None - open_mode = 'r' - if encoding is None: - open_mode = 'r+b' - with codecs.open(path, open_mode, encoding) as file: - return file.read() + return self._filesystem.join(platform_dir, baseline_filename) + return self._filesystem.join(self.layout_tests_dir(), baseline_filename) def expected_checksum(self, test): """Returns the checksum of the image we expect the test to produce, or None if it is a text-only test.""" - return self._expected_file_contents(test, '.checksum', 'ascii') + path = self.expected_filename(test, '.checksum') + if not self.path_exists(path): + return None + return self._filesystem.read_text_file(path) def expected_image(self, test): """Returns the image we expect the test to produce.""" - return self._expected_file_contents(test, '.png', None) + path = self.expected_filename(test, '.png') + if not self.path_exists(path): + return None + return self._filesystem.read_binary_file(path) def expected_text(self, test): """Returns the text output we expect the test to produce.""" - # NOTE: -expected.txt files are ALWAYS utf-8. However, - # we do not decode the output from DRT, so we should not - # decode the -expected.txt values either to allow comparisons. - text = self._expected_file_contents(test, '.txt', None) - if not text: + # FIXME: DRT output is actually utf-8, but since we don't decode the + # output from DRT (instead treating it as a binary string), we read the + # baselines as a binary string, too. + path = self.expected_filename(test, '.txt') + if not self.path_exists(path): return '' + text = self._filesystem.read_binary_file(path) return text.strip("\r\n").replace("\r\n", "\n") + "\n" def filename_to_uri(self, filename): @@ -362,7 +359,7 @@ class Port(object): protocol = "http" return "%s://127.0.0.1:%u/%s" % (protocol, port, relative_path) - return abspath_to_uri(os.path.abspath(filename)) + return path.abspath_to_uri(os.path.abspath(filename)) def tests(self, paths): """Return the list of tests found (relative to layout_tests_dir().""" @@ -373,20 +370,19 @@ class Port(object): Used by --clobber-old-results.""" layout_tests_dir = self.layout_tests_dir() - return filter(lambda x: os.path.isdir(os.path.join(layout_tests_dir, x)), - os.listdir(layout_tests_dir)) + return filter(lambda x: self._filesystem.isdir(self._filesystem.join(layout_tests_dir, x)), + self._filesystem.listdir(layout_tests_dir)) def path_isdir(self, path): - """Returns whether the path refers to a directory of tests. - - Used by test_expectations.py to apply rules to whole directories.""" - return os.path.isdir(path) + """Return True if the path refers to a directory of tests.""" + # Used by test_expectations.py to apply rules to whole directories. + return self._filesystem.isdir(path) def path_exists(self, path): - """Returns whether the path refers to an existing test or baseline.""" + """Return True if the path refers to an existing test or baseline.""" # Used by test_expectations.py to determine if an entry refers to a - # valid test and by printing.py to determine if baselines exist.""" - return os.path.exists(path) + # valid test and by printing.py to determine if baselines exist. + return self._filesystem.exists(path) def update_baseline(self, path, data, encoding): """Updates the baseline for a test. @@ -398,11 +394,12 @@ class Port(object): data: contents of the baseline. encoding: file encoding to use for the baseline. """ - write_mode = "w" + # FIXME: remove the encoding parameter in favor of text/binary + # functions. if encoding is None: - write_mode = "wb" - with codecs.open(path, write_mode, encoding=encoding) as file: - file.write(data) + self._filesystem.write_binary_file(path, data) + else: + self._filesystem.write_text_file(path, data) def uri_to_test_name(self, uri): """Return the base layout test name for a given URI. @@ -414,7 +411,7 @@ class Port(object): """ test = uri if uri.startswith("file:///"): - prefix = abspath_to_uri(self.layout_tests_dir()) + "/" + prefix = path.abspath_to_uri(self.layout_tests_dir()) + "/" return test[len(prefix):] if uri.startswith("http://127.0.0.1:8880/"): @@ -441,18 +438,16 @@ class Port(object): for test_or_category in self.skipped_layout_tests(): if test_or_category == test_name: return True - category = os.path.join(self.layout_tests_dir(), test_or_category) - if os.path.isdir(category) and test_name.startswith(test_or_category): + category = self._filesystem.join(self.layout_tests_dir(), + test_or_category) + if (self._filesystem.isdir(category) and + test_name.startswith(test_or_category)): return True return False def maybe_make_directory(self, *path): """Creates the specified directory if it doesn't already exist.""" - try: - os.makedirs(os.path.join(*path)) - except OSError, e: - if e.errno != errno.EEXIST: - raise + self._filesystem.maybe_make_directory(*path) def name(self): """Return the name of the port (e.g., 'mac', 'chromium-win-xp'). @@ -473,19 +468,13 @@ class Port(object): if not hasattr(self._options, name): return setattr(self._options, name, default_value) - # FIXME: This could be replaced by functions in webkitpy.common.checkout.scm. def path_from_webkit_base(self, *comps): """Returns the full path to path made by joining the top of the WebKit source tree and the list of path components in |*comps|.""" - if not self._webkit_base_dir: - abspath = os.path.abspath(__file__) - self._webkit_base_dir = abspath[0:abspath.find('WebKitTools')] - - return os.path.join(self._webkit_base_dir, *comps) + return self._config.path_from_webkit_base(*comps) - # FIXME: Callers should eventually move to scm.script_path. def script_path(self, script_name): - return self.path_from_webkit_base("WebKitTools", "Scripts", script_name) + return self._config.script_path(script_name) def path_to_test_expectations_file(self): """Update the test expectations to the passed-in string. @@ -726,50 +715,8 @@ class Port(object): e.message_with_output())) return self._pretty_patch_error_html - def _webkit_build_directory_command(self, args): - return ["perl", self.script_path("webkit-build-directory")] + args - - @memoized - def _webkit_top_level_build_directory(self, top_level=True): - """This directory is above where products are built to and contains things like the Configuration file.""" - args = self._webkit_build_directory_command(["--top-level"]) - return self._executive.run_command(args).rstrip() - - @memoized - def _webkit_configuration_build_directory(self, configuration=None): - """This is where products are normally built to.""" - if not configuration: - configuration = self.flag_from_configuration(self.get_option('configuration')) - args = self._webkit_build_directory_command(["--configuration", configuration]) - return self._executive.run_command(args).rstrip() - - def _configuration_file_path(self): - return os.path.join(self._webkit_top_level_build_directory(), "Configuration") - - # Easy override for unit tests - def _open_configuration_file(self): - configuration_path = self._configuration_file_path() - return codecs.open(configuration_path, "r", "utf-8") - - def _read_configuration(self): - try: - with self._open_configuration_file() as file: - return file.readline().rstrip() - except: - return None - - # FIXME: This list may be incomplete as Apple has some sekret configs. - _RECOGNIZED_CONFIGURATIONS = ("Debug", "Release") - def default_configuration(self): - # FIXME: Unify this with webkitdir.pm configuration reading code. - configuration = self._read_configuration() - if not configuration: - configuration = "Release" - if configuration not in self._RECOGNIZED_CONFIGURATIONS: - _log.warn("Configuration \"%s\" found in %s is not a recognized value.\n" % (configuration, self._configuration_file_path())) - _log.warn("Scripts may fail. See 'set-webkit-configuration --help'.") - return configuration + return self._config.default_configuration() # # PROTECTED ROUTINES @@ -777,6 +724,8 @@ class Port(object): # The routines below should only be called by routines in this class # or any of its subclasses. # + def _webkit_build_directory(self, args): + return self._config.build_directory(args[0]) def _path_to_apache(self): """Returns the full path to the apache binary. @@ -848,8 +797,8 @@ class Port(object): def _webkit_baseline_path(self, platform): """Return the full path to the top of the baseline tree for a given platform.""" - return os.path.join(self.layout_tests_dir(), 'platform', - platform) + return self._filesystem.join(self.layout_tests_dir(), 'platform', + platform) class Driver: @@ -883,16 +832,8 @@ class Driver: checksum - if present, the expected checksum for the image for this test - Returns a tuple of the following: - crash - a boolean indicating whether the driver crashed on the test - timeout - a boolean indicating whehter the test timed out - checksum - a string containing the checksum of the image, if - present - output - any text output - error - any unexpected or additional (or error) text output - - Note that the image itself should be written to the path that was - specified in the __init__() call.""" + Returns a TestOutput object. + """ raise NotImplementedError('Driver.run_test') # FIXME: This is static so we can test it w/o creating a Base instance. |