summaryrefslogtreecommitdiffstats
path: root/WebKitTools/Scripts/webkitpy/layout_tests
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-10-22 13:02:20 +0100
committerBen Murdoch <benm@google.com>2010-10-26 15:21:41 +0100
commita94275402997c11dd2e778633dacf4b7e630a35d (patch)
treee66f56c67e3b01f22c9c23cd932271ee9ac558ed /WebKitTools/Scripts/webkitpy/layout_tests
parent09e26c78506587b3f5d930d7bc72a23287ffbec0 (diff)
downloadexternal_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.zip
external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.gz
external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.bz2
Merge WebKit at r70209: Initial merge by Git
Change-Id: Id23a68efa36e9d1126bcce0b137872db00892c8e
Diffstat (limited to 'WebKitTools/Scripts/webkitpy/layout_tests')
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py3
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py88
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/base.py183
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py71
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py92
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py9
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py21
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py8
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py10
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py91
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py23
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py1
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py18
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py44
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py55
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock.py125
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock_unittest.py111
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py2
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py15
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/test.py8
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py23
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py9
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py85
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py41
-rwxr-xr-xWebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py121
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py91
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py2
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py5
28 files changed, 986 insertions, 369 deletions
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py
index bb9604f..309bf8d 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py
@@ -205,3 +205,6 @@ class ListDuplicatesTest(unittest.TestCase):
for expected, inputs in test_cases:
self.assertEquals(expected,
deduplicate_tests.get_relative_test_path(*inputs))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py
index 970de60..e0fd1b6 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
# Copyright (C) 2010 Google Inc. All rights reserved.
+# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -271,23 +272,26 @@ class TestShellThread(WatchableThread):
self._test_types = test_types
self._test_args = test_args
self._driver = None
- self._directory_timing_stats = {}
+ self._test_group_timing_stats = {}
self._test_results = []
self._num_tests = 0
self._start_time = 0
self._stop_time = 0
-
- # Current directory of tests we're running.
- self._current_dir = None
- # Number of tests in self._current_dir.
- self._num_tests_in_current_dir = None
- # Time at which we started running tests from self._current_dir.
- self._current_dir_start_time = None
-
- def get_directory_timing_stats(self):
- """Returns a dictionary mapping test directory to a tuple of
- (number of tests in that directory, time to run the tests)"""
- return self._directory_timing_stats
+ self._have_http_lock = False
+ self._http_lock_wait_begin = 0
+ self._http_lock_wait_end = 0
+
+ # Current group of tests we're running.
+ self._current_group = None
+ # Number of tests in self._current_group.
+ self._num_tests_in_current_group = None
+ # Time at which we started running tests from self._current_group.
+ self._current_group_start_time = None
+
+ def get_test_group_timing_stats(self):
+ """Returns a dictionary mapping test group to a tuple of
+ (number of tests in that group, time to run the tests)"""
+ return self._test_group_timing_stats
def get_test_results(self):
"""Return the list of all tests run on this thread.
@@ -298,7 +302,8 @@ class TestShellThread(WatchableThread):
return self._test_results
def get_total_time(self):
- return max(self._stop_time - self._start_time, 0.0)
+ return max(self._stop_time - self._start_time -
+ self._http_lock_wait_time(), 0.0)
def get_num_tests(self):
return self._num_tests
@@ -337,6 +342,25 @@ class TestShellThread(WatchableThread):
do multi-threaded debugging."""
self._run(test_runner, result_summary)
+ def cancel(self):
+ """Clean up http lock and set a flag telling this thread to quit."""
+ self._stop_http_lock()
+ WatchableThread.cancel(self)
+
+ def next_timeout(self):
+ """Return the time the test is supposed to finish by."""
+ if self._next_timeout:
+ return self._next_timeout + self._http_lock_wait_time()
+ return self._next_timeout
+
+ def _http_lock_wait_time(self):
+ """Return the time what http locking takes."""
+ if self._http_lock_wait_begin == 0:
+ return 0
+ if self._http_lock_wait_end == 0:
+ return time.time() - self._http_lock_wait_begin
+ return self._http_lock_wait_end - self._http_lock_wait_begin
+
def _run(self, test_runner, result_summary):
"""Main work entry point of the thread. Basically we pull urls from the
filename queue and run the tests until we run out of urls.
@@ -359,21 +383,35 @@ class TestShellThread(WatchableThread):
return
if len(self._filename_list) is 0:
- if self._current_dir is not None:
- self._directory_timing_stats[self._current_dir] = \
- (self._num_tests_in_current_dir,
- time.time() - self._current_dir_start_time)
+ if self._current_group is not None:
+ self._test_group_timing_stats[self._current_group] = \
+ (self._num_tests_in_current_group,
+ time.time() - self._current_group_start_time)
try:
- self._current_dir, self._filename_list = \
+ self._current_group, self._filename_list = \
self._filename_list_queue.get_nowait()
except Queue.Empty:
+ self._stop_http_lock()
self._kill_dump_render_tree()
tests_run_file.close()
return
- self._num_tests_in_current_dir = len(self._filename_list)
- self._current_dir_start_time = time.time()
+ if self._options.wait_for_httpd:
+ if self._current_group == "tests_to_http_lock":
+ self._http_lock_wait_begin = time.time()
+ self._port.acquire_http_lock()
+
+ self._port.start_http_server()
+ self._port.start_websocket_server()
+
+ self._have_http_lock = True
+ self._http_lock_wait_end = time.time()
+ elif self._have_http_lock:
+ self._stop_http_lock()
+
+ self._num_tests_in_current_group = len(self._filename_list)
+ self._current_group_start_time = time.time()
test_info = self._filename_list.pop()
@@ -517,6 +555,14 @@ class TestShellThread(WatchableThread):
self._options)
self._driver.start()
+ def _stop_http_lock(self):
+ """Stop the servers and release http lock."""
+ if self._have_http_lock:
+ self._port.stop_http_server()
+ self._port.stop_websocket_server()
+ self._port.release_http_lock()
+ self._have_http_lock = False
+
def _kill_dump_render_tree(self):
"""Kill the DumpRenderTree process if it's running."""
if self._driver:
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
index 6a5d43b..cd7d663 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
@@ -42,33 +42,35 @@ import sys
import time
import apache_http_server
-import test_files
+import http_lock
import http_server
+import test_files
import websocket_server
from webkitpy.common.system import logutils
from webkitpy.common.system.executive import Executive, ScriptError
+from webkitpy.common.system.path import abspath_to_uri
from webkitpy.common.system.user import User
_log = logutils.get_logger(__file__)
-# Python's Popen has a bug that causes any pipes opened to a
-# process that can't be executed to be leaked. Since this
-# code is specifically designed to tolerate exec failures
-# to gracefully handle cases where wdiff is not installed,
-# the bug results in a massive file descriptor leak. As a
-# workaround, if an exec failure is ever experienced for
-# wdiff, assume it's not available. This will leak one
-# file descriptor but that's better than leaking each time
-# wdiff would be run.
-#
-# http://mail.python.org/pipermail/python-list/
-# 2008-August/505753.html
-# http://bugs.python.org/issue3210
-_wdiff_available = True
-_pretty_patch_available = True
+class DummyOptions(object):
+ """Fake implementation of optparse.Values. Cloned from
+ webkitpy.tool.mocktool.MockOptions.
+
+ """
+
+ def __init__(self, **kwargs):
+ # The caller can set option values using keyword arguments. We don't
+ # set any values by default because we don't know how this
+ # object will be used. Generally speaking unit tests should
+ # subclass this or provider wrapper functions that set a common
+ # set of options.
+ for key, value in kwargs.items():
+ self.__dict__[key] = value
+
# FIXME: This class should merge with webkitpy.webkit_port at some point.
class Port(object):
@@ -85,13 +87,41 @@ class Port(object):
def __init__(self, **kwargs):
self._name = kwargs.get('port_name', None)
- self._options = kwargs.get('options', None)
+ self._options = kwargs.get('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._helper = None
self._http_server = None
self._webkit_base_dir = None
self._websocket_server = None
+ self._http_lock = None
+
+ # Python's Popen has a bug that causes any pipes opened to a
+ # process that can't be executed to be leaked. Since this
+ # code is specifically designed to tolerate exec failures
+ # to gracefully handle cases where wdiff is not installed,
+ # the bug results in a massive file descriptor leak. As a
+ # workaround, if an exec failure is ever experienced for
+ # wdiff, assume it's not available. This will leak one
+ # file descriptor but that's better than leaking each time
+ # wdiff would be run.
+ #
+ # http://mail.python.org/pipermail/python-list/
+ # 2008-August/505753.html
+ # http://bugs.python.org/issue3210
+ self._wdiff_available = True
+
+ self._pretty_patch_path = self.path_from_webkit_base("BugsSite",
+ "PrettyPatch", "prettify.rb")
+ self._pretty_patch_available = True
+ self.set_option_default('configuration', None)
+ if self._options.configuration is None:
+ self._options.configuration = self.default_configuration()
def default_child_processes(self):
"""Return the number of DumpRenderTree instances to use for this
@@ -125,6 +155,27 @@ class Port(object):
"""This routine is used to check whether image_diff binary exists."""
raise NotImplementedError('Port.check_image_diff')
+ def check_pretty_patch(self):
+ """Checks whether we can use the PrettyPatch ruby script."""
+
+ # check if Ruby is installed
+ try:
+ result = self._executive.run_command(['ruby', '--version'])
+ except OSError, e:
+ if e.errno in [errno.ENOENT, errno.EACCES, errno.ECHILD]:
+ _log.error("Ruby is not installed; "
+ "can't generate pretty patches.")
+ _log.error('')
+ return False
+
+ if not self.path_exists(self._pretty_patch_path):
+ _log.error('Unable to find %s .' % self._pretty_patch_path)
+ _log.error("Can't generate pretty patches.")
+ _log.error('')
+ return False
+
+ return True
+
def compare_text(self, expected_text, actual_text):
"""Return whether or not the two strings are *not* equal. This
routine is used to diff text output.
@@ -259,7 +310,10 @@ class Port(object):
path = self.expected_filename(test, extension)
if not os.path.exists(path):
return None
- with codecs.open(path, 'r', encoding) as file:
+ open_mode = 'r'
+ if encoding is None:
+ open_mode = 'r+b'
+ with codecs.open(path, open_mode, encoding) as file:
return file.read()
def expected_checksum(self, test):
@@ -281,22 +335,18 @@ class Port(object):
return text.strip("\r\n").replace("\r\n", "\n") + "\n"
def filename_to_uri(self, filename):
- """Convert a test file to a URI."""
+ """Convert a test file (which is an absolute path) to a URI."""
LAYOUTTEST_HTTP_DIR = "http/tests/"
- LAYOUTTEST_WEBSOCKET_DIR = "websocket/tests/"
+ LAYOUTTEST_WEBSOCKET_DIR = "http/tests/websocket/tests/"
relative_path = self.relative_test_filename(filename)
port = None
use_ssl = False
- if relative_path.startswith(LAYOUTTEST_HTTP_DIR):
- # http/tests/ run off port 8000 and ssl/ off 8443
+ if (relative_path.startswith(LAYOUTTEST_WEBSOCKET_DIR)
+ or relative_path.startswith(LAYOUTTEST_HTTP_DIR)):
relative_path = relative_path[len(LAYOUTTEST_HTTP_DIR):]
port = 8000
- elif relative_path.startswith(LAYOUTTEST_WEBSOCKET_DIR):
- # websocket/tests/ run off port 8880 and 9323
- # Note: the root is /, not websocket/tests/
- port = 8880
# Make http/tests/local run as local files. This is to mimic the
# logic in run-webkit-tests.
@@ -311,9 +361,7 @@ class Port(object):
protocol = "http"
return "%s://127.0.0.1:%u/%s" % (protocol, port, relative_path)
- if sys.platform in ('cygwin', 'win32'):
- return "file:///" + self.get_absolute_path(filename)
- return "file://" + self.get_absolute_path(filename)
+ return abspath_to_uri(os.path.abspath(filename))
def tests(self, paths):
"""Return the list of tests found (relative to layout_tests_dir()."""
@@ -349,7 +397,10 @@ class Port(object):
data: contents of the baseline.
encoding: file encoding to use for the baseline.
"""
- with codecs.open(path, "w", encoding=encoding) as file:
+ write_mode = "w"
+ if encoding is None:
+ write_mode = "wb"
+ with codecs.open(path, write_mode, encoding=encoding) as file:
file.write(data)
def uri_to_test_name(self, uri):
@@ -362,12 +413,8 @@ class Port(object):
"""
test = uri
if uri.startswith("file:///"):
- if sys.platform == 'win32':
- test = test.replace('file:///', '')
- test = test.replace('/', '\\')
- else:
- test = test.replace('file://', '')
- return self.relative_test_filename(test)
+ prefix = abspath_to_uri(self.layout_tests_dir()) + "/"
+ return test[len(prefix):]
if uri.startswith("http://127.0.0.1:8880/"):
# websocket tests
@@ -382,13 +429,6 @@ class Port(object):
raise NotImplementedError('unknown url type: %s' % uri)
- def get_absolute_path(self, filename):
- """Return the absolute path in unix format for the given filename.
-
- This routine exists so that platforms that don't use unix filenames
- can convert accordingly."""
- return os.path.abspath(filename)
-
def layout_tests_dir(self):
"""Return the absolute path to the top of the LayoutTests directory."""
return self.path_from_webkit_base('LayoutTests')
@@ -420,6 +460,18 @@ class Port(object):
may be different (e.g., 'win-xp' instead of 'chromium-win-xp'."""
return self._name
+ def get_option(self, name, default_value=None):
+ # FIXME: Eventually we should not have to do a test for
+ # hasattr(), and we should be able to just do
+ # self.options.value. See additional FIXME in the constructor.
+ if hasattr(self._options, name):
+ return getattr(self._options, name)
+ return default_value
+
+ def set_option_default(self, name, default_value):
+ 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
@@ -445,7 +497,7 @@ class Port(object):
"""Relative unix-style path for a filename under the LayoutTests
directory. Filenames outside the LayoutTests directory should raise
an error."""
- assert(filename.startswith(self.layout_tests_dir()))
+ #assert(filename.startswith(self.layout_tests_dir()))
return filename[len(self.layout_tests_dir()) + 1:]
def results_directory(self):
@@ -484,12 +536,12 @@ class Port(object):
"""Start a web server if it is available. Do nothing if
it isn't. This routine is allowed to (and may) fail if a server
is already running."""
- if self._options.use_apache:
+ if self.get_option('use_apache'):
self._http_server = apache_http_server.LayoutTestApacheHttpd(self,
- self._options.results_directory)
+ self.get_option('results_directory'))
else:
self._http_server = http_server.Lighttpd(self,
- self._options.results_directory)
+ self.get_option('results_directory'))
self._http_server.start()
def start_websocket_server(self):
@@ -497,9 +549,13 @@ class Port(object):
it isn't. This routine is allowed to (and may) fail if a server
is already running."""
self._websocket_server = websocket_server.PyWebSocket(self,
- self._options.results_directory)
+ self.get_option('results_directory'))
self._websocket_server.start()
+ def acquire_http_lock(self):
+ self._http_lock = http_lock.HttpLock(None)
+ self._http_lock.wait_for_httpd_lock()
+
def stop_helper(self):
"""Shut down the test helper if it is running. Do nothing if
it isn't, or it isn't available. If a port overrides start_helper()
@@ -518,6 +574,10 @@ class Port(object):
if self._websocket_server:
self._websocket_server.stop()
+ def release_http_lock(self):
+ if self._http_lock:
+ self._http_lock.cleanup_http_lock()
+
def test_expectations(self):
"""Returns the test expectations for this port.
@@ -628,8 +688,7 @@ class Port(object):
"""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."""
- global _wdiff_available # See explaination at top of file.
- if not _wdiff_available:
+ if not self._wdiff_available:
return ""
try:
# It's possible to raise a ScriptError we pass wdiff invalid paths.
@@ -637,33 +696,33 @@ class Port(object):
except OSError, e:
if e.errno in [errno.ENOENT, errno.EACCES, errno.ECHILD]:
# Silently ignore cases where wdiff is missing.
- _wdiff_available = False
+ self._wdiff_available = False
return ""
raise
- _pretty_patch_error_html = "Failed to run PrettyPatch, see error console."
+ # This is a class variable so we can test error output easily.
+ _pretty_patch_error_html = "Failed to run PrettyPatch, see error log."
def pretty_patch_text(self, diff_path):
- # FIXME: Much of this function could move to prettypatch.rb
- global _pretty_patch_available
- if not _pretty_patch_available:
+ if not self._pretty_patch_available:
return self._pretty_patch_error_html
- pretty_patch_path = self.path_from_webkit_base("BugsSite", "PrettyPatch")
- prettify_path = os.path.join(pretty_patch_path, "prettify.rb")
- command = ["ruby", "-I", pretty_patch_path, prettify_path, diff_path]
+ command = ("ruby", "-I", os.path.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:
# If the system is missing ruby log the error and stop trying.
- _pretty_patch_available = False
+ self._pretty_patch_available = False
_log.error("Failed to run PrettyPatch (%s): %s" % (command, e))
return self._pretty_patch_error_html
except ScriptError, e:
- # If ruby failed to run for some reason, log the command output and stop trying.
- _pretty_patch_available = False
- _log.error("Failed to run PrettyPatch (%s):\n%s" % (command, e.message_with_output()))
+ # 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()))
return self._pretty_patch_error_html
def _webkit_build_directory(self, args):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py
index 71877b3..93f8808 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py
@@ -26,16 +26,19 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-import base
+import optparse
import os
import StringIO
import sys
import tempfile
import unittest
+from webkitpy.common.system.path import abspath_to_uri
from webkitpy.common.system.executive import Executive, ScriptError
from webkitpy.thirdparty.mock import Mock
+from webkitpy.tool import mocktool
+import base
# FIXME: This makes StringIO objects work with "with". Remove
# when we upgrade to 2.6.
@@ -139,11 +142,11 @@ class PortTest(unittest.TestCase):
expected_wdiff = "<head><style>.del { background: #faa; } .add { background: #afa; }</style></head><pre><span class=del>foo</span><span class=add>bar</span></pre>"
self.assertEqual(wdiff, expected_wdiff)
# Running the full wdiff_text method should give the same result.
- base._wdiff_available = True # In case it's somehow already disabled.
+ port._wdiff_available = True # In case it's somehow already disabled.
wdiff = port.wdiff_text(actual.name, expected.name)
self.assertEqual(wdiff, expected_wdiff)
# wdiff should still be available after running wdiff_text with a valid diff.
- self.assertTrue(base._wdiff_available)
+ self.assertTrue(port._wdiff_available)
actual.close()
expected.close()
@@ -151,7 +154,7 @@ class PortTest(unittest.TestCase):
self.assertRaises(ScriptError, port._run_wdiff, "/does/not/exist", "/does/not/exist2")
self.assertRaises(ScriptError, port.wdiff_text, "/does/not/exist", "/does/not/exist2")
# wdiff will still be available after running wdiff_text with invalid paths.
- self.assertTrue(base._wdiff_available)
+ self.assertTrue(port._wdiff_available)
base._wdiff_available = True
# If wdiff does not exist _run_wdiff should throw an OSError.
@@ -161,8 +164,7 @@ class PortTest(unittest.TestCase):
# wdiff_text should not throw an error if wdiff does not exist.
self.assertEqual(port.wdiff_text("foo", "bar"), "")
# However wdiff should not be available after running wdiff_text if wdiff is missing.
- self.assertFalse(base._wdiff_available)
- base._wdiff_available = True
+ self.assertFalse(port._wdiff_available)
def test_diff_text(self):
port = base.Port()
@@ -226,6 +228,63 @@ class PortTest(unittest.TestCase):
self.assertTrue('canvas' in dirs)
self.assertTrue('css2.1' in dirs)
+ def test_filename_to_uri(self):
+
+ port = base.Port()
+ layout_test_dir = port.layout_tests_dir()
+ test_file = os.path.join(layout_test_dir, "foo", "bar.html")
+
+ # On Windows, absolute paths are of the form "c:\foo.txt". However,
+ # all current browsers (except for Opera) normalize file URLs by
+ # prepending an additional "/" as if the absolute path was
+ # "/c:/foo.txt". This means that all file URLs end up with "file:///"
+ # at the beginning.
+ if sys.platform == 'win32':
+ prefix = "file:///"
+ path = test_file.replace("\\", "/")
+ else:
+ prefix = "file://"
+ path = test_file
+
+ self.assertEqual(port.filename_to_uri(test_file),
+ abspath_to_uri(test_file))
+
+ def test_get_option__set(self):
+ options, args = optparse.OptionParser().parse_args()
+ options.foo = 'bar'
+ port = base.Port(options=options)
+ self.assertEqual(port.get_option('foo'), 'bar')
+
+ def test_get_option__unset(self):
+ port = base.Port()
+ self.assertEqual(port.get_option('foo'), None)
+
+ def test_get_option__default(self):
+ port = base.Port()
+ self.assertEqual(port.get_option('foo', 'bar'), 'bar')
+
+ def test_set_option_default__unset(self):
+ port = base.Port()
+ port.set_option_default('foo', 'bar')
+ self.assertEqual(port.get_option('foo'), 'bar')
+
+ def test_set_option_default__set(self):
+ options, args = optparse.OptionParser().parse_args()
+ options.foo = 'bar'
+ port = base.Port(options=options)
+ # This call should have no effect.
+ port.set_option_default('foo', 'new_bar')
+ self.assertEqual(port.get_option('foo'), 'bar')
+
+ def test_name__unset(self):
+ port = base.Port()
+ self.assertEqual(port.name(), None)
+
+ def test_name__set(self):
+ port = base.Port(port_name='foo')
+ self.assertEqual(port.name(), 'foo')
+
+
class VirtualTest(unittest.TestCase):
"""Tests that various methods expected to be virtual are."""
def assertVirtual(self, method, *args, **kwargs):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py
index a72627a..4d17b51 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py
@@ -43,6 +43,10 @@ import tempfile
import time
import webbrowser
+from webkitpy.common.system.executive import Executive
+from webkitpy.common.system.path import cygpath
+from webkitpy.layout_tests.layout_package import test_expectations
+
import base
import http_server
@@ -84,11 +88,6 @@ class ChromiumPort(base.Port):
def __init__(self, **kwargs):
base.Port.__init__(self, **kwargs)
- if 'options' in kwargs:
- options = kwargs['options']
- if (options and (not hasattr(options, 'configuration') or
- options.configuration is None)):
- options.configuration = self.default_configuration()
self._chromium_base_dir = None
def baseline_path(self):
@@ -100,9 +99,9 @@ class ChromiumPort(base.Port):
dump_render_tree_binary_path = self._path_to_driver()
result = check_file_exists(dump_render_tree_binary_path,
'test driver') and result
- if result and self._options.build:
+ if result and self.get_option('build'):
result = self._check_driver_build_up_to_date(
- self._options.configuration)
+ self.get_option('configuration'))
else:
_log.error('')
@@ -111,10 +110,14 @@ class ChromiumPort(base.Port):
result = check_file_exists(helper_path,
'layout test helper') and result
- if self._options.pixel_tests:
+ if self.get_option('pixel_tests'):
result = self.check_image_diff(
'To override, invoke with --no-pixel-tests') and result
+ # It's okay if pretty patch isn't available, but we will at
+ # least log a message.
+ self.check_pretty_patch()
+
return result
def check_sys_deps(self, needs_http):
@@ -134,28 +137,43 @@ class ChromiumPort(base.Port):
def diff_image(self, expected_contents, actual_contents,
diff_filename=None, tolerance=0):
executable = self._path_to_image_diff()
- expected_tmpfile = tempfile.NamedTemporaryFile()
- expected_tmpfile.write(expected_contents)
- actual_tmpfile = tempfile.NamedTemporaryFile()
- actual_tmpfile.write(actual_contents)
+
+ tempdir = tempfile.mkdtemp()
+ expected_filename = os.path.join(tempdir, "expected.png")
+ with open(expected_filename, 'w+b') as file:
+ file.write(expected_contents)
+ actual_filename = os.path.join(tempdir, "actual.png")
+ with open(actual_filename, 'w+b') as file:
+ file.write(actual_contents)
+
if diff_filename:
- cmd = [executable, '--diff', expected_tmpfile.name,
- actual_tmpfile.name, diff_filename]
+ cmd = [executable, '--diff', expected_filename,
+ actual_filename, diff_filename]
else:
- cmd = [executable, expected_tmpfile.name, actual_tmpfile.name]
+ cmd = [executable, expected_filename, actual_filename]
result = True
try:
- if self._executive.run_command(cmd, return_exit_code=True) == 0:
- return False
+ exit_code = self._executive.run_command(cmd, return_exit_code=True)
+ if exit_code == 0:
+ # The images are the same.
+ result = False
+ elif exit_code != 1:
+ _log.error("image diff returned an exit code of "
+ + str(exit_code))
+ # Returning False here causes the script to think that we
+ # successfully created the diff even though we didn't. If
+ # we return True, we think that the images match but the hashes
+ # don't match.
+ # FIXME: Figure out why image_diff returns other values.
+ result = False
except OSError, e:
if e.errno == errno.ENOENT or e.errno == errno.EACCES:
_compare_available = False
else:
raise e
finally:
- expected_tmpfile.close()
- actual_tmpfile.close()
+ shutil.rmtree(tempdir, ignore_errors=True)
return result
def driver_name(self):
@@ -182,10 +200,11 @@ class ChromiumPort(base.Port):
def results_directory(self):
try:
return self.path_from_chromium_base('webkit',
- self._options.configuration, self._options.results_directory)
+ self.get_option('configuration'),
+ self.get_option('results_directory'))
except AssertionError:
- return self._build_path(self._options.configuration,
- self._options.results_directory)
+ return self._build_path(self.get_option('configuration'),
+ self.get_option('results_directory'))
def setup_test_run(self):
# Delete the disk cache if any to ensure a clean test run.
@@ -239,7 +258,7 @@ class ChromiumPort(base.Port):
# FIXME: This drt_overrides handling should be removed when we switch
# from tes_shell to DRT.
drt_overrides = ''
- if self._options and self._options.use_drt:
+ if self.get_option('use_drt'):
drt_overrides_path = self.path_from_webkit_base('LayoutTests',
'platform', 'chromium', 'drt_expectations.txt')
if os.path.exists(drt_overrides_path):
@@ -325,11 +344,18 @@ class ChromiumPort(base.Port):
platform = self.name()
return self.path_from_webkit_base('LayoutTests', 'platform', platform)
+ def _convert_path(self, path):
+ """Handles filename conversion for subprocess command line args."""
+ # See note above in diff_image() for why we need this.
+ if sys.platform == 'cygwin':
+ return cygpath(path)
+ return path
+
def _path_to_image_diff(self):
binary_name = 'image_diff'
- if self._options.use_drt:
+ if self.get_option('use_drt'):
binary_name = 'ImageDiff'
- return self._build_path(self._options.configuration, binary_name)
+ return self._build_path(self.get_option('configuration'), binary_name)
class ChromiumDriver(base.Driver):
@@ -344,29 +370,31 @@ class ChromiumDriver(base.Driver):
def _driver_args(self):
driver_args = []
if self._image_path:
- driver_args.append("--pixel-tests=" + self._image_path)
+ # See note above in diff_image() for why we need _convert_path().
+ driver_args.append("--pixel-tests=" +
+ self._port._convert_path(self._image_path))
- if self._options.use_drt:
+ if self._port.get_option('use_drt'):
driver_args.append('--test-shell')
else:
driver_args.append('--layout-tests')
- if self._options.startup_dialog:
+ if self._port.get_option('startup_dialog'):
driver_args.append('--testshell-startup-dialog')
- if self._options.gp_fault_error_box:
+ if self._port.get_option('gp_fault_error_box'):
driver_args.append('--gp-fault-error-box')
- if self._options.accelerated_compositing:
+ if self._port.get_option('accelerated_compositing'):
driver_args.append('--enable-accelerated-compositing')
- if self._options.accelerated_2d_canvas:
+ if self._port.get_option('accelerated_2d_canvas'):
driver_args.append('--enable-accelerated-2d-canvas')
return driver_args
def start(self):
# FIXME: Should be an error to call this method twice.
- cmd = self._command_wrapper(self._options.wrapper)
+ cmd = self._command_wrapper(self._port.get_option('wrapper'))
cmd.append(self._port._path_to_driver())
cmd += self._driver_args()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py
index 80602d9..95c716e 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu.py
@@ -66,7 +66,7 @@ def get(**kwargs):
def _set_gpu_options(options):
if options:
if options.accelerated_compositing is None:
- options.accelerated_composting = True
+ options.accelerated_compositing = True
if options.accelerated_2d_canvas is None:
options.accelerated_2d_canvas = True
@@ -90,7 +90,8 @@ class ChromiumGpuLinuxPort(chromium_linux.ChromiumLinuxPort):
chromium_linux.ChromiumLinuxPort.__init__(self, **kwargs)
def baseline_search_path(self):
- return ([self._webkit_baseline_path('chromium-gpu-linux')] +
+ # Mimic the Linux -> Win expectations fallback in the ordinary Chromium port.
+ return (map(self._webkit_baseline_path, ['chromium-gpu-linux', 'chromium-gpu-win', 'chromium-gpu']) +
chromium_linux.ChromiumLinuxPort.baseline_search_path(self))
def path_to_test_expectations_file(self):
@@ -108,7 +109,7 @@ class ChromiumGpuMacPort(chromium_mac.ChromiumMacPort):
chromium_mac.ChromiumMacPort.__init__(self, **kwargs)
def baseline_search_path(self):
- return ([self._webkit_baseline_path('chromium-gpu-mac')] +
+ return (map(self._webkit_baseline_path, ['chromium-gpu-mac', 'chromium-gpu']) +
chromium_mac.ChromiumMacPort.baseline_search_path(self))
def path_to_test_expectations_file(self):
@@ -126,7 +127,7 @@ class ChromiumGpuWinPort(chromium_win.ChromiumWinPort):
chromium_win.ChromiumWinPort.__init__(self, **kwargs)
def baseline_search_path(self):
- return ([self._webkit_baseline_path('chromium-gpu-win')] +
+ return (map(self._webkit_baseline_path, ['chromium-gpu-win', 'chromium-gpu']) +
chromium_win.ChromiumWinPort.baseline_search_path(self))
def path_to_test_expectations_file(self):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py
index 5c79a3f..7a13b1c 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_gpu_unittest.py
@@ -26,6 +26,8 @@
import os
import unittest
+
+from webkitpy.tool import mocktool
import chromium_gpu
@@ -41,16 +43,25 @@ class ChromiumGpuTest(unittest.TestCase):
def assertOverridesWorked(self, port_name):
# test that we got the right port
- port = chromium_gpu.get(port_name=port_name, options=None)
+ mock_options = mocktool.MockOptions(accelerated_compositing=None,
+ accelerated_2d_canvas=None)
+ port = chromium_gpu.get(port_name=port_name, options=mock_options)
+ self.assertTrue(port._options.accelerated_compositing)
+ self.assertTrue(port._options.accelerated_2d_canvas)
# we use startswith() instead of Equal to gloss over platform versions.
self.assertTrue(port.name().startswith(port_name))
- # test that it has the right directory in front of the search path.
- path = port.baseline_search_path()[0]
- self.assertEqual(port._webkit_baseline_path(port_name), path)
+ # test that it has the right directories in front of the search path.
+ paths = port.baseline_search_path()
+ self.assertEqual(port._webkit_baseline_path(port_name), paths[0])
+ if port_name == 'chromium-gpu-linux':
+ self.assertEqual(port._webkit_baseline_path('chromium-gpu-win'), paths[1])
+ self.assertEqual(port._webkit_baseline_path('chromium-gpu'), paths[2])
+ else:
+ self.assertEqual(port._webkit_baseline_path('chromium-gpu'), paths[1])
- # test that we have the right expectations file.
+ # Test that we have the right expectations file.
self.assertTrue('chromium-gpu' in
port.path_to_test_expectations_file())
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
index 176991b..b26a6b5 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
@@ -52,7 +52,7 @@ class ChromiumLinuxPort(chromium.ChromiumPort):
def check_build(self, needs_http):
result = chromium.ChromiumPort.check_build(self, needs_http)
if needs_http:
- if self._options.use_apache:
+ if self.get_option('use_apache'):
result = self._check_apache_install() and result
else:
result = self._check_lighttpd_install() and result
@@ -81,7 +81,7 @@ class ChromiumLinuxPort(chromium.ChromiumPort):
base = self.path_from_chromium_base()
if os.path.exists(os.path.join(base, 'sconsbuild')):
return os.path.join(base, 'sconsbuild', *comps)
- if os.path.exists(os.path.join(base, 'out', *comps)) or not self._options.use_drt:
+ if os.path.exists(os.path.join(base, 'out', *comps)) or not self.get_option('use_drt'):
return os.path.join(base, 'out', *comps)
base = self.path_from_webkit_base()
if os.path.exists(os.path.join(base, 'sconsbuild')):
@@ -147,9 +147,9 @@ class ChromiumLinuxPort(chromium.ChromiumPort):
def _path_to_driver(self, configuration=None):
if not configuration:
- configuration = self._options.configuration
+ configuration = self.get_option('configuration')
binary_name = 'test_shell'
- if self._options.use_drt:
+ if self.get_option('use_drt'):
binary_name = 'DumpRenderTree'
return self._build_path(configuration, binary_name)
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
index 64016ab..d1c383c 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
@@ -73,7 +73,7 @@ class ChromiumMacPort(chromium.ChromiumPort):
def driver_name(self):
"""name for this port's equivalent of DumpRenderTree."""
- if self._options.use_drt:
+ if self.get_option('use_drt'):
return "DumpRenderTree"
return "TestShell"
@@ -100,7 +100,7 @@ class ChromiumMacPort(chromium.ChromiumPort):
def _build_path(self, *comps):
path = self.path_from_chromium_base('xcodebuild', *comps)
- if os.path.exists(path) or not self._options.use_drt:
+ if os.path.exists(path) or not self.get_option('use_drt'):
return path
return self.path_from_webkit_base('WebKit', 'chromium', 'xcodebuild',
*comps)
@@ -138,15 +138,15 @@ class ChromiumMacPort(chromium.ChromiumPort):
# FIXME: make |configuration| happy with case-sensitive file
# systems.
if not configuration:
- configuration = self._options.configuration
+ configuration = self.get_option('configuration')
return self._build_path(configuration, self.driver_name() + '.app',
'Contents', 'MacOS', self.driver_name())
def _path_to_helper(self):
binary_name = 'layout_test_helper'
- if self._options.use_drt:
+ if self.get_option('use_drt'):
binary_name = 'LayoutTestHelper'
- return self._build_path(self._options.configuration, binary_name)
+ return self._build_path(self.get_option('configuration'), binary_name)
def _path_to_wdiff(self):
return 'wdiff'
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py
index a4a9ea6..cb45430 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py
@@ -26,24 +26,22 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-import chromium
-import chromium_linux
-import chromium_mac
-import chromium_win
+import os
import unittest
import StringIO
-import os
+from webkitpy.tool import mocktool
from webkitpy.thirdparty.mock import Mock
+import chromium
+import chromium_linux
+import chromium_mac
+import chromium_win
class ChromiumDriverTest(unittest.TestCase):
def setUp(self):
mock_port = Mock()
- # FIXME: The Driver should not be grabbing at port._options!
- mock_port._options = Mock()
- mock_port._options.wrapper = ""
self.driver = chromium.ChromiumDriver(mock_port, image_path=None, options=None)
def test_test_shell_command(self):
@@ -106,25 +104,19 @@ class ChromiumPortTest(unittest.TestCase):
return 'default'
def test_path_to_image_diff(self):
- class MockOptions:
- def __init__(self):
- self.use_drt = True
-
- port = ChromiumPortTest.TestLinuxPort(options=MockOptions())
+ mock_options = mocktool.MockOptions(use_drt=True)
+ port = ChromiumPortTest.TestLinuxPort(options=mock_options)
self.assertTrue(port._path_to_image_diff().endswith(
'/out/default/ImageDiff'), msg=port._path_to_image_diff())
- port = ChromiumPortTest.TestMacPort(options=MockOptions())
+ port = ChromiumPortTest.TestMacPort(options=mock_options)
self.assertTrue(port._path_to_image_diff().endswith(
'/xcodebuild/default/ImageDiff'))
# FIXME: Figure out how this is going to work on Windows.
#port = chromium_win.ChromiumWinPort('test-port', options=MockOptions())
def test_skipped_layout_tests(self):
- class MockOptions:
- def __init__(self):
- self.use_drt = True
-
- port = ChromiumPortTest.TestLinuxPort(options=MockOptions())
+ mock_options = mocktool.MockOptions(use_drt=True)
+ port = ChromiumPortTest.TestLinuxPort(options=mock_options)
fake_test = os.path.join(port.layout_tests_dir(), "fast/js/not-good.js")
@@ -138,23 +130,56 @@ DEFER LINUX WIN : fast/js/very-good.js = TIMEOUT PASS"""
self.assertTrue("fast/js/not-good.js" in skipped_tests)
def test_default_configuration(self):
- class EmptyOptions:
- def __init__(self):
- pass
-
- options = EmptyOptions()
- port = ChromiumPortTest.TestLinuxPort(options)
- self.assertEquals(options.configuration, 'default')
+ mock_options = mocktool.MockOptions()
+ port = ChromiumPortTest.TestLinuxPort(options=mock_options)
+ self.assertEquals(mock_options.configuration, 'default')
self.assertTrue(port.default_configuration_called)
- class OptionsWithUnsetConfiguration:
- def __init__(self):
- self.configuration = None
-
- options = OptionsWithUnsetConfiguration()
- port = ChromiumPortTest.TestLinuxPort(options)
- self.assertEquals(options.configuration, 'default')
+ mock_options = mocktool.MockOptions(configuration=None)
+ port = ChromiumPortTest.TestLinuxPort(mock_options)
+ self.assertEquals(mock_options.configuration, 'default')
self.assertTrue(port.default_configuration_called)
+ def test_diff_image(self):
+ class TestPort(ChromiumPortTest.TestLinuxPort):
+ def _path_to_image_diff(self):
+ return "/path/to/image_diff"
+
+ class MockExecute:
+ def __init__(self, result):
+ self._result = result
+
+ def run_command(self,
+ args,
+ cwd=None,
+ input=None,
+ error_handler=None,
+ return_exit_code=False,
+ return_stderr=True,
+ decode_output=False):
+ if return_exit_code:
+ return self._result
+ return ''
+
+ mock_options = mocktool.MockOptions(use_drt=False)
+ port = ChromiumPortTest.TestLinuxPort(mock_options)
+
+ # Images are different.
+ port._executive = MockExecute(0)
+ self.assertEquals(False, port.diff_image("EXPECTED", "ACTUAL"))
+
+ # Images are the same.
+ port._executive = MockExecute(1)
+ self.assertEquals(True, port.diff_image("EXPECTED", "ACTUAL"))
+
+ # There was some error running image_diff.
+ port._executive = MockExecute(2)
+ exception_raised = False
+ try:
+ port.diff_image("EXPECTED", "ACTUAL")
+ except ValueError, e:
+ exception_raised = True
+ self.assertFalse(exception_raised)
+
if __name__ == '__main__':
unittest.main()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py
index d2b0265..69b529a 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py
@@ -55,9 +55,7 @@ class ChromiumWinPort(chromium.ChromiumPort):
# python executable to run cgi program.
env["CYGWIN_PATH"] = self.path_from_chromium_base(
"third_party", "cygwin", "bin")
- if (sys.platform == "win32" and self._options and
- hasattr(self._options, "register_cygwin") and
- self._options.register_cygwin):
+ if (sys.platform == "win32" and self.get_option('register_cygwin')):
setup_mount = self.path_from_chromium_base("third_party",
"cygwin",
"setup_mount.bat")
@@ -84,11 +82,6 @@ class ChromiumWinPort(chromium.ChromiumPort):
'build-instructions-windows')
return result
- def get_absolute_path(self, filename):
- """Return the absolute path in unix format for the given filename."""
- abspath = os.path.abspath(filename)
- return abspath.replace('\\', '/')
-
def relative_test_filename(self, filename):
path = filename[len(self.layout_tests_dir()) + 1:]
return path.replace('\\', '/')
@@ -118,7 +111,7 @@ class ChromiumWinPort(chromium.ChromiumPort):
if os.path.exists(p):
return p
p = self.path_from_chromium_base('chrome', *comps)
- if os.path.exists(p) or not self._options.use_drt:
+ if os.path.exists(p) or not self.get_option('use_drt'):
return p
return os.path.join(self.path_from_webkit_base(), 'WebKit', 'chromium',
*comps)
@@ -146,23 +139,23 @@ class ChromiumWinPort(chromium.ChromiumPort):
def _path_to_driver(self, configuration=None):
if not configuration:
- configuration = self._options.configuration
+ configuration = self.get_option('configuration')
binary_name = 'test_shell.exe'
- if self._options.use_drt:
+ if self.get_option('use_drt'):
binary_name = 'DumpRenderTree.exe'
return self._build_path(configuration, binary_name)
def _path_to_helper(self):
binary_name = 'layout_test_helper.exe'
- if self._options.use_drt:
+ if self.get_option('use_drt'):
binary_name = 'LayoutTestHelper.exe'
- return self._build_path(self._options.configuration, binary_name)
+ return self._build_path(self.get_option('configuration'), binary_name)
def _path_to_image_diff(self):
binary_name = 'image_diff.exe'
- if self._options.use_drt:
+ if self.get_option('use_drt'):
binary_name = 'ImageDiff.exe'
- return self._build_path(self._options.configuration, binary_name)
+ return self._build_path(self.get_option('configuration'), binary_name)
def _path_to_wdiff(self):
return self.path_from_chromium_base('third_party', 'cygwin', 'bin',
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py
index 648ccad..8a6af56 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py
@@ -101,7 +101,6 @@ class DryrunDriver(base.Driver):
def __init__(self, port, image_path, options, executive):
self._port = port
- self._options = options
self._image_path = image_path
self._executive = executive
self._layout_tests_dir = None
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
index 81c3732..978a557 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
@@ -29,6 +29,8 @@
import sys
import unittest
+from webkitpy.tool import mocktool
+
import chromium_gpu
import chromium_linux
import chromium_mac
@@ -52,21 +54,11 @@ class FactoryTest(unittest.TestCase):
# FIXME: The ports themselves should expose what options they require,
# instead of passing generic "options".
- class WebKitOptions(object):
- """Represents the minimum options for WebKit port."""
- def __init__(self):
- self.pixel_tests = False
-
- class ChromiumOptions(WebKitOptions):
- """Represents minimum options for Chromium port."""
- def __init__(self):
- FactoryTest.WebKitOptions.__init__(self)
- self.chromium = True
-
def setUp(self):
self.real_sys_platform = sys.platform
- self.webkit_options = FactoryTest.WebKitOptions()
- self.chromium_options = FactoryTest.ChromiumOptions()
+ self.webkit_options = mocktool.MockOptions(pixel_tests=False)
+ self.chromium_options = mocktool.MockOptions(pixel_tests=False,
+ chromium=True)
def tearDown(self):
sys.platform = self.real_sys_platform
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py
index bffc860..8d94bb5 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome.py
@@ -24,6 +24,30 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from __future__ import with_statement
+
+import codecs
+import os
+
+
+def _test_expectations_overrides(port, super):
+ # The chrome ports use the regular overrides plus anything in the
+ # official test_expectations as well. Hopefully we don't get collisions.
+ chromium_overrides = super.test_expectations_overrides(port)
+
+ # FIXME: It used to be that AssertionError would get raised by
+ # path_from_chromium_base() if we weren't in a Chromium checkout, but
+ # this changed in r60427. This should probably be changed back.
+ overrides_path = port.path_from_chromium_base('webkit', 'tools',
+ 'layout_tests', 'test_expectations_chrome.txt')
+ if not os.path.exists(overrides_path):
+ return chromium_overrides
+
+ with codecs.open(overrides_path, "r", "utf-8") as file:
+ if chromium_overrides:
+ return chromium_overrides + file.read()
+ else:
+ return file.read()
def GetGoogleChromePort(**kwargs):
"""Some tests have slightly different results when compiled as Google
@@ -41,6 +65,11 @@ def GetGoogleChromePort(**kwargs):
paths.insert(0, self._webkit_baseline_path(
'google-chrome-linux32'))
return paths
+
+ def test_expectations_overrides(self):
+ return _test_expectations_overrides(self,
+ chromium_linux.ChromiumLinuxPort)
+
return GoogleChromeLinux32Port(**kwargs)
elif port_name == 'google-chrome-linux64':
import chromium_linux
@@ -52,6 +81,11 @@ def GetGoogleChromePort(**kwargs):
paths.insert(0, self._webkit_baseline_path(
'google-chrome-linux64'))
return paths
+
+ def test_expectations_overrides(self):
+ return _test_expectations_overrides(self,
+ chromium_linux.ChromiumLinuxPort)
+
return GoogleChromeLinux64Port(**kwargs)
elif port_name.startswith('google-chrome-mac'):
import chromium_mac
@@ -63,6 +97,11 @@ def GetGoogleChromePort(**kwargs):
paths.insert(0, self._webkit_baseline_path(
'google-chrome-mac'))
return paths
+
+ def test_expectations_overrides(self):
+ return _test_expectations_overrides(self,
+ chromium_mac.ChromiumMacPort)
+
return GoogleChromeMacPort(**kwargs)
elif port_name.startswith('google-chrome-win'):
import chromium_win
@@ -74,5 +113,10 @@ def GetGoogleChromePort(**kwargs):
paths.insert(0, self._webkit_baseline_path(
'google-chrome-win'))
return paths
+
+ def test_expectations_overrides(self):
+ return _test_expectations_overrides(self,
+ chromium_win.ChromiumWinPort)
+
return GoogleChromeWinPort(**kwargs)
raise NotImplementedError('unsupported port: %s' % port_name)
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py
index 85e9338..c4c885d 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/google_chrome_unittest.py
@@ -24,8 +24,12 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import codecs
import os
import unittest
+
+import base_unittest
+import factory
import google_chrome
@@ -35,6 +39,7 @@ class GetGoogleChromePortTest(unittest.TestCase):
'google-chrome-mac', 'google-chrome-win')
for port in test_ports:
self._verify_baseline_path(port, port)
+ self._verify_expectations_overrides(port)
self._verify_baseline_path('google-chrome-mac', 'google-chrome-mac-leopard')
self._verify_baseline_path('google-chrome-win', 'google-chrome-win-xp')
@@ -45,3 +50,53 @@ class GetGoogleChromePortTest(unittest.TestCase):
options=None)
path = port.baseline_search_path()[0]
self.assertEqual(expected_path, os.path.split(path)[1])
+
+ def _verify_expectations_overrides(self, port_name):
+ # FIXME: make this more robust when we have the Tree() abstraction.
+ # we should be able to test for the files existing or not, and
+ # be able to control the contents better.
+
+ chromium_port = factory.get("chromium-mac")
+ chromium_overrides = chromium_port.test_expectations_overrides()
+ port = google_chrome.GetGoogleChromePort(port_name=port_name,
+ options=None)
+
+ orig_exists = os.path.exists
+ orig_open = codecs.open
+ expected_string = "// hello, world\n"
+
+ def mock_exists_chrome_not_found(path):
+ if 'test_expectations_chrome.txt' in path:
+ return False
+ return orig_exists(path)
+
+ def mock_exists_chrome_found(path):
+ if 'test_expectations_chrome.txt' in path:
+ return True
+ return orig_exists(path)
+
+ def mock_open(path, mode, encoding):
+ if 'test_expectations_chrome.txt' in path:
+ return base_unittest.NewStringIO(expected_string)
+ return orig_open(path, mode, encoding)
+
+ try:
+ os.path.exists = mock_exists_chrome_not_found
+ chrome_overrides = port.test_expectations_overrides()
+ self.assertEqual(chromium_overrides, chrome_overrides)
+
+ os.path.exists = mock_exists_chrome_found
+ codecs.open = mock_open
+ chrome_overrides = port.test_expectations_overrides()
+ if chromium_overrides:
+ self.assertEqual(chrome_overrides,
+ chromium_overrides + expected_string)
+ else:
+ self.assertEqual(chrome_overrides, expected_string)
+ finally:
+ os.path.exists = orig_exists
+ codecs.open = orig_open
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock.py
new file mode 100644
index 0000000..73200a0
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged
+# Copyright (C) 2010 Andras Becsi (abecsi@inf.u-szeged.hu), University of Szeged
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""This class helps to block NRWT threads when more NRWTs run
+http and websocket tests in a same time."""
+
+import glob
+import os
+import sys
+import tempfile
+import time
+
+
+class HttpLock(object):
+
+ def __init__(self, lock_path, lock_file_prefix="WebKitHttpd.lock.",
+ guard_lock="WebKit.lock"):
+ if not lock_path:
+ self._lock_path = tempfile.gettempdir()
+ self._lock_file_prefix = lock_file_prefix
+ self._lock_file_path_prefix = os.path.join(self._lock_path,
+ self._lock_file_prefix)
+ self._guard_lock_file = os.path.join(self._lock_path, guard_lock)
+ self._process_lock_file_name = ""
+
+ def cleanup_http_lock(self):
+ """Delete the lock file if exists."""
+ if os.path.exists(self._process_lock_file_name):
+ os.unlink(self._process_lock_file_name)
+
+ def _extract_lock_number(self, lock_file_name):
+ """Return the lock number from lock file."""
+ prefix_length = len(self._lock_file_path_prefix)
+ return int(lock_file_name[prefix_length:])
+
+ def _lock_file_list(self):
+ """Return the list of lock files sequentially."""
+ lock_list = glob.glob(self._lock_file_path_prefix + '*')
+ lock_list.sort(key=self._extract_lock_number)
+ return lock_list
+
+ def _next_lock_number(self):
+ """Return the next available lock number."""
+ lock_list = self._lock_file_list()
+ if not lock_list:
+ return 0
+ return self._extract_lock_number(lock_list[-1]) + 1
+
+ def _check_pid(self, current_pid):
+ """Return True if pid is alive, otherwise return False."""
+ try:
+ os.kill(current_pid, 0)
+ except OSError:
+ return False
+ else:
+ return True
+
+ def _curent_lock_pid(self):
+ """Return with the current lock pid. If the lock is not valid
+ it deletes the lock file."""
+ lock_list = self._lock_file_list()
+ if not lock_list:
+ return
+ try:
+ current_lock_file = open(lock_list[0], 'r')
+ current_pid = current_lock_file.readline()
+ current_lock_file.close()
+ if not (current_pid and
+ sys.platform in ('darwin', 'linux2') and
+ self._check_pid(int(current_pid))):
+ os.unlink(lock_list[0])
+ return
+ except IOError, OSError:
+ return
+ return int(current_pid)
+
+ def _create_lock_file(self):
+ """The lock files are used to schedule the running test sessions in first
+ come first served order. The sequential guard lock ensures that the lock
+ numbers are sequential."""
+ while(True):
+ try:
+ sequential_guard_lock = os.open(self._guard_lock_file,
+ os.O_CREAT | os.O_NONBLOCK | os.O_EXCL)
+
+ self._process_lock_file_name = (self._lock_file_path_prefix +
+ str(self._next_lock_number()))
+ lock_file = open(self._process_lock_file_name, 'w')
+ lock_file.write(str(os.getpid()))
+ lock_file.close()
+ os.close(sequential_guard_lock)
+ os.unlink(self._guard_lock_file)
+ break
+ except OSError:
+ pass
+
+ def wait_for_httpd_lock(self):
+ """Create a lock file and wait until it's turn comes."""
+ self._create_lock_file()
+ while self._curent_lock_pid() != os.getpid():
+ time.sleep(1)
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock_unittest.py
new file mode 100644
index 0000000..85c760a
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_lock_unittest.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import glob
+import http_lock
+import os
+import unittest
+
+
+class HttpLockTest(unittest.TestCase):
+
+ def __init__(self, testFunc):
+ self.http_lock_obj = http_lock.HttpLock(None, "WebKitTestHttpd.lock.", "WebKitTest.lock")
+ self.lock_file_path_prefix = os.path.join(self.http_lock_obj._lock_path,
+ self.http_lock_obj._lock_file_prefix)
+ self.lock_file_name = self.lock_file_path_prefix + "0"
+ self.guard_lock_file = self.http_lock_obj._guard_lock_file
+ self.clean_all_lockfile()
+ unittest.TestCase.__init__(self, testFunc)
+
+ def clean_all_lockfile(self):
+ if os.path.exists(self.guard_lock_file):
+ os.unlink(self.guard_lock_file)
+ lock_list = glob.glob(self.lock_file_path_prefix + '*')
+ for file_name in lock_list:
+ os.unlink(file_name)
+
+ def assertEqual(self, first, second):
+ if first != second:
+ self.clean_all_lockfile()
+ unittest.TestCase.assertEqual(self, first, second)
+
+ def _check_lock_file(self):
+ if os.path.exists(self.lock_file_name):
+ pid = os.getpid()
+ lock_file = open(self.lock_file_name, 'r')
+ lock_file_pid = lock_file.readline()
+ lock_file.close()
+ self.assertEqual(pid, int(lock_file_pid))
+ return True
+ return False
+
+ def test_lock_lifecycle(self):
+ self.http_lock_obj._create_lock_file()
+
+ self.assertEqual(True, self._check_lock_file())
+ self.assertEqual(1, self.http_lock_obj._next_lock_number())
+
+ self.http_lock_obj.cleanup_http_lock()
+
+ self.assertEqual(False, self._check_lock_file())
+ self.assertEqual(0, self.http_lock_obj._next_lock_number())
+
+ def test_extract_lock_number(self,):
+ lock_file_list = (
+ self.lock_file_path_prefix + "00",
+ self.lock_file_path_prefix + "9",
+ self.lock_file_path_prefix + "001",
+ self.lock_file_path_prefix + "021",
+ )
+
+ expected_number_list = (0, 9, 1, 21)
+
+ for lock_file, expected in zip(lock_file_list, expected_number_list):
+ self.assertEqual(self.http_lock_obj._extract_lock_number(lock_file), expected)
+
+ def test_lock_file_list(self):
+ lock_file_list = [
+ self.lock_file_path_prefix + "6",
+ self.lock_file_path_prefix + "1",
+ self.lock_file_path_prefix + "4",
+ self.lock_file_path_prefix + "3",
+ ]
+
+ expected_file_list = [
+ self.lock_file_path_prefix + "1",
+ self.lock_file_path_prefix + "3",
+ self.lock_file_path_prefix + "4",
+ self.lock_file_path_prefix + "6",
+ ]
+
+ for file_name in lock_file_list:
+ open(file_name, 'w')
+
+ self.assertEqual(self.http_lock_obj._lock_file_list(), expected_file_list)
+
+ for file_name in lock_file_list:
+ os.unlink(file_name)
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py
index 327b19e..d383a4c 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py
@@ -35,7 +35,7 @@ import port_testcase
class MacTest(port_testcase.PortTestCase):
- def make_port(self, options=port_testcase.MockOptions()):
+ def make_port(self, options=port_testcase.mock_options):
if sys.platform != 'darwin':
return None
port_obj = mac.MacPort(options=options)
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py
index 47597d6..04ada50 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/port_testcase.py
@@ -32,20 +32,15 @@ import os
import tempfile
import unittest
-
-class MockOptions(object):
- def __init__(self,
- results_directory='layout-test-results',
- use_apache=True,
- configuration='Release'):
- self.results_directory = results_directory
- self.use_apache = use_apache
- self.configuration = configuration
+from webkitpy.tool import mocktool
+mock_options = mocktool.MockOptions(results_directory='layout-test-results',
+ use_apache=True,
+ configuration='Release')
class PortTestCase(unittest.TestCase):
"""Tests the WebKit port implementation."""
- def make_port(self, options=MockOptions()):
+ def make_port(self, options=mock_options):
"""Override in subclass."""
raise NotImplementedError()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py
index 3b81167..3691c5a 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py
@@ -215,14 +215,11 @@ class TestPort(base.Port):
def name(self):
return self._name
- def options(self):
- return self._options
-
def _path_to_wdiff(self):
return None
def results_directory(self):
- return '/tmp/' + self._options.results_directory
+ return '/tmp/' + self.get_option('results_directory')
def setup_test_run(self):
pass
@@ -285,7 +282,6 @@ class TestDriver(base.Driver):
def __init__(self, port, image_path, options, executive):
self._port = port
self._image_path = image_path
- self._options = options
self._executive = executive
self._image_written = False
@@ -302,7 +298,7 @@ class TestDriver(base.Driver):
if test.hang:
time.sleep((float(timeoutms) * 4) / 1000.0)
- if self._port.options().pixel_tests and test.actual_image:
+ if self._port.get_option('pixel_tests') and test.actual_image:
with open(self._image_path, 'w') as file:
file.write(test.actual_image)
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py
index ed19c09..c940f1e 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py
@@ -65,9 +65,7 @@ class WebKitPort(base.Port):
# FIXME: disable pixel tests until they are run by default on the
# build machines.
- if self._options and (not hasattr(self._options, "pixel_tests") or
- self._options.pixel_tests is None):
- self._options.pixel_tests = False
+ self.set_option_default('pixel_tests', False)
def baseline_path(self):
return self._webkit_baseline_path(self._name)
@@ -86,7 +84,7 @@ class WebKitPort(base.Port):
def _build_driver(self):
exit_code = self._executive.run_command([
self.script_path("build-dumprendertree"),
- self.flag_from_configuration(self._options.configuration),
+ self.flag_from_configuration(self.get_option('configuration')),
], return_exit_code=True)
if exit_code != 0:
_log.error("Failed to build DumpRenderTree")
@@ -101,11 +99,11 @@ class WebKitPort(base.Port):
return True
def check_build(self, needs_http):
- if self._options.build and not self._build_driver():
+ if self.get_option('build') and not self._build_driver():
return False
if not self._check_driver():
return False
- if self._options.pixel_tests:
+ if self.get_option('pixel_tests'):
if not self.check_image_diff():
return False
if not self._check_port_build():
@@ -184,7 +182,7 @@ class WebKitPort(base.Port):
def results_directory(self):
# Results are store relative to the built products to make it easy
# to have multiple copies of webkit checked out and built.
- return self._build_path(self._options.results_directory)
+ return self._build_path(self.get_option('results_directory'))
def setup_test_run(self):
# This port doesn't require any specific configuration.
@@ -360,7 +358,7 @@ class WebKitPort(base.Port):
if not self._cached_build_root:
self._cached_build_root = self._webkit_build_directory([
"--configuration",
- self.flag_from_configuration(self._options.configuration),
+ self.flag_from_configuration(self.get_option('configuration')),
])
return os.path.join(self._cached_build_root, *comps)
@@ -401,7 +399,6 @@ class WebKitDriver(base.Driver):
def __init__(self, port, image_path, options, executive=Executive()):
self._port = port
self._image_path = image_path
- self._options = options
self._executive = executive
self._driver_tempdir = tempfile.mkdtemp(prefix='DumpRenderTree-')
@@ -414,17 +411,17 @@ class WebKitDriver(base.Driver):
if self._image_path:
driver_args.append('--pixel-tests')
- if self._options.use_drt:
- if self._options.accelerated_compositing:
+ if self._port.get_option('use_drt'):
+ if self._port.get_option('accelerated_compositing'):
driver_args.append('--enable-accelerated-compositing')
- if self._options.accelerated_2d_canvas:
+ if self._port.get_option('accelerated_2d_canvas'):
driver_args.append('--enable-accelerated-2d-canvas')
return driver_args
def start(self):
- command = self._command_wrapper(self._options.wrapper)
+ command = self._command_wrapper(self._port.get_option('wrapper'))
command += [self._port._path_to_driver(), '-']
command += self._driver_args()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py
index 7346671..926bc04 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py
@@ -124,12 +124,13 @@ class PyWebSocket(http_server.Lighttpd):
if self._root:
self._layout_tests = os.path.abspath(self._root)
self._web_socket_tests = os.path.abspath(
- os.path.join(self._root, 'websocket', 'tests'))
+ os.path.join(self._root, 'http', 'tests',
+ 'websocket', 'tests'))
else:
try:
self._layout_tests = self._port_obj.layout_tests_dir()
self._web_socket_tests = os.path.join(self._layout_tests,
- 'websocket', 'tests')
+ 'http', 'tests', 'websocket', 'tests')
except:
self._web_socket_tests = None
@@ -164,10 +165,10 @@ class PyWebSocket(http_server.Lighttpd):
pywebsocket_script = os.path.join(pywebsocket_base, 'mod_pywebsocket',
'standalone.py')
start_cmd = [
- python_interp, pywebsocket_script,
+ python_interp, '-u', pywebsocket_script,
'--server-host', '127.0.0.1',
'--port', str(self._port),
- '--document-root', self._layout_tests,
+ '--document-root', os.path.join(self._layout_tests, 'http', 'tests'),
'--scan-dir', self._web_socket_tests,
'--cgi-paths', '/websocket/tests',
'--log-file', error_log,
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py
index e57ceb2..a47370d 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py
@@ -57,8 +57,9 @@ import time
import urllib
import zipfile
+from webkitpy.common.system import path
from webkitpy.common.system import user
-from webkitpy.common.system.executive import run_command, ScriptError
+from webkitpy.common.system.executive import Executive, ScriptError
import webkitpy.common.checkout.scm as scm
import port
@@ -81,58 +82,6 @@ ARCHIVE_DIR_NAME_DICT = {'win': 'webkit-rel',
'linux-canary': 'webkit-rel-linux-webkit-org'}
-# FIXME: Should be rolled into webkitpy.Executive
-def run_shell_with_return_code(command, print_output=False):
- """Executes a command and returns the output and process return code.
-
- Args:
- command: program and arguments.
- print_output: if true, print the command results to standard output.
-
- Returns:
- command output, return code
- """
-
- # Use a shell for subcommands on Windows to get a PATH search.
- # FIXME: shell=True is a trail of tears, and should be removed.
- use_shell = sys.platform.startswith('win')
- # Note: Not thread safe: http://bugs.python.org/issue2320
- p = subprocess.Popen(command, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT, shell=use_shell)
- if print_output:
- output_array = []
- while True:
- line = p.stdout.readline()
- if not line:
- break
- if print_output:
- print line.strip('\n')
- output_array.append(line)
- output = ''.join(output_array)
- else:
- output = p.stdout.read()
- p.wait()
- p.stdout.close()
-
- return output, p.returncode
-
-
-# FIXME: Should be rolled into webkitpy.Executive
-def run_shell(command, print_output=False):
- """Executes a command and returns the output.
-
- Args:
- command: program and arguments.
- print_output: if true, print the command results to standard output.
-
- Returns:
- command output
- """
-
- output, return_code = run_shell_with_return_code(command, print_output)
- return output
-
-
def log_dashed_string(text, platform, logging_level=logging.INFO):
"""Log text message with dashes on both sides."""
@@ -547,7 +496,7 @@ class Rebaseliner(object):
"""
if is_image:
- return self._port.diff_image(output1, output2)
+ return self._port.diff_image(output1, output2, None, 0)
else:
return self._port.compare_text(output1, output2)
@@ -628,7 +577,6 @@ class Rebaseliner(object):
base_file = get_result_file_fullpath(self._options.html_directory,
baseline_filename, self._platform,
'old')
- # FIXME: This assumes run_shell returns a byte array.
# We should be using an explicit encoding here.
with open(base_file, "wb") as file:
file.write(output)
@@ -642,12 +590,12 @@ class Rebaseliner(object):
diff_file = get_result_file_fullpath(
self._options.html_directory, baseline_filename,
self._platform, 'diff')
- # FIXME: This assumes run_shell returns a byte array, not unicode()
with open(diff_file, 'wb') as file:
file.write(output)
_log.info(' Html: created baseline diff file: "%s".',
diff_file)
+
class HtmlGenerator(object):
"""Class to generate rebaselining result comparison html."""
@@ -694,14 +642,20 @@ class HtmlGenerator(object):
'<img style="width: 200" src="%(uri)s" /></a></td>')
HTML_TR = '<tr>%s</tr>'
- def __init__(self, target_port, options, platforms, rebaselining_tests):
+ def __init__(self, target_port, options, platforms, rebaselining_tests,
+ executive):
self._html_directory = options.html_directory
self._target_port = target_port
self._platforms = platforms
self._rebaselining_tests = rebaselining_tests
+ self._executive = executive
self._html_file = os.path.join(options.html_directory,
'rebaseline.html')
+ def abspath_to_uri(self, filename):
+ """Converts an absolute path to a file: URI."""
+ return path.abspath_to_uri(filename, self._executive)
+
def generate_html(self):
"""Generate html file for rebaselining result comparison."""
@@ -769,14 +723,13 @@ class HtmlGenerator(object):
links = ''
if os.path.exists(old_file):
links += html_td_link % {
- 'uri': self._target_port.filename_to_uri(old_file),
+ 'uri': self.abspath_to_uri(old_file),
'name': baseline_filename}
else:
_log.info(' No old baseline file: "%s"', old_file)
links += self.HTML_TD_NOLINK % ''
- links += html_td_link % {'uri': self._target_port.filename_to_uri(
- new_file),
+ links += html_td_link % {'uri': self.abspath_to_uri(new_file),
'name': baseline_filename}
diff_file = get_result_file_fullpath(self._html_directory,
@@ -784,8 +737,8 @@ class HtmlGenerator(object):
'diff')
_log.info(' Baseline diff file: "%s"', diff_file)
if os.path.exists(diff_file):
- links += html_td_link % {'uri': self._target_port.filename_to_uri(
- diff_file), 'name': 'Diff'}
+ links += html_td_link % {'uri': self.abspath_to_uri(diff_file),
+ 'name': 'Diff'}
else:
_log.info(' No baseline diff file: "%s"', diff_file)
links += self.HTML_TD_NOLINK % ''
@@ -825,8 +778,7 @@ class HtmlGenerator(object):
if rows:
test_path = os.path.join(self._target_port.layout_tests_dir(),
test)
- html = self.HTML_TR_TEST % (
- self._target_port.filename_to_uri(test_path), test)
+ html = self.HTML_TR_TEST % (self.abspath_to_uri(test_path), test)
html += self.HTML_TEST_DETAIL % ' '.join(rows)
_log.debug(' html for test: %s', html)
@@ -867,7 +819,7 @@ def get_host_port_object(options):
return port_obj
-def main():
+def main(executive=Executive()):
"""Main function to produce new baselines."""
option_parser = optparse.OptionParser()
@@ -992,7 +944,8 @@ def main():
html_generator = HtmlGenerator(target_port_obj,
options,
rebaseline_platforms,
- rebaselining_tests)
+ rebaselining_tests,
+ executive=executive)
html_generator.generate_html()
if not options.quiet:
html_generator.show_html()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py
index 9ba3d6b..ef33a47 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests_unittest.py
@@ -30,10 +30,13 @@
"""Unit tests for rebaseline_chromium_webkit_tests.py."""
import os
+import sys
import unittest
+from webkitpy.tool import mocktool
from webkitpy.layout_tests import port
from webkitpy.layout_tests import rebaseline_chromium_webkit_tests
+from webkitpy.common.system.executive import Executive, ScriptError
class MockPort(object):
@@ -44,11 +47,6 @@ class MockPort(object):
return self.image_diff_exists
-class MockOptions(object):
- def __init__(self):
- self.configuration = None
-
-
def get_mock_get(config_expectations):
def mock_get(port_name, options):
return MockPort(config_expectations[options.configuration])
@@ -61,7 +59,8 @@ class TestGetHostPortObject(unittest.TestCase):
# that Image diff is (or isn't) present in the two configs.
port.get = get_mock_get({'Release': release_present,
'Debug': debug_present})
- options = MockOptions()
+ options = mocktool.MockOptions(configuration=None,
+ html_directory=None)
port_obj = rebaseline_chromium_webkit_tests.get_host_port_object(
options)
if valid_port_obj:
@@ -87,7 +86,8 @@ class TestGetHostPortObject(unittest.TestCase):
class TestRebaseliner(unittest.TestCase):
def make_rebaseliner(self):
- options = MockOptions()
+ options = mocktool.MockOptions(configuration=None,
+ html_directory=None)
host_port_obj = port.get('test', options)
target_options = options
target_port_obj = port.get('test', target_options)
@@ -118,5 +118,32 @@ class TestRebaseliner(unittest.TestCase):
self.assertFalse(rebaseliner._diff_baselines(image, image,
is_image=True))
+
+class TestHtmlGenerator(unittest.TestCase):
+ def make_generator(self, tests):
+ return rebaseline_chromium_webkit_tests.HtmlGenerator(
+ target_port=None,
+ options=mocktool.MockOptions(configuration=None,
+ html_directory='/tmp'),
+ platforms=['mac'],
+ rebaselining_tests=tests,
+ executive=Executive())
+
+ def test_generate_baseline_links(self):
+ orig_platform = sys.platform
+ orig_exists = os.path.exists
+
+ try:
+ sys.platform = 'darwin'
+ os.path.exists = lambda x: True
+ generator = self.make_generator(["foo.txt"])
+ links = generator._generate_baseline_links("foo", ".txt", "mac")
+ expected_links = '<td align=center><a href="file:///tmp/foo-expected-mac-old.txt">foo-expected.txt</a></td><td align=center><a href="file:///tmp/foo-expected-mac-new.txt">foo-expected.txt</a></td><td align=center><a href="file:///tmp/foo-expected-mac-diff.txt">Diff</a></td>'
+ self.assertEqual(links, expected_links)
+ finally:
+ sys.platform = orig_platform
+ os.path.exists = orig_exists
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
index e9c6d2c..9cc7895 100755
--- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
# Copyright (C) 2010 Google Inc. All rights reserved.
+# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -498,6 +499,12 @@ class TestRunner:
self._options.slow_time_out_ms)
return TestInfo(self._port, test_file, self._options.time_out_ms)
+ def _test_requires_lock(self, test_file):
+ """Return True if the test needs to be locked when
+ running multiple copies of NRWTs."""
+ split_path = test_file.split(os.sep)
+ return 'http' in split_path or 'websocket' in split_path
+
def _get_test_file_queue(self, test_files):
"""Create the thread safe queue of lists of (test filenames, test URIs)
tuples. Each TestShellThread pulls a list from this queue and runs
@@ -511,46 +518,47 @@ class TestRunner:
The Queue of lists of TestInfo objects.
"""
+ test_lists = []
+ tests_to_http_lock = []
if (self._options.experimental_fully_parallel or
self._is_single_threaded()):
- filename_queue = Queue.Queue()
for test_file in test_files:
- filename_queue.put(
- ('.', [self._get_test_info_for_file(test_file)]))
- return filename_queue
-
- tests_by_dir = {}
- for test_file in test_files:
- directory = self._get_dir_for_test_file(test_file)
- tests_by_dir.setdefault(directory, [])
- tests_by_dir[directory].append(
- self._get_test_info_for_file(test_file))
-
- # Sort by the number of tests in the dir so that the ones with the
- # most tests get run first in order to maximize parallelization.
- # Number of tests is a good enough, but not perfect, approximation
- # of how long that set of tests will take to run. We can't just use
- # a PriorityQueue until we move # to Python 2.6.
- test_lists = []
- http_tests = None
- for directory in tests_by_dir:
- test_list = tests_by_dir[directory]
- # Keep the tests in alphabetical order.
- # TODO: Remove once tests are fixed so they can be run in any
- # order.
- test_list.reverse()
- test_list_tuple = (directory, test_list)
- if directory == 'LayoutTests' + os.sep + 'http':
- http_tests = test_list_tuple
- else:
+ test_info = self._get_test_info_for_file(test_file)
+ if self._test_requires_lock(test_file):
+ tests_to_http_lock.append(test_info)
+ else:
+ test_lists.append((".", [test_info]))
+ else:
+ tests_by_dir = {}
+ for test_file in test_files:
+ directory = self._get_dir_for_test_file(test_file)
+ test_info = self._get_test_info_for_file(test_file)
+ if self._test_requires_lock(test_file):
+ tests_to_http_lock.append(test_info)
+ else:
+ tests_by_dir.setdefault(directory, [])
+ tests_by_dir[directory].append(test_info)
+ # Sort by the number of tests in the dir so that the ones with the
+ # most tests get run first in order to maximize parallelization.
+ # Number of tests is a good enough, but not perfect, approximation
+ # of how long that set of tests will take to run. We can't just use
+ # a PriorityQueue until we move to Python 2.6.
+ for directory in tests_by_dir:
+ test_list = tests_by_dir[directory]
+ # Keep the tests in alphabetical order.
+ # FIXME: Remove once tests are fixed so they can be run in any
+ # order.
+ test_list.reverse()
+ test_list_tuple = (directory, test_list)
test_lists.append(test_list_tuple)
- test_lists.sort(lambda a, b: cmp(len(b[1]), len(a[1])))
+ test_lists.sort(lambda a, b: cmp(len(b[1]), len(a[1])))
# Put the http tests first. There are only a couple hundred of them,
# but each http test takes a very long time to run, so sorting by the
# number of tests doesn't accurately capture how long they take to run.
- if http_tests:
- test_lists.insert(0, http_tests)
+ if tests_to_http_lock:
+ tests_to_http_lock.reverse()
+ test_lists.insert(0, ("tests_to_http_lock", tests_to_http_lock))
filename_queue = Queue.Queue()
for item in test_lists:
@@ -687,7 +695,7 @@ class TestRunner:
thread_timings.append({'name': thread.getName(),
'num_tests': thread.get_num_tests(),
'total_time': thread.get_total_time()})
- test_timings.update(thread.get_directory_timing_stats())
+ test_timings.update(thread.get_test_group_timing_stats())
individual_test_timings.extend(thread.get_test_results())
return (thread_timings, test_timings, individual_test_timings)
@@ -696,6 +704,10 @@ class TestRunner:
"""Returns whether the test runner needs an HTTP server."""
return self._contains_tests(self.HTTP_SUBDIR)
+ def needs_websocket(self):
+ """Returns whether the test runner needs a WEBSOCKET server."""
+ return self._contains_tests(self.WEBSOCKET_SUBDIR)
+
def set_up_run(self):
"""Configures the system to be ready to run tests.
@@ -728,14 +740,16 @@ class TestRunner:
if not result_summary:
return None
- if self.needs_http():
- self._printer.print_update('Starting HTTP server ...')
- self._port.start_http_server()
+ # Do not start when http locking is enabled.
+ if not self._options.wait_for_httpd:
+ if self.needs_http():
+ self._printer.print_update('Starting HTTP server ...')
+ self._port.start_http_server()
- if self._contains_tests(self.WEBSOCKET_SUBDIR):
- self._printer.print_update('Starting WebSocket server ...')
- self._port.start_websocket_server()
- # self._websocket_secure_server.Start()
+ if self.needs_websocket():
+ self._printer.print_update('Starting WebSocket server ...')
+ self._port.start_websocket_server()
+ # self._websocket_secure_server.Start()
return result_summary
@@ -826,10 +840,11 @@ class TestRunner:
sys.stdout.flush()
_log.debug("flushing stderr")
sys.stderr.flush()
- _log.debug("stopping http server")
- self._port.stop_http_server()
- _log.debug("stopping websocket server")
- self._port.stop_websocket_server()
+ if not self._options.wait_for_httpd:
+ _log.debug("stopping http server")
+ self._port.stop_http_server()
+ _log.debug("stopping websocket server")
+ self._port.stop_websocket_server()
_log.debug("stopping helper")
self._port.stop_helper()
@@ -1432,13 +1447,10 @@ def _set_up_derived_options(port_obj, options):
if not options.use_apache:
options.use_apache = sys.platform in ('darwin', 'linux2')
- if options.results_directory.startswith("/"):
- # Assume it's an absolute path and normalize.
- options.results_directory = port_obj.get_absolute_path(
- options.results_directory)
- else:
- # If it's a relative path, make the output directory relative to
- # Debug or Release.
+ if not os.path.isabs(options.results_directory):
+ # This normalizes the path to the build dir.
+ # FIXME: how this happens is not at all obvious; this is a dumb
+ # interface and should be cleaned up.
options.results_directory = port_obj.results_directory()
if not options.time_out_ms:
@@ -1588,13 +1600,12 @@ def parse_args(args=None):
optparse.make_option("--no-record-results", action="store_false",
default=True, dest="record_results",
help="Don't record the results."),
+ optparse.make_option("--wait-for-httpd", action="store_true",
+ default=False, dest="wait_for_httpd",
+ help="Wait for http locks."),
# old-run-webkit-tests also has HTTP toggle options:
# --[no-]http Run (or do not run) http tests
# (default: run)
- # --[no-]wait-for-httpd Wait for httpd if some other test
- # session is using it already (same
- # as WEBKIT_WAIT_FOR_HTTPD=1).
- # (default: 0)
]
test_options = [
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
index 6fe99d6..a716cec 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
@@ -1,5 +1,6 @@
#!/usr/bin/python
# Copyright (C) 2010 Google Inc. All rights reserved.
+# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -33,6 +34,7 @@ import codecs
import logging
import os
import Queue
+import shutil
import sys
import tempfile
import thread
@@ -70,7 +72,7 @@ def passing_run(args=[], port_obj=None, record_results=False,
# We use the glob to test that globbing works.
new_args.extend(['passes',
'http/tests',
- 'websocket/tests',
+ 'http/tests/websocket/tests',
'failures/expected/*'])
options, parsed_args = run_webkit_tests.parse_args(new_args)
if port_obj is None:
@@ -88,7 +90,7 @@ def logging_run(args=[], tests_included=False):
if not tests_included:
new_args.extend(['passes',
'http/tests',
- 'websocket/tests',
+ 'http/tests/websocket/tests',
'failures/expected/*'])
options, parsed_args = run_webkit_tests.parse_args(new_args)
user = MockUser()
@@ -232,10 +234,37 @@ class MainTest(unittest.TestCase):
self.assertFalse(err.empty())
self.assertEqual(user.url, '/tmp/layout-test-results/results.html')
+ def test_results_directory_absolute(self):
+ # We run a configuration that should fail, to generate output, then
+ # look for what the output results url was.
+
+ tmpdir = tempfile.mkdtemp()
+ res, out, err, user = logging_run(['--results-directory=' + tmpdir],
+ tests_included=True)
+ self.assertEqual(user.url, os.path.join(tmpdir, 'results.html'))
+ shutil.rmtree(tmpdir, ignore_errors=True)
+
+ def test_results_directory_default(self):
+ # We run a configuration that should fail, to generate output, then
+ # look for what the output results url was.
+
+ # This is the default location.
+ res, out, err, user = logging_run(tests_included=True)
+ self.assertEqual(user.url, '/tmp/layout-test-results/results.html')
+
+ def test_results_directory_relative(self):
+ # We run a configuration that should fail, to generate output, then
+ # look for what the output results url was.
+
+ res, out, err, user = logging_run(['--results-directory=foo'],
+ tests_included=True)
+ self.assertEqual(user.url, '/tmp/foo/results.html')
+
+
def _mocked_open(original_open, file_list):
def _wrapper(name, mode, encoding):
- if name.find("-expected.") != -1 and mode == "w":
+ if name.find("-expected.") != -1 and mode.find("w") != -1:
# we don't want to actually write new baselines, so stub these out
name.replace('\\', '/')
file_list.append(name)
@@ -251,7 +280,10 @@ class RebaselineTest(unittest.TestCase):
baseline = file + "-expected" + ext
self.assertTrue(any(f.find(baseline) != -1 for f in file_list))
- def test_reset_results(self):
+ # FIXME: This test is failing on the bots. Also, this test touches the
+ # file system. Unit tests should not read or write the file system.
+ # https://bugs.webkit.org/show_bug.cgi?id=47879
+ def disabled_test_reset_results(self):
file_list = []
original_open = codecs.open
try:
@@ -294,6 +326,11 @@ class RebaselineTest(unittest.TestCase):
codecs.open = original_open
+class TestRunnerWrapper(run_webkit_tests.TestRunner):
+ def _get_test_info_for_file(self, test_file):
+ return test_file
+
+
class TestRunnerTest(unittest.TestCase):
def test_results_html(self):
mock_port = Mock()
@@ -314,6 +351,52 @@ class TestRunnerTest(unittest.TestCase):
html = runner._results_html(["test_path"], {}, "Title", override_time="time")
self.assertEqual(html, expected_html)
+ def queue_to_list(self, queue):
+ queue_list = []
+ while(True):
+ try:
+ queue_list.append(queue.get_nowait())
+ except Queue.Empty:
+ break
+ return queue_list
+
+ def test_get_test_file_queue(self):
+ # Test that _get_test_file_queue in run_webkit_tests.TestRunner really
+ # put the http tests first in the queue.
+ runner = TestRunnerWrapper(port=Mock(), options=Mock(), printer=Mock())
+ runner._options.experimental_fully_parallel = False
+
+ test_list = [
+ "LayoutTests/websocket/tests/unicode.htm",
+ "LayoutTests/animations/keyframes.html",
+ "LayoutTests/http/tests/security/view-source-no-refresh.html",
+ "LayoutTests/websocket/tests/websocket-protocol-ignored.html",
+ "LayoutTests/fast/css/display-none-inline-style-change-crash.html",
+ "LayoutTests/http/tests/xmlhttprequest/supported-xml-content-types.html",
+ "LayoutTests/dom/html/level2/html/HTMLAnchorElement03.html",
+ "LayoutTests/ietestcenter/Javascript/11.1.5_4-4-c-1.html",
+ "LayoutTests/dom/html/level2/html/HTMLAnchorElement06.html",
+ ]
+
+ expected_tests_to_http_lock = set([
+ 'LayoutTests/websocket/tests/unicode.htm',
+ 'LayoutTests/http/tests/security/view-source-no-refresh.html',
+ 'LayoutTests/websocket/tests/websocket-protocol-ignored.html',
+ 'LayoutTests/http/tests/xmlhttprequest/supported-xml-content-types.html',
+ ])
+
+ runner._options.child_processes = 1
+ test_queue_for_single_thread = runner._get_test_file_queue(test_list)
+ runner._options.child_processes = 2
+ test_queue_for_multi_thread = runner._get_test_file_queue(test_list)
+
+ single_thread_results = self.queue_to_list(test_queue_for_single_thread)
+ multi_thread_results = self.queue_to_list(test_queue_for_multi_thread)
+
+ self.assertEqual("tests_to_http_lock", single_thread_results[0][0])
+ self.assertEqual(expected_tests_to_http_lock, set(single_thread_results[0][1]))
+ self.assertEqual("tests_to_http_lock", multi_thread_results[0][0])
+ self.assertEqual(expected_tests_to_http_lock, set(multi_thread_results[0][1]))
class DryrunTest(unittest.TestCase):
# FIXME: it's hard to know which platforms are safe to test; the
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py
index 1ad0fe6..0b05802 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py
@@ -104,7 +104,7 @@ class ImageDiff(test_type_base.TestTypeBase):
self.FILENAME_SUFFIX_EXPECTED + '.png')
expected_image = port.expected_image(filename)
- with codecs.open(actual_filename, 'r', None) as file:
+ with codecs.open(actual_filename, 'r+b', None) as file:
actual_image = file.read()
result = port.diff_image(expected_image, actual_image,
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py
index 3a6e92b..dcc64a3 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py
@@ -161,7 +161,10 @@ class TestTypeBase(object):
def _write_into_file_at_path(self, file_path, contents, encoding):
"""This method assumes that byte_array is already encoded
into the right format."""
- with codecs.open(file_path, "w", encoding=encoding) as file:
+ open_mode = 'w'
+ if encoding is None:
+ open_mode = 'w+b'
+ with codecs.open(file_path, open_mode, encoding=encoding) as file:
file.write(contents)
def write_output_files(self, filename, file_type,