summaryrefslogtreecommitdiff
path: root/Tools/Scripts/webkitpy
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/Scripts/webkitpy')
-rw-r--r--Tools/Scripts/webkitpy/common/config/committers.py4
-rw-r--r--Tools/Scripts/webkitpy/common/system/executive.py9
-rw-r--r--Tools/Scripts/webkitpy/common/system/executive_unittest.py37
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/base.py107
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py30
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/chromium.py9
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py9
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py6
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/driver.py282
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py200
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/gtk.py2
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/qt.py10
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/webkit.py397
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py181
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver.py6
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py2
-rw-r--r--Tools/Scripts/webkitpy/performance_tests/perftest.py4
-rw-r--r--Tools/Scripts/webkitpy/style/checker.py9
-rw-r--r--Tools/Scripts/webkitpy/style/checkers/cpp.py7
-rw-r--r--Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py6
-rw-r--r--Tools/Scripts/webkitpy/test/main.py5
21 files changed, 644 insertions, 678 deletions
diff --git a/Tools/Scripts/webkitpy/common/config/committers.py b/Tools/Scripts/webkitpy/common/config/committers.py
index 4a55d495c..efa5aac89 100644
--- a/Tools/Scripts/webkitpy/common/config/committers.py
+++ b/Tools/Scripts/webkitpy/common/config/committers.py
@@ -113,6 +113,7 @@ contributors_who_are_not_committers = [
Contributor("Alexandre Elias", "aelias@chromium.org"),
Contributor("Alexey Marinichev", ["amarinichev@chromium.org", "amarinichev@google.com"], "amarinichev"),
Contributor("Andras Piroska", "pandras@inf.u-szeged.hu", "andris88"),
+ Contributor("Andrei Bucur", "abucur@adobe.com", "abucur"),
Contributor("Anne van Kesteren", "annevankesteren+webkit@gmail.com", "annevk"),
Contributor("Annie Sullivan", "sullivan@chromium.org", "annie"),
Contributor("Aryeh Gregor", "ayg@aryeh.name", "AryehGregor"),
@@ -142,12 +143,15 @@ contributors_who_are_not_committers = [
Contributor("John Mellor", "johnme@chromium.org"),
Contributor("Kulanthaivel Palanichamy", "kulanthaivel@codeaurora.org", "kvel"),
Contributor(u"Michael Br\u00fcning", "michael.bruning@nokia.com", "mibrunin"),
+ Contributor("Mihai Balan", "mibalan@adobe.com", "miChou"),
Contributor("Min Qin", "qinmin@chromium.org"),
Contributor("Nandor Huszka", "hnandor@inf.u-szeged.hu", "hnandor"),
Contributor("Oliver Varga", ["voliver@inf.u-szeged.hu", "Varga.Oliver@stud.u-szeged.hu"], "TwistO"),
Contributor("Peter Gal", "galpeter@inf.u-szeged.hu", "elecro"),
Contributor("Peter Linss", "peter.linss@hp.com", "plinss"),
+ Contributor("Pravin D", "pravind.2k4@gmail.com", 'pravind'),
Contributor("Radar WebKit Bug Importer", "webkit-bug-importer@group.apple.com"),
+ Contributor("Raul Hudea", "rhudea@adobe.com", "rhudea"),
Contributor("Roland Takacs", "rtakacs@inf.u-szeged.hu", "rtakacs"),
Contributor("Szilard Ledan-Muntean", "szledan@inf.u-szeged.hu", "szledan"),
Contributor("Tab Atkins", ["tabatkins@google.com", "jackalmage@gmail.com"], "tabatkins"),
diff --git a/Tools/Scripts/webkitpy/common/system/executive.py b/Tools/Scripts/webkitpy/common/system/executive.py
index cb36b5dc0..1099e07fb 100644
--- a/Tools/Scripts/webkitpy/common/system/executive.py
+++ b/Tools/Scripts/webkitpy/common/system/executive.py
@@ -27,10 +27,9 @@
# (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 multiprocessing
-import ctypes
import errno
import logging
+import multiprocessing
import os
import StringIO
import signal
@@ -211,12 +210,18 @@ class Executive(object):
continue
if e.errno == errno.ESRCH: # The process does not exist.
return
+ if e.errno == errno.EPIPE: # The process has exited already on cygwin
+ return
if e.errno == errno.ECHILD:
# Can't wait on a non-child process, but the kill worked.
return
raise
def _win32_check_running_pid(self, pid):
+ # importing ctypes at the top-level seems to cause weird crashes at
+ # exit under cygwin on apple's win port. Only win32 needs cygwin, so
+ # we import it here instead. See https://bugs.webkit.org/show_bug.cgi?id=91682
+ import ctypes
class PROCESSENTRY32(ctypes.Structure):
_fields_ = [("dwSize", ctypes.c_ulong),
diff --git a/Tools/Scripts/webkitpy/common/system/executive_unittest.py b/Tools/Scripts/webkitpy/common/system/executive_unittest.py
index 212896a4a..c041b6372 100644
--- a/Tools/Scripts/webkitpy/common/system/executive_unittest.py
+++ b/Tools/Scripts/webkitpy/common/system/executive_unittest.py
@@ -28,6 +28,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
+import errno
import signal
import subprocess
import sys
@@ -77,8 +78,6 @@ def command_line(cmd, *args):
class ExecutiveTest(unittest.TestCase):
def assert_interpreter_for_content(self, intepreter, content):
fs = MockFileSystem()
- file_path = None
- file_interpreter = None
tempfile, temp_name = fs.open_binary_tempfile('')
tempfile.write(content)
@@ -166,26 +165,12 @@ class ExecutiveTest(unittest.TestCase):
else:
expected_exit_code = -signal.SIGKILL
self.assertEqual(process.wait(), expected_exit_code)
+
# Killing again should fail silently.
executive.kill_process(process.pid)
- def _assert_windows_image_name(self, name, expected_windows_name):
- executive = Executive()
- windows_name = executive._windows_image_name(name)
- self.assertEqual(windows_name, expected_windows_name)
-
- def test_windows_image_name(self):
- self._assert_windows_image_name("foo", "foo.exe")
- self._assert_windows_image_name("foo.exe", "foo.exe")
- self._assert_windows_image_name("foo.com", "foo.com")
- # If the name looks like an extension, even if it isn't
- # supposed to, we have no choice but to return the original name.
- self._assert_windows_image_name("foo.baz", "foo.baz")
- self._assert_windows_image_name("foo.baz.exe", "foo.baz.exe")
-
- def test_kill_all(self):
- executive = Executive()
- # We use "yes" because it loops forever.
+ # Now test kill_all ; we do this in the same test as kill
+ # so that we don't collide when running tests in parallel.
process = subprocess.Popen(never_ending_command(), stdout=subprocess.PIPE)
self.assertEqual(process.poll(), None) # Process is running
executive.kill_all(never_ending_command()[0])
@@ -203,6 +188,20 @@ class ExecutiveTest(unittest.TestCase):
# Killing again should fail silently.
executive.kill_all(never_ending_command()[0])
+ def _assert_windows_image_name(self, name, expected_windows_name):
+ executive = Executive()
+ windows_name = executive._windows_image_name(name)
+ self.assertEqual(windows_name, expected_windows_name)
+
+ def test_windows_image_name(self):
+ self._assert_windows_image_name("foo", "foo.exe")
+ self._assert_windows_image_name("foo.exe", "foo.exe")
+ self._assert_windows_image_name("foo.com", "foo.com")
+ # If the name looks like an extension, even if it isn't
+ # supposed to, we have no choice but to return the original name.
+ self._assert_windows_image_name("foo.baz", "foo.baz")
+ self._assert_windows_image_name("foo.baz.exe", "foo.baz.exe")
+
def test_check_running_pid(self):
executive = Executive()
self.assertTrue(executive.check_running_pid(os.getpid()))
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/base.py b/Tools/Scripts/webkitpy/layout_tests/port/base.py
index dda129f2f..d79143189 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -36,6 +36,7 @@ import errno
import os
import optparse
import re
+import sys
try:
from collections import OrderedDict
@@ -184,12 +185,39 @@ class Port(object):
def baseline_search_path(self):
"""Return a list of absolute paths to directories to search under for
baselines. The directories are searched in order."""
- raise NotImplementedError('Port.baseline_search_path')
+ search_paths = []
+ if self.get_option('webkit_test_runner'):
+ search_paths.append(self._wk2_port_name())
+ search_paths.append(self.name())
+ if self.name() != self.port_name:
+ search_paths.append(self.port_name)
+ return map(self._webkit_baseline_path, search_paths)
def check_build(self, needs_http):
"""This routine is used to ensure that the build is up to date
and all the needed binaries are present."""
- raise NotImplementedError('Port.check_build')
+ # If we're using a pre-built copy of WebKit (--root), we assume it also includes a build of DRT.
+ if not self.get_option('root') and self.get_option('build') and not self._build_driver():
+ return False
+ if not self._check_driver():
+ return False
+ if self.get_option('pixel_tests'):
+ if not self.check_image_diff():
+ return False
+ if not self._check_port_build():
+ return False
+ return True
+
+ def _check_driver(self):
+ driver_path = self._path_to_driver()
+ if not self._filesystem.exists(driver_path):
+ _log.error("%s was not found at %s" % (self.driver_name(), driver_path))
+ return False
+ return True
+
+ def _check_port_build(self):
+ # Ports can override this method to do additional checks.
+ return True
def check_sys_deps(self, needs_http):
"""If the port needs to do some runtime checks to ensure that the
@@ -203,7 +231,11 @@ class Port(object):
def check_image_diff(self, override_step=None, logging=True):
"""This routine is used to check whether image_diff binary exists."""
- raise NotImplementedError('Port.check_image_diff')
+ image_diff_path = self._path_to_image_diff()
+ if not self._filesystem.exists(image_diff_path):
+ _log.error("ImageDiff was not found at %s" % image_diff_path)
+ return False
+ return True
def check_pretty_patch(self, logging=True):
"""Checks whether we can use the PrettyPatch ruby script."""
@@ -308,9 +340,10 @@ class Port(object):
pass
def driver_name(self):
- # FIXME: Seems we should get this from the Port's Driver class.
if self.get_option('driver_name'):
return self.get_option('driver_name')
+ if self.get_option('webkit_test_runner'):
+ return 'WebKitTestRunner'
return 'DumpRenderTree'
def expected_baselines_by_extension(self, test_name):
@@ -733,7 +766,9 @@ class Port(object):
def default_results_directory(self):
"""Absolute path to the default place to store the test results."""
- raise NotImplementedError()
+ # 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('layout-test-results')
def setup_test_run(self):
"""Perform port-specific work at the beginning of a test run."""
@@ -777,12 +812,20 @@ class Port(object):
# Windows:
'PATH',
+
+ # Most ports (?):
+ 'WEBKIT_TESTFONTS',
]
for variable in variables_to_copy:
self._copy_value_from_environ_if_set(clean_env, variable)
# For Linux:
clean_env['DISPLAY'] = self._value_or_default_from_environ('DISPLAY', ':1')
+
+ for string_variable in self.get_option('additional_env_var', []):
+ [name, value] = string_variable.split('=', 1)
+ clean_env[name] = value
+
return clean_env
def show_results_html_file(self, results_filename):
@@ -1038,25 +1081,63 @@ class Port(object):
def _uses_apache(self):
return True
+ # FIXME: This does not belong on the port object.
+ @memoized
def _path_to_apache(self):
"""Returns the full path to the apache binary.
This is needed only by ports that use the apache_http_server module."""
- raise NotImplementedError('Port.path_to_apache')
+ # The Apache binary path can vary depending on OS and distribution
+ # See http://wiki.apache.org/httpd/DistrosDefaultLayout
+ for path in ["/usr/sbin/httpd", "/usr/sbin/apache2"]:
+ if self._filesystem.exists(path):
+ return path
+ _log.error("Could not find apache. Not installed or unknown path.")
+ return None
+
+ # FIXME: This belongs on some platform abstraction instead of Port.
+ def _is_redhat_based(self):
+ return self._filesystem.exists('/etc/redhat-release')
+
+ def _is_debian_based(self):
+ return self._filesystem.exists('/etc/debian_version')
+
+ # We pass sys_platform into this method to make it easy to unit test.
+ def _apache_config_file_name_for_platform(self, sys_platform):
+ if sys_platform == 'cygwin':
+ return 'cygwin-httpd.conf' # CYGWIN is the only platform to still use Apache 1.3.
+ if sys_platform.startswith('linux'):
+ if self._is_redhat_based():
+ return 'fedora-httpd.conf' # This is an Apache 2.x config file despite the naming.
+ if self._is_debian_based():
+ return 'apache2-debian-httpd.conf'
+ # All platforms use apache2 except for CYGWIN (and Mac OS X Tiger and prior, which we no longer support).
+ return "apache2-httpd.conf"
def _path_to_apache_config_file(self):
"""Returns the full path to the apache binary.
This is needed only by ports that use the apache_http_server module."""
- raise NotImplementedError('Port.path_to_apache_config_file')
+ config_file_name = self._apache_config_file_name_for_platform(sys.platform)
+ return self._filesystem.join(self.layout_tests_dir(), 'http', 'conf', config_file_name)
+
+ def _build_path(self, *comps):
+ # --root is used for running with a pre-built root (like from a nightly zip).
+ build_directory = self.get_option('root') or self.get_option('build_directory')
+ if not build_directory:
+ build_directory = self._config.build_directory(self.get_option('configuration'))
+ # Set --build-directory here Since this modifies the options object used by the worker subprocesses,
+ # it avoids the slow call out to build_directory in each subprocess.
+ self.set_option_default('build_directory', build_directory)
+ return self._filesystem.join(self._filesystem.abspath(build_directory), *comps)
def _path_to_driver(self, configuration=None):
"""Returns the full path to the test driver (DumpRenderTree)."""
- raise NotImplementedError('Port._path_to_driver')
+ return self._build_path(self.driver_name())
def _path_to_webcore_library(self):
"""Returns the full path to a built copy of WebCore."""
- raise NotImplementedError('Port.path_to_webcore_library')
+ return None
def _path_to_helper(self):
"""Returns the full path to the layout_test_helper binary, which
@@ -1064,13 +1145,13 @@ class Port(object):
if no helper is needed.
This is likely only used by start/stop_helper()."""
- raise NotImplementedError('Port._path_to_helper')
+ return None
def _path_to_image_diff(self):
"""Returns the full path to the image_diff binary, or None if it is not available.
This is likely used only by diff_image()"""
- raise NotImplementedError('Port.path_to_image_diff')
+ return self._build_path('ImageDiff')
def _path_to_lighttpd(self):
"""Returns the path to the LigHTTPd binary.
@@ -1094,7 +1175,7 @@ class Port(object):
"""Returns the full path to the wdiff binary, or None if it is not available.
This is likely used only by wdiff_text()"""
- raise NotImplementedError('Port._path_to_wdiff')
+ return 'wdiff'
def _webkit_baseline_path(self, platform):
"""Return the full path to the top of the baseline tree for a
@@ -1109,7 +1190,7 @@ class Port(object):
def _driver_class(self):
"""Returns the port's driver implementation."""
- raise NotImplementedError('Port._driver_class')
+ return driver.Driver
def _get_crash_log(self, name, pid, stdout, stderr, newer_than):
name_str = name or '<unknown process name>'
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
index f7afb7b22..7e9259bd3 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
@@ -287,6 +287,14 @@ class PortTest(unittest.TestCase):
'/tmp/additional-expectations-1.txt', '/tmp/additional-expectations-2.txt']
self.assertEquals('\n'.join(port.expectations_dict().values()), '\ncontent1\n\ncontent2\n')
+ def test_additional_env_var(self):
+ port = self.make_port(options=optparse.Values({'additional_env_var': ['FOO=BAR', 'BAR=FOO']}))
+ self.assertEqual(port.get_option('additional_env_var'), ['FOO=BAR', 'BAR=FOO'])
+ environment = port.setup_environ_for_server()
+ self.assertTrue(('FOO' in environment) & ('BAR' in environment))
+ self.assertEqual(environment['FOO'], 'BAR')
+ self.assertEqual(environment['BAR'], 'FOO')
+
def test_uses_test_expectations_file(self):
port = self.make_port(port_name='foo')
port.port_name = 'foo'
@@ -383,28 +391,6 @@ class PortTest(unittest.TestCase):
_, _, logs = capture.restore_output()
self.assertEqual('httpd seems broken. Cannot run http tests.\n', logs)
- def assertVirtual(self, method, *args, **kwargs):
- self.assertRaises(NotImplementedError, method, *args, **kwargs)
-
- def test_virtual_methods(self):
- port = Port(MockSystemHost())
- self.assertVirtual(port.baseline_path)
- self.assertVirtual(port.baseline_search_path)
- self.assertVirtual(port.check_build, None)
- self.assertVirtual(port.check_image_diff)
- self.assertVirtual(port.create_driver, 0)
- self.assertVirtual(port.diff_image, None, None)
- self.assertVirtual(port.default_results_directory)
- self.assertVirtual(port._path_to_apache)
- self.assertVirtual(port._path_to_apache_config_file)
- self.assertVirtual(port._path_to_driver)
- self.assertVirtual(port._path_to_helper)
- self.assertVirtual(port._path_to_image_diff)
- self.assertVirtual(port._path_to_lighttpd)
- self.assertVirtual(port._path_to_lighttpd_modules)
- self.assertVirtual(port._path_to_lighttpd_php)
- self.assertVirtual(port._path_to_wdiff)
-
def test_test_exists(self):
port = self.make_port(with_tests=True)
self.assertTrue(port.test_exists('passes'))
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
index 45298c634..9729f94c0 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
@@ -42,8 +42,7 @@ from webkitpy.common.system import executive
from webkitpy.common.system.path import cygpath
from webkitpy.layout_tests.models.test_configuration import TestConfiguration
from webkitpy.layout_tests.port.base import Port, VirtualTestSuite
-from webkitpy.layout_tests.port.driver import DriverOutput
-from webkitpy.layout_tests.port.webkit import WebKitPort, WebKitDriver
+from webkitpy.layout_tests.port.webkit import WebKitPort
_log = logging.getLogger(__name__)
@@ -140,12 +139,6 @@ class ChromiumPort(WebKitPort):
return False
return True
- def driver_name(self):
- # FIXME: merge this with Port.driver_name, WebKitPort.driver_name
- if self.get_option('driver_name'):
- return self.get_option('driver_name')
- return 'DumpRenderTree'
-
def check_build(self, needs_http):
result = True
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py
index 126b31868..eb4dcec95 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py
@@ -34,6 +34,7 @@ import threading
import time
from webkitpy.layout_tests.port import chromium
+from webkitpy.layout_tests.port import driver
from webkitpy.layout_tests.port import factory
from webkitpy.layout_tests.port import server_process
from webkitpy.layout_tests.port import webkit
@@ -57,7 +58,7 @@ DEVICE_DRT_STAMP_PATH = DEVICE_DRT_DIR + 'DumpRenderTree.stamp'
DRT_APP_PACKAGE = 'org.chromium.native_test'
DRT_ACTIVITY_FULL_NAME = DRT_APP_PACKAGE + '/.ChromeNativeTestActivity'
DRT_APP_DIR = '/data/user/0/' + DRT_APP_PACKAGE + '/'
-DRT_APP_FILES_DIR = DRT_APP_DIR + 'files/'
+DRT_APP_FILES_DIR = DEVICE_SOURCE_ROOT_DIR
DRT_APP_CACHE_DIR = DRT_APP_DIR + 'cache/'
# This only works for single core devices so far.
@@ -456,9 +457,9 @@ class ChromiumAndroidPort(chromium.ChromiumPort):
self._original_governor = None
-class ChromiumAndroidDriver(webkit.WebKitDriver):
+class ChromiumAndroidDriver(driver.Driver):
def __init__(self, port, worker_number, pixel_tests, no_timeout=False):
- webkit.WebKitDriver.__init__(self, port, worker_number, pixel_tests, no_timeout)
+ super(ChromiumAndroidDriver, self).__init__(port, worker_number, pixel_tests, no_timeout)
self._pixel_tests = pixel_tests
self._in_fifo_path = DRT_APP_FILES_DIR + 'DumpRenderTree.in'
self._out_fifo_path = DRT_APP_FILES_DIR + 'DumpRenderTree.out'
@@ -490,7 +491,7 @@ class ChromiumAndroidDriver(webkit.WebKitDriver):
# Otherwise the main thread has been proceeded normally. This thread just exits silently.
def _drt_cmd_line(self, pixel_tests, per_test_args):
- return webkit.WebKitDriver.cmd_line(self, pixel_tests, per_test_args) + [
+ return driver.Driver.cmd_line(self, pixel_tests, per_test_args) + [
'--in-fifo=' + self._in_fifo_path,
'--out-fifo=' + self._out_fifo_path,
'--err-fifo=' + self._err_fifo_path,
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py
index a3a3aaeb4..0e2801a57 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py
@@ -38,7 +38,7 @@ from webkitpy.common.system.systemhost_mock import MockSystemHost
from webkitpy.layout_tests.port import chromium_android
from webkitpy.layout_tests.port import chromium_port_testcase
from webkitpy.layout_tests.port import driver
-from webkitpy.layout_tests.port import webkit_unittest
+from webkitpy.layout_tests.port import driver_unittest
class ChromiumAndroidPortTest(chromium_port_testcase.ChromiumPortTestCase):
@@ -147,9 +147,9 @@ class ChromiumAndroidDriverTest(unittest.TestCase):
self.assertTrue('--err-fifo=' + chromium_android.DRT_APP_FILES_DIR + 'DumpRenderTree.err' in cmd_line)
def test_read_prompt(self):
- self.driver._server_process = webkit_unittest.MockServerProcess(['root@android:/ # '])
+ self.driver._server_process = driver_unittest.MockServerProcess(lines=['root@android:/ # '])
self.assertEquals(self.driver._read_prompt(time.time() + 1), None)
- self.driver._server_process = webkit_unittest.MockServerProcess(['$ '])
+ self.driver._server_process = driver_unittest.MockServerProcess(lines=['$ '])
self.assertRaises(AssertionError, self.driver._read_prompt, time.time() + 1)
def test_command_from_driver_input(self):
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/driver.py b/Tools/Scripts/webkitpy/layout_tests/port/driver.py
index f65db2f7b..5e7061bab 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/driver.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/driver.py
@@ -26,12 +26,21 @@
# (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 base64
import copy
+import logging
import re
import shlex
+import sys
+import time
from webkitpy.common.system import path
+from webkitpy.layout_tests.port import server_process
+
+
+_log = logging.getLogger(__name__)
+
class DriverInput(object):
def __init__(self, test_name, timeout, image_hash, should_run_pixel_test, args=None):
@@ -91,7 +100,7 @@ class DriverOutput(object):
class Driver(object):
- """Abstract interface for the DumpRenderTree interface."""
+ """object for running test(s) using DumpRenderTree/WebKitTestRunner."""
def __init__(self, port, worker_number, pixel_tests, no_timeout=False):
"""Initialize a Driver to subsequently run tests.
@@ -106,6 +115,32 @@ class Driver(object):
self._worker_number = worker_number
self._no_timeout = no_timeout
+ # overridable for testing.
+ self._server_process_constructor = server_process.ServerProcess
+
+ self._driver_tempdir = None
+ # WebKitTestRunner can report back subprocess crashes by printing
+ # "#CRASHED - PROCESSNAME". Since those can happen at any time
+ # and ServerProcess won't be aware of them (since the actual tool
+ # didn't crash, just a subprocess) we record the crashed subprocess name here.
+ self._crashed_process_name = None
+ self._crashed_pid = None
+
+ # WebKitTestRunner can report back subprocesses that became unresponsive
+ # This could mean they crashed.
+ self._subprocess_was_unresponsive = False
+
+ # stderr reading is scoped on a per-test (not per-block) basis, so we store the accumulated
+ # stderr output, as well as if we've seen #EOF on this driver instance.
+ # FIXME: We should probably remove _read_first_block and _read_optional_image_block and
+ # instead scope these locally in run_test.
+ self.error_from_test = str()
+ self.err_seen_eof = False
+ self._server_process = None
+
+ def __del__(self):
+ self.stop()
+
def run_test(self, driver_input):
"""Run a single test and return the results.
@@ -115,9 +150,51 @@ class Driver(object):
Returns a DriverOuput object.
"""
- raise NotImplementedError('Driver.run_test')
+ start_time = time.time()
+ self.start(driver_input.should_run_pixel_test, driver_input.args)
+ test_begin_time = time.time()
+ self.error_from_test = str()
+ self.err_seen_eof = False
+
+ command = self._command_from_driver_input(driver_input)
+ deadline = test_begin_time + int(driver_input.timeout) / 1000.0
+
+ self._server_process.write(command)
+ text, audio = self._read_first_block(deadline) # First block is either text or audio
+ image, actual_image_hash = self._read_optional_image_block(deadline) # The second (optional) block is image data.
+
+ # We may not have read all of the output if an error (crash) occured.
+ # Since some platforms output the stacktrace over error, we should
+ # dump any buffered error into self.error_from_test.
+ # FIXME: We may need to also read stderr until the process dies?
+ self.error_from_test += self._server_process.pop_all_buffered_stderr()
+
+ crash_log = None
+ if self.has_crashed():
+ crash_log = self._port._get_crash_log(self._crashed_process_name, self._crashed_pid, text, self.error_from_test,
+ newer_than=start_time)
+
+ # If we don't find a crash log use a placeholder error message instead.
+ if not crash_log:
+ crash_log = 'no crash log found for %s:%d.' % (self._crashed_process_name, self._crashed_pid)
+ # If we were unresponsive append a message informing there may not have been a crash.
+ if self._subprocess_was_unresponsive:
+ crash_log += ' Process failed to become responsive before timing out.'
+
+ timeout = self._server_process.timed_out
+ if timeout:
+ # DRT doesn't have a built in timer to abort the test, so we might as well
+ # kill the process directly and not wait for it to shut down cleanly (since it may not).
+ self._server_process.kill()
+
+ return DriverOutput(text, image, actual_image_hash, audio,
+ crash=self.has_crashed(), test_time=time.time() - test_begin_time,
+ timeout=timeout, error=self.error_from_test,
+ crashed_process_name=self._crashed_process_name,
+ crashed_pid=self._crashed_pid, crash_log=crash_log)
# FIXME: Seems this could just be inlined into callers.
+ @classmethod
def _command_wrapper(cls, wrapper_option):
# Hook for injecting valgrind or other runtime instrumentation,
# used by e.g. tools/valgrind/valgrind_tests.py.
@@ -161,17 +238,210 @@ class Driver(object):
raise NotImplementedError('unknown url type: %s' % uri)
def has_crashed(self):
+ if self._server_process is None:
+ return False
+ if self._crashed_process_name:
+ return True
+ if self._server_process.has_crashed():
+ self._crashed_process_name = self._server_process.name()
+ self._crashed_pid = self._server_process.pid()
+ return True
return False
- def start(self):
- raise NotImplementedError('Driver.start')
+ def start(self, pixel_tests, per_test_args):
+ # FIXME: Callers shouldn't normally call this, since this routine
+ # may not be specifying the correct combination of pixel test and
+ # per_test args.
+ #
+ # The only reason we have this routine at all is so the perftestrunner
+ # can pause before running a test; it might be better to push that
+ # into run_test() directly.
+ if not self._server_process:
+ self._start(pixel_tests, per_test_args)
+
+ def _start(self, pixel_tests, per_test_args):
+ self.stop()
+ self._driver_tempdir = self._port._filesystem.mkdtemp(prefix='%s-' % self._port.driver_name())
+ server_name = self._port.driver_name()
+ environment = self._port.setup_environ_for_server(server_name)
+ environment['DYLD_LIBRARY_PATH'] = self._port._build_path()
+ environment['DYLD_FRAMEWORK_PATH'] = self._port._build_path()
+ # FIXME: We're assuming that WebKitTestRunner checks this DumpRenderTree-named environment variable.
+ environment['DUMPRENDERTREE_TEMP'] = str(self._driver_tempdir)
+ environment['LOCAL_RESOURCE_ROOT'] = self._port.layout_tests_dir()
+ self._crashed_process_name = None
+ self._crashed_pid = None
+ self._server_process = self._server_process_constructor(self._port, server_name, self.cmd_line(pixel_tests, per_test_args), environment)
+ self._server_process.start()
def stop(self):
- raise NotImplementedError('Driver.stop')
+ if self._server_process:
+ self._server_process.stop()
+ self._server_process = None
+
+ if self._driver_tempdir:
+ self._port._filesystem.rmtree(str(self._driver_tempdir))
+ self._driver_tempdir = None
def cmd_line(self, pixel_tests, per_test_args):
- raise NotImplementedError('Driver.cmd_line')
+ cmd = self._command_wrapper(self._port.get_option('wrapper'))
+ cmd.append(self._port._path_to_driver())
+ if self._port.get_option('gc_between_tests'):
+ cmd.append('--gc-between-tests')
+ if self._port.get_option('complex_text'):
+ cmd.append('--complex-text')
+ if self._port.get_option('threaded'):
+ cmd.append('--threaded')
+ if self._no_timeout:
+ cmd.append('--no-timeout')
+ # FIXME: We need to pass --timeout=SECONDS to WebKitTestRunner for WebKit2.
+
+ cmd.extend(self._port.get_option('additional_drt_flag', []))
+
+ if pixel_tests:
+ cmd.append('--pixel-tests')
+ cmd.extend(per_test_args)
+
+ cmd.append('-')
+ return cmd
+
+ def _check_for_driver_crash(self, error_line):
+ if error_line == "#CRASHED\n":
+ # This is used on Windows to report that the process has crashed
+ # See http://trac.webkit.org/changeset/65537.
+ self._crashed_process_name = self._server_process.name()
+ self._crashed_pid = self._server_process.pid()
+ elif (error_line.startswith("#CRASHED - WebProcess")
+ or error_line.startswith("#PROCESS UNRESPONSIVE - WebProcess")):
+ # WebKitTestRunner uses this to report that the WebProcess subprocess crashed.
+ pid = None
+ m = re.search('pid (\d+)', error_line)
+ if m:
+ pid = int(m.group(1))
+ self._crashed_process_name = 'WebProcess'
+ self._crashed_pid = pid
+ # FIXME: delete this after we're sure this code is working :)
+ _log.debug('WebProcess crash, pid = %s, error_line = %s' % (str(pid), error_line))
+ if error_line.startswith("#PROCESS UNRESPONSIVE - WebProcess"):
+ self._subprocess_was_unresponsive = True
+ return True
+ return self.has_crashed()
+
+ def _command_from_driver_input(self, driver_input):
+ # FIXME: performance tests pass in full URLs instead of test names.
+ if driver_input.test_name.startswith('http://') or driver_input.test_name.startswith('https://') or driver_input.test_name == ('about:blank'):
+ command = driver_input.test_name
+ elif self.is_http_test(driver_input.test_name):
+ command = self.test_to_uri(driver_input.test_name)
+ else:
+ command = self._port.abspath_for_test(driver_input.test_name)
+ if sys.platform == 'cygwin':
+ command = path.cygpath(command)
+
+ if driver_input.image_hash:
+ # "'" is the separator of command fields.
+ command += "'" + driver_input.image_hash
+ return command + "\n"
+
+ def _read_first_block(self, deadline):
+ # returns (text_content, audio_content)
+ block = self._read_block(deadline)
+ if block.content_type == 'audio/wav':
+ return (None, block.decoded_content)
+ return (block.decoded_content, None)
+
+ def _read_optional_image_block(self, deadline):
+ # returns (image, actual_image_hash)
+ block = self._read_block(deadline, wait_for_stderr_eof=True)
+ if block.content and block.content_type == 'image/png':
+ return (block.decoded_content, block.content_hash)
+ return (None, block.content_hash)
+
+ def _read_header(self, block, line, header_text, header_attr, header_filter=None):
+ if line.startswith(header_text) and getattr(block, header_attr) is None:
+ value = line.split()[1]
+ if header_filter:
+ value = header_filter(value)
+ setattr(block, header_attr, value)
+ return True
+ return False
+ def _process_stdout_line(self, block, line):
+ if (self._read_header(block, line, 'Content-Type: ', 'content_type')
+ or self._read_header(block, line, 'Content-Transfer-Encoding: ', 'encoding')
+ or self._read_header(block, line, 'Content-Length: ', '_content_length', int)
+ or self._read_header(block, line, 'ActualHash: ', 'content_hash')):
+ return
+ # Note, we're not reading ExpectedHash: here, but we could.
+ # If the line wasn't a header, we just append it to the content.
+ block.content += line
+
+ def _strip_eof(self, line):
+ if line and line.endswith("#EOF\n"):
+ return line[:-5], True
+ return line, False
+
+ def _read_block(self, deadline, wait_for_stderr_eof=False):
+ block = ContentBlock()
+ out_seen_eof = False
+
+ while not self.has_crashed():
+ if out_seen_eof and (self.err_seen_eof or not wait_for_stderr_eof):
+ break
+
+ if self.err_seen_eof:
+ out_line = self._server_process.read_stdout_line(deadline)
+ err_line = None
+ elif out_seen_eof:
+ out_line = None
+ err_line = self._server_process.read_stderr_line(deadline)
+ else:
+ out_line, err_line = self._server_process.read_either_stdout_or_stderr_line(deadline)
+
+ if self._server_process.timed_out or self.has_crashed():
+ break
+
+ if out_line:
+ assert not out_seen_eof
+ out_line, out_seen_eof = self._strip_eof(out_line)
+ if err_line:
+ assert not self.err_seen_eof
+ err_line, self.err_seen_eof = self._strip_eof(err_line)
+
+ if out_line:
+ if out_line[-1] != "\n":
+ _log.error("Last character read from DRT stdout line was not a newline! This indicates either a NRWT or DRT bug.")
+ content_length_before_header_check = block._content_length
+ self._process_stdout_line(block, out_line)
+ # FIXME: Unlike HTTP, DRT dumps the content right after printing a Content-Length header.
+ # Don't wait until we're done with headers, just read the binary blob right now.
+ if content_length_before_header_check != block._content_length:
+ block.content = self._server_process.read_stdout(deadline, block._content_length)
+
+ if err_line:
+ if self._check_for_driver_crash(err_line):
+ break
+ self.error_from_test += err_line
+
+ block.decode_content()
+ return block
+
+
+class ContentBlock(object):
+ def __init__(self):
+ self.content_type = None
+ self.encoding = None
+ self.content_hash = None
+ self._content_length = None
+ # Content is treated as binary data even though the text output is usually UTF-8.
+ self.content = str() # FIXME: Should be bytearray() once we require Python 2.6.
+ self.decoded_content = None
+
+ def decode_content(self):
+ if self.encoding == 'base64':
+ self.decoded_content = base64.b64decode(self.content)
+ else:
+ self.decoded_content = self.content
class DriverProxy(object):
"""A wrapper for managing two Driver instances, one with pixel tests and
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
index 00a42f42f..d712023e3 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
@@ -26,13 +26,15 @@
# (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 sys
import unittest
from webkitpy.common.system.systemhost_mock import MockSystemHost
from webkitpy.layout_tests.port import Port, Driver, DriverOutput
+# FIXME: remove the dependency on TestWebKitPort
+from webkitpy.layout_tests.port.webkit_unittest import TestWebKitPort
+
class DriverOutputTest(unittest.TestCase):
def test_strip_metrics(self):
@@ -79,19 +81,10 @@ class DriverTest(unittest.TestCase):
def make_port(self):
return Port(MockSystemHost())
- def assertVirtual(self, method, *args, **kwargs):
- self.assertRaises(NotImplementedError, method, *args, **kwargs)
-
def _assert_wrapper(self, wrapper_string, expected_wrapper):
wrapper = Driver(self.make_port(), None, pixel_tests=False)._command_wrapper(wrapper_string)
self.assertEqual(wrapper, expected_wrapper)
- def test_virtual_driver_methods(self):
- driver = Driver(self.make_port(), None, pixel_tests=False)
- self.assertVirtual(driver.run_test, None)
- self.assertVirtual(driver.stop)
- self.assertVirtual(driver.cmd_line, False, [])
-
def test_command_wrapper(self):
self._assert_wrapper(None, [])
self._assert_wrapper("valgrind", ["valgrind"])
@@ -115,6 +108,193 @@ class DriverTest(unittest.TestCase):
self.assertEqual(driver.uri_to_test('http://127.0.0.1:8000/foo.html'), 'http/tests/foo.html')
self.assertEqual(driver.uri_to_test('https://127.0.0.1:8443/ssl/bar.html'), 'http/tests/ssl/bar.html')
+ def test_read_block(self):
+ port = TestWebKitPort()
+ driver = Driver(port, 0, pixel_tests=False)
+ driver._server_process = MockServerProcess(lines=[
+ 'ActualHash: foobar',
+ 'Content-Type: my_type',
+ 'Content-Transfer-Encoding: none',
+ "#EOF",
+ ])
+ content_block = driver._read_block(0)
+ self.assertEquals(content_block.content_type, 'my_type')
+ self.assertEquals(content_block.encoding, 'none')
+ self.assertEquals(content_block.content_hash, 'foobar')
+ driver._server_process = None
+
+ def test_read_binary_block(self):
+ port = TestWebKitPort()
+ driver = Driver(port, 0, pixel_tests=True)
+ driver._server_process = MockServerProcess(lines=[
+ 'ActualHash: actual',
+ 'ExpectedHash: expected',
+ 'Content-Type: image/png',
+ 'Content-Length: 9',
+ "12345678",
+ "#EOF",
+ ])
+ content_block = driver._read_block(0)
+ self.assertEquals(content_block.content_type, 'image/png')
+ self.assertEquals(content_block.content_hash, 'actual')
+ self.assertEquals(content_block.content, '12345678\n')
+ self.assertEquals(content_block.decoded_content, '12345678\n')
+ driver._server_process = None
+
+ def test_read_base64_block(self):
+ port = TestWebKitPort()
+ driver = Driver(port, 0, pixel_tests=True)
+ driver._server_process = MockServerProcess(lines=[
+ 'ActualHash: actual',
+ 'ExpectedHash: expected',
+ 'Content-Type: image/png',
+ 'Content-Transfer-Encoding: base64',
+ 'Content-Length: 12',
+ 'MTIzNDU2NzgK#EOF',
+ ])
+ content_block = driver._read_block(0)
+ self.assertEquals(content_block.content_type, 'image/png')
+ self.assertEquals(content_block.content_hash, 'actual')
+ self.assertEquals(content_block.encoding, 'base64')
+ self.assertEquals(content_block.content, 'MTIzNDU2NzgK')
+ self.assertEquals(content_block.decoded_content, '12345678\n')
+
+ def test_no_timeout(self):
+ port = TestWebKitPort()
+ driver = Driver(port, 0, pixel_tests=True, no_timeout=True)
+ self.assertEquals(driver.cmd_line(True, []), ['/mock-build/DumpRenderTree', '--no-timeout', '--pixel-tests', '-'])
+
+ def test_check_for_driver_crash(self):
+ port = TestWebKitPort()
+ driver = Driver(port, 0, pixel_tests=True)
+
+ class FakeServerProcess(object):
+ def __init__(self, crashed):
+ self.crashed = crashed
+
+ def pid(self):
+ return 1234
+
+ def name(self):
+ return 'FakeServerProcess'
+
+ def has_crashed(self):
+ return self.crashed
+
+ def stop(self):
+ pass
+
+ def assert_crash(driver, error_line, crashed, name, pid, unresponsive=False):
+ self.assertEquals(driver._check_for_driver_crash(error_line), crashed)
+ self.assertEquals(driver._crashed_process_name, name)
+ self.assertEquals(driver._crashed_pid, pid)
+ self.assertEquals(driver._subprocess_was_unresponsive, unresponsive)
+ driver.stop()
+
+ driver._server_process = FakeServerProcess(False)
+ assert_crash(driver, '', False, None, None)
+
+ driver._crashed_process_name = None
+ driver._crashed_pid = None
+ driver._server_process = FakeServerProcess(False)
+ driver._subprocess_was_unresponsive = False
+ assert_crash(driver, '#CRASHED\n', True, 'FakeServerProcess', 1234)
+
+ driver._crashed_process_name = None
+ driver._crashed_pid = None
+ driver._server_process = FakeServerProcess(False)
+ driver._subprocess_was_unresponsive = False
+ assert_crash(driver, '#CRASHED - WebProcess\n', True, 'WebProcess', None)
+
+ driver._crashed_process_name = None
+ driver._crashed_pid = None
+ driver._server_process = FakeServerProcess(False)
+ driver._subprocess_was_unresponsive = False
+ assert_crash(driver, '#CRASHED - WebProcess (pid 8675)\n', True, 'WebProcess', 8675)
+
+ driver._crashed_process_name = None
+ driver._crashed_pid = None
+ driver._server_process = FakeServerProcess(False)
+ driver._subprocess_was_unresponsive = False
+ assert_crash(driver, '#PROCESS UNRESPONSIVE - WebProcess (pid 8675)\n', True, 'WebProcess', 8675, True)
+
+ driver._crashed_process_name = None
+ driver._crashed_pid = None
+ driver._server_process = FakeServerProcess(True)
+ driver._subprocess_was_unresponsive = False
+ assert_crash(driver, '', True, 'FakeServerProcess', 1234)
+
+ def test_creating_a_port_does_not_write_to_the_filesystem(self):
+ port = TestWebKitPort()
+ driver = Driver(port, 0, pixel_tests=True)
+ self.assertEquals(port._filesystem.written_files, {})
+ self.assertEquals(port._filesystem.last_tmpdir, None)
+
+ def test_stop_cleans_up_properly(self):
+ port = TestWebKitPort()
+ driver = Driver(port, 0, pixel_tests=True)
+ driver._server_process_constructor = MockServerProcess
+ driver.start(True, [])
+ last_tmpdir = port._filesystem.last_tmpdir
+ self.assertNotEquals(last_tmpdir, None)
+ driver.stop()
+ self.assertFalse(port._filesystem.isdir(last_tmpdir))
+
+ def test_two_starts_cleans_up_properly(self):
+ port = TestWebKitPort()
+ driver = Driver(port, 0, pixel_tests=True)
+ driver._server_process_constructor = MockServerProcess
+ driver.start(True, [])
+ last_tmpdir = port._filesystem.last_tmpdir
+ driver._start(True, [])
+ self.assertFalse(port._filesystem.isdir(last_tmpdir))
+
+ def test_start_actually_starts(self):
+ port = TestWebKitPort()
+ driver = Driver(port, 0, pixel_tests=True)
+ driver._server_process_constructor = MockServerProcess
+ driver.start(True, [])
+ self.assertTrue(driver._server_process.started)
+
+
+class MockServerProcess(object):
+ def __init__(self, port_obj=None, name=None, cmd=None, env=None, universal_newlines=False, lines=None):
+ self.timed_out = False
+ self.lines = lines or []
+ self.crashed = False
+ self.started = False
+
+ def has_crashed(self):
+ return self.crashed
+
+ def read_stdout_line(self, deadline):
+ return self.lines.pop(0) + "\n"
+
+ def read_stdout(self, deadline, size):
+ first_line = self.lines[0]
+ if size > len(first_line):
+ self.lines.pop(0)
+ remaining_size = size - len(first_line) - 1
+ if not remaining_size:
+ return first_line + "\n"
+ return first_line + "\n" + self.read_stdout(deadline, remaining_size)
+ result = self.lines[0][:size]
+ self.lines[0] = self.lines[0][size:]
+ return result
+
+ def read_either_stdout_or_stderr_line(self, deadline):
+ # FIXME: We should have tests which intermix stderr and stdout lines.
+ return self.read_stdout_line(deadline), None
+
+ def start(self):
+ self.started = True
+
+ def stop(self, kill_directly=False):
+ return
+
+ def kill(self):
+ return
+
if __name__ == '__main__':
unittest.main()
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/gtk.py b/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
index 6c59427f3..ebb761bbd 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
@@ -33,7 +33,7 @@ import subprocess
from webkitpy.layout_tests.models.test_configuration import TestConfiguration
from webkitpy.layout_tests.port.server_process import ServerProcess
-from webkitpy.layout_tests.port.webkit import WebKitDriver, WebKitPort
+from webkitpy.layout_tests.port.webkit import WebKitPort
from webkitpy.layout_tests.port.pulseaudio_sanitizer import PulseAudioSanitizer
from webkitpy.layout_tests.port.xvfbdriver import XvfbDriver
from webkitpy.common.system.executive import Executive
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/qt.py b/Tools/Scripts/webkitpy/layout_tests/port/qt.py
index 154cfdab8..aaaafac5d 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/qt.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/qt.py
@@ -28,6 +28,7 @@
"""QtWebKit implementation of the Port interface."""
+import glob
import logging
import re
import sys
@@ -93,6 +94,15 @@ class QtPort(WebKitPort):
else:
return self._build_path('lib/libQtWebKit.so')
+ def _modules_to_search_for_symbols(self):
+ # We search in every library to be reliable in the case of building with CONFIG+=force_static_libs_as_shared.
+ if self.operating_system() == 'mac':
+ frameworks = glob.glob(os.path.join(self._build_path('lib'), '*.framework'))
+ return [os.path.join(framework, os.path.splitext(os.path.basename(framework))[0]) for framework in frameworks]
+ else:
+ suffix = 'dll' if self.operating_system() == 'win' else 'so'
+ return glob.glob(os.path.join(self._build_path('lib'), 'lib*.' + suffix))
+
@memoized
def qt_version(self):
version = ''
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/webkit.py b/Tools/Scripts/webkitpy/layout_tests/port/webkit.py
index d376e774a..d5b7c0d7f 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/webkit.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/webkit.py
@@ -31,20 +31,14 @@
"""WebKit implementations of the Port interface."""
-import base64
import itertools
import logging
import operator
import re
-import sys
import time
-from webkitpy.common.memoized import memoized
-from webkitpy.common.net.buildbot import BuildBot
-from webkitpy.common.system.environment import Environment
from webkitpy.common.system.executive import Executive, ScriptError
-from webkitpy.common.system.path import cygpath
-from webkitpy.layout_tests.port import builders, server_process, Port, Driver, DriverOutput
+from webkitpy.layout_tests.port import server_process, Port
_log = logging.getLogger(__name__)
@@ -52,22 +46,8 @@ _log = logging.getLogger(__name__)
class WebKitPort(Port):
- def driver_name(self):
- if self.get_option('webkit_test_runner'):
- return "WebKitTestRunner"
- return "DumpRenderTree"
-
# FIXME: Eventually we should standarize port naming, and make this method smart enough
# to use for all port configurations (including architectures, graphics types, etc).
- def baseline_search_path(self):
- search_paths = []
- if self.get_option('webkit_test_runner'):
- search_paths.append(self._wk2_port_name())
- search_paths.append(self.name())
- if self.name() != self.port_name:
- search_paths.append(self.port_name)
- return map(self._webkit_baseline_path, search_paths)
-
def _port_flag_for_scripts(self):
# This is overrriden by ports which need a flag passed to scripts to distinguish the use of that port.
# For example --qt on linux, since a user might have both Gtk and Qt libraries installed.
@@ -116,37 +96,6 @@ class WebKitPort(Port):
def _build_driver_flags(self):
return []
- def _check_driver(self):
- driver_path = self._path_to_driver()
- if not self._filesystem.exists(driver_path):
- _log.error("%s was not found at %s" % (self.driver_name(), driver_path))
- return False
- return True
-
- def check_build(self, needs_http):
- # If we're using a pre-built copy of WebKit (--root), we assume it also includes a build of DRT.
- if not self.get_option('root') and self.get_option('build') and not self._build_driver():
- return False
- if not self._check_driver():
- return False
- if self.get_option('pixel_tests'):
- if not self.check_image_diff():
- return False
- if not self._check_port_build():
- return False
- return True
-
- def _check_port_build(self):
- # Ports can override this method to do additional checks.
- return True
-
- def check_image_diff(self, override_step=None, logging=True):
- image_diff_path = self._path_to_image_diff()
- if not self._filesystem.exists(image_diff_path):
- _log.error("ImageDiff was not found at %s" % image_diff_path)
- return False
- return True
-
def diff_image(self, expected_contents, actual_contents, tolerance=None):
# Handle the case where the test didn't actually generate an image.
# FIXME: need unit tests for this.
@@ -222,19 +171,6 @@ class WebKitPort(Port):
return (output_image, diff_percent)
- def setup_environ_for_server(self, server_name=None):
- clean_env = super(WebKitPort, self).setup_environ_for_server(server_name)
- self._copy_value_from_environ_if_set(clean_env, 'WEBKIT_TESTFONTS')
- return clean_env
-
- def default_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('layout-test-results')
-
- def _driver_class(self):
- return WebKitDriver
-
def _tests_for_other_platforms(self):
# By default we will skip any directory under LayoutTests/platform
# that isn't in our baseline search path (this mirrors what
@@ -360,334 +296,3 @@ class WebKitPort(Port):
tests_to_skip.update(self._tests_for_other_platforms())
tests_to_skip.update(self._skipped_tests_for_unsupported_features(test_list))
return tests_to_skip
-
- def _build_path(self, *comps):
- # --root is used for running with a pre-built root (like from a nightly zip).
- build_directory = self.get_option('root') or self.get_option('build_directory')
- if not build_directory:
- build_directory = self._config.build_directory(self.get_option('configuration'))
- # Set --build-directory here Since this modifies the options object used by the worker subprocesses,
- # it avoids the slow call out to build_directory in each subprocess.
- self.set_option_default('build_directory', build_directory)
- return self._filesystem.join(self._filesystem.abspath(build_directory), *comps)
-
- def _path_to_driver(self):
- return self._build_path(self.driver_name())
-
- def _path_to_webcore_library(self):
- return None
-
- def _path_to_helper(self):
- return None
-
- def _path_to_image_diff(self):
- return self._build_path('ImageDiff')
-
- def _path_to_wdiff(self):
- # FIXME: This does not exist on a default Mac OS X Leopard install.
- return 'wdiff'
-
- # FIXME: This does not belong on the port object.
- @memoized
- def _path_to_apache(self):
- # The Apache binary path can vary depending on OS and distribution
- # See http://wiki.apache.org/httpd/DistrosDefaultLayout
- for path in ["/usr/sbin/httpd", "/usr/sbin/apache2"]:
- if self._filesystem.exists(path):
- return path
- _log.error("Could not find apache. Not installed or unknown path.")
- return None
-
- # FIXME: This belongs on some platform abstraction instead of Port.
- def _is_redhat_based(self):
- return self._filesystem.exists('/etc/redhat-release')
-
- def _is_debian_based(self):
- return self._filesystem.exists('/etc/debian_version')
-
- # We pass sys_platform into this method to make it easy to unit test.
- def _apache_config_file_name_for_platform(self, sys_platform):
- if sys_platform == 'cygwin':
- return 'cygwin-httpd.conf' # CYGWIN is the only platform to still use Apache 1.3.
- if sys_platform.startswith('linux'):
- if self._is_redhat_based():
- return 'fedora-httpd.conf' # This is an Apache 2.x config file despite the naming.
- if self._is_debian_based():
- return 'apache2-debian-httpd.conf'
- # All platforms use apache2 except for CYGWIN (and Mac OS X Tiger and prior, which we no longer support).
- return "apache2-httpd.conf"
-
- def _path_to_apache_config_file(self):
- config_file_name = self._apache_config_file_name_for_platform(sys.platform)
- return self._filesystem.join(self.layout_tests_dir(), 'http', 'conf', config_file_name)
-
-
-class WebKitDriver(Driver):
- """WebKit implementation of the DumpRenderTree/WebKitTestRunner interface."""
-
- def __init__(self, port, worker_number, pixel_tests, no_timeout=False):
- Driver.__init__(self, port, worker_number, pixel_tests, no_timeout)
- self._driver_tempdir = None
- # WebKitTestRunner can report back subprocess crashes by printing
- # "#CRASHED - PROCESSNAME". Since those can happen at any time
- # and ServerProcess won't be aware of them (since the actual tool
- # didn't crash, just a subprocess) we record the crashed subprocess name here.
- self._crashed_process_name = None
- self._crashed_pid = None
-
- # WebKitTestRunner can report back subprocesses that became unresponsive
- # This could mean they crashed.
- self._subprocess_was_unresponsive = False
-
- # stderr reading is scoped on a per-test (not per-block) basis, so we store the accumulated
- # stderr output, as well as if we've seen #EOF on this driver instance.
- # FIXME: We should probably remove _read_first_block and _read_optional_image_block and
- # instead scope these locally in run_test.
- self.error_from_test = str()
- self.err_seen_eof = False
- self._server_process = None
-
- def __del__(self):
- self.stop()
-
- def cmd_line(self, pixel_tests, per_test_args):
- cmd = self._command_wrapper(self._port.get_option('wrapper'))
- cmd.append(self._port._path_to_driver())
- if self._port.get_option('gc_between_tests'):
- cmd.append('--gc-between-tests')
- if self._port.get_option('complex_text'):
- cmd.append('--complex-text')
- if self._port.get_option('threaded'):
- cmd.append('--threaded')
- if self._no_timeout:
- cmd.append('--no-timeout')
- # FIXME: We need to pass --timeout=SECONDS to WebKitTestRunner for WebKit2.
-
- cmd.extend(self._port.get_option('additional_drt_flag', []))
-
- if pixel_tests:
- cmd.append('--pixel-tests')
- cmd.extend(per_test_args)
-
- cmd.append('-')
- return cmd
-
- def _start(self, pixel_tests, per_test_args):
- self.stop()
- self._driver_tempdir = self._port._filesystem.mkdtemp(prefix='%s-' % self._port.driver_name())
- server_name = self._port.driver_name()
- environment = self._port.setup_environ_for_server(server_name)
- environment['DYLD_LIBRARY_PATH'] = self._port._build_path()
- environment['DYLD_FRAMEWORK_PATH'] = self._port._build_path()
- # FIXME: We're assuming that WebKitTestRunner checks this DumpRenderTree-named environment variable.
- environment['DUMPRENDERTREE_TEMP'] = str(self._driver_tempdir)
- environment['LOCAL_RESOURCE_ROOT'] = self._port.layout_tests_dir()
- self._crashed_process_name = None
- self._crashed_pid = None
- self._server_process = server_process.ServerProcess(self._port, server_name, self.cmd_line(pixel_tests, per_test_args), environment)
-
- def has_crashed(self):
- if self._server_process is None:
- return False
- if self._crashed_process_name:
- return True
- if self._server_process.has_crashed():
- self._crashed_process_name = self._server_process.name()
- self._crashed_pid = self._server_process.pid()
- return True
- return False
-
- def _check_for_driver_crash(self, error_line):
- if error_line == "#CRASHED\n":
- # This is used on Windows to report that the process has crashed
- # See http://trac.webkit.org/changeset/65537.
- self._crashed_process_name = self._server_process.name()
- self._crashed_pid = self._server_process.pid()
- elif (error_line.startswith("#CRASHED - WebProcess")
- or error_line.startswith("#PROCESS UNRESPONSIVE - WebProcess")):
- # WebKitTestRunner uses this to report that the WebProcess subprocess crashed.
- pid = None
- m = re.search('pid (\d+)', error_line)
- if m:
- pid = int(m.group(1))
- self._crashed_process_name = 'WebProcess'
- self._crashed_pid = pid
- # FIXME: delete this after we're sure this code is working :)
- _log.debug('WebProcess crash, pid = %s, error_line = %s' % (str(pid), error_line))
- if error_line.startswith("#PROCESS UNRESPONSIVE - WebProcess"):
- self._subprocess_was_unresponsive = True
- return True
- return self.has_crashed()
-
- def _command_from_driver_input(self, driver_input):
- # FIXME: performance tests pass in full URLs instead of test names.
- if driver_input.test_name.startswith('http://') or driver_input.test_name.startswith('https://') or driver_input.test_name == ('about:blank'):
- command = driver_input.test_name
- elif self.is_http_test(driver_input.test_name):
- command = self.test_to_uri(driver_input.test_name)
- else:
- command = self._port.abspath_for_test(driver_input.test_name)
- if sys.platform == 'cygwin':
- command = cygpath(command)
-
- if driver_input.image_hash:
- # "'" is the separator of command fields.
- command += "'" + driver_input.image_hash
- return command + "\n"
-
- def _read_first_block(self, deadline):
- # returns (text_content, audio_content)
- block = self._read_block(deadline)
- if block.content_type == 'audio/wav':
- return (None, block.decoded_content)
- return (block.decoded_content, None)
-
- def _read_optional_image_block(self, deadline):
- # returns (image, actual_image_hash)
- block = self._read_block(deadline, wait_for_stderr_eof=True)
- if block.content and block.content_type == 'image/png':
- return (block.decoded_content, block.content_hash)
- return (None, block.content_hash)
-
- def run_test(self, driver_input):
- start_time = time.time()
- self.start(driver_input.should_run_pixel_test, driver_input.args)
- test_begin_time = time.time()
- self.error_from_test = str()
- self.err_seen_eof = False
-
- command = self._command_from_driver_input(driver_input)
- deadline = test_begin_time + int(driver_input.timeout) / 1000.0
-
- self._server_process.write(command)
- text, audio = self._read_first_block(deadline) # First block is either text or audio
- image, actual_image_hash = self._read_optional_image_block(deadline) # The second (optional) block is image data.
-
- # We may not have read all of the output if an error (crash) occured.
- # Since some platforms output the stacktrace over error, we should
- # dump any buffered error into self.error_from_test.
- # FIXME: We may need to also read stderr until the process dies?
- self.error_from_test += self._server_process.pop_all_buffered_stderr()
-
- crash_log = None
- if self.has_crashed():
- crash_log = self._port._get_crash_log(self._crashed_process_name, self._crashed_pid, text, self.error_from_test,
- newer_than=start_time)
-
- # If we don't find a crash log use a placeholder error message instead.
- if not crash_log:
- crash_log = 'no crash log found for %s:%d.' % (self._crashed_process_name, self._crashed_pid)
- # If we were unresponsive append a message informing there may not have been a crash.
- if self._subprocess_was_unresponsive:
- crash_log += ' Process failed to become responsive before timing out.'
-
- timeout = self._server_process.timed_out
- if timeout:
- # DRT doesn't have a built in timer to abort the test, so we might as well
- # kill the process directly and not wait for it to shut down cleanly (since it may not).
- self._server_process.kill()
-
- return DriverOutput(text, image, actual_image_hash, audio,
- crash=self.has_crashed(), test_time=time.time() - test_begin_time,
- timeout=timeout, error=self.error_from_test,
- crashed_process_name=self._crashed_process_name,
- crashed_pid=self._crashed_pid, crash_log=crash_log)
-
- def _read_header(self, block, line, header_text, header_attr, header_filter=None):
- if line.startswith(header_text) and getattr(block, header_attr) is None:
- value = line.split()[1]
- if header_filter:
- value = header_filter(value)
- setattr(block, header_attr, value)
- return True
- return False
-
- def _process_stdout_line(self, block, line):
- if (self._read_header(block, line, 'Content-Type: ', 'content_type')
- or self._read_header(block, line, 'Content-Transfer-Encoding: ', 'encoding')
- or self._read_header(block, line, 'Content-Length: ', '_content_length', int)
- or self._read_header(block, line, 'ActualHash: ', 'content_hash')):
- return
- # Note, we're not reading ExpectedHash: here, but we could.
- # If the line wasn't a header, we just append it to the content.
- block.content += line
-
- def _strip_eof(self, line):
- if line and line.endswith("#EOF\n"):
- return line[:-5], True
- return line, False
-
- def _read_block(self, deadline, wait_for_stderr_eof=False):
- block = ContentBlock()
- out_seen_eof = False
-
- while not self.has_crashed():
- if out_seen_eof and (self.err_seen_eof or not wait_for_stderr_eof):
- break
-
- if self.err_seen_eof:
- out_line = self._server_process.read_stdout_line(deadline)
- err_line = None
- elif out_seen_eof:
- out_line = None
- err_line = self._server_process.read_stderr_line(deadline)
- else:
- out_line, err_line = self._server_process.read_either_stdout_or_stderr_line(deadline)
-
- if self._server_process.timed_out or self.has_crashed():
- break
-
- if out_line:
- assert not out_seen_eof
- out_line, out_seen_eof = self._strip_eof(out_line)
- if err_line:
- assert not self.err_seen_eof
- err_line, self.err_seen_eof = self._strip_eof(err_line)
-
- if out_line:
- if out_line[-1] != "\n":
- _log.error("Last character read from DRT stdout line was not a newline! This indicates either a NRWT or DRT bug.")
- content_length_before_header_check = block._content_length
- self._process_stdout_line(block, out_line)
- # FIXME: Unlike HTTP, DRT dumps the content right after printing a Content-Length header.
- # Don't wait until we're done with headers, just read the binary blob right now.
- if content_length_before_header_check != block._content_length:
- block.content = self._server_process.read_stdout(deadline, block._content_length)
-
- if err_line:
- if self._check_for_driver_crash(err_line):
- break
- self.error_from_test += err_line
-
- block.decode_content()
- return block
-
- def start(self, pixel_tests, per_test_args):
- if not self._server_process:
- self._start(pixel_tests, per_test_args)
-
- def stop(self):
- if self._server_process:
- self._server_process.stop()
- self._server_process = None
-
- if self._driver_tempdir:
- self._port._filesystem.rmtree(str(self._driver_tempdir))
- self._driver_tempdir = None
-
-
-class ContentBlock(object):
- def __init__(self):
- self.content_type = None
- self.encoding = None
- self.content_hash = None
- self._content_length = None
- # Content is treated as binary data even though the text output is usually UTF-8.
- self.content = str() # FIXME: Should be bytearray() once we require Python 2.6.
- self.decoded_content = None
-
- def decode_content(self):
- if self.encoding == 'base64':
- self.decoded_content = base64.b64decode(self.content)
- else:
- self.decoded_content = self.content
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py
index 54ad31919..078182541 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py
@@ -34,7 +34,7 @@ from webkitpy.common.system.outputcapture import OutputCapture
from webkitpy.common.system.systemhost_mock import MockSystemHost
from webkitpy.layout_tests.models.test_configuration import TestConfiguration
from webkitpy.layout_tests.port import port_testcase
-from webkitpy.layout_tests.port.webkit import WebKitPort, WebKitDriver
+from webkitpy.layout_tests.port.webkit import WebKitPort
from webkitpy.layout_tests.port.config_mock import MockConfig
from webkitpy.tool.mocktool import MockOptions
@@ -231,182 +231,3 @@ class WebKitPortTest(port_testcase.PortTestCase):
# Mock out _apache_config_file_name_for_platform to ignore the passed sys.platform value.
port._apache_config_file_name_for_platform = lambda platform: 'httpd.conf'
self.assertEquals(port._path_to_apache_config_file(), '/mock-checkout/LayoutTests/http/conf/httpd.conf')
-
-
-class MockServerProcess(object):
- def __init__(self, lines=None):
- self.timed_out = False
- self.lines = lines or []
- self.crashed = False
-
- def has_crashed(self):
- return self.crashed
-
- def read_stdout_line(self, deadline):
- return self.lines.pop(0) + "\n"
-
- def read_stdout(self, deadline, size):
- first_line = self.lines[0]
- if size > len(first_line):
- self.lines.pop(0)
- remaining_size = size - len(first_line) - 1
- if not remaining_size:
- return first_line + "\n"
- return first_line + "\n" + self.read_stdout(deadline, remaining_size)
- result = self.lines[0][:size]
- self.lines[0] = self.lines[0][size:]
- return result
-
- def read_either_stdout_or_stderr_line(self, deadline):
- # FIXME: We should have tests which intermix stderr and stdout lines.
- return self.read_stdout_line(deadline), None
-
- def start(self):
- return
-
- def stop(self, kill_directly=False):
- return
-
- def kill(self):
- return
-
-
-class WebKitDriverTest(unittest.TestCase):
- def test_read_block(self):
- port = TestWebKitPort()
- driver = WebKitDriver(port, 0, pixel_tests=False)
- driver._server_process = MockServerProcess([
- 'ActualHash: foobar',
- 'Content-Type: my_type',
- 'Content-Transfer-Encoding: none',
- "#EOF",
- ])
- content_block = driver._read_block(0)
- self.assertEquals(content_block.content_type, 'my_type')
- self.assertEquals(content_block.encoding, 'none')
- self.assertEquals(content_block.content_hash, 'foobar')
- driver._server_process = None
-
- def test_read_binary_block(self):
- port = TestWebKitPort()
- driver = WebKitDriver(port, 0, pixel_tests=True)
- driver._server_process = MockServerProcess([
- 'ActualHash: actual',
- 'ExpectedHash: expected',
- 'Content-Type: image/png',
- 'Content-Length: 9',
- "12345678",
- "#EOF",
- ])
- content_block = driver._read_block(0)
- self.assertEquals(content_block.content_type, 'image/png')
- self.assertEquals(content_block.content_hash, 'actual')
- self.assertEquals(content_block.content, '12345678\n')
- self.assertEquals(content_block.decoded_content, '12345678\n')
- driver._server_process = None
-
- def test_read_base64_block(self):
- port = TestWebKitPort()
- driver = WebKitDriver(port, 0, pixel_tests=True)
- driver._server_process = MockServerProcess([
- 'ActualHash: actual',
- 'ExpectedHash: expected',
- 'Content-Type: image/png',
- 'Content-Transfer-Encoding: base64',
- 'Content-Length: 12',
- 'MTIzNDU2NzgK#EOF',
- ])
- content_block = driver._read_block(0)
- self.assertEquals(content_block.content_type, 'image/png')
- self.assertEquals(content_block.content_hash, 'actual')
- self.assertEquals(content_block.encoding, 'base64')
- self.assertEquals(content_block.content, 'MTIzNDU2NzgK')
- self.assertEquals(content_block.decoded_content, '12345678\n')
-
- def test_no_timeout(self):
- port = TestWebKitPort()
- driver = WebKitDriver(port, 0, pixel_tests=True, no_timeout=True)
- self.assertEquals(driver.cmd_line(True, []), ['/mock-build/DumpRenderTree', '--no-timeout', '--pixel-tests', '-'])
-
- def test_check_for_driver_crash(self):
- port = TestWebKitPort()
- driver = WebKitDriver(port, 0, pixel_tests=True)
-
- class FakeServerProcess(object):
- def __init__(self, crashed):
- self.crashed = crashed
-
- def pid(self):
- return 1234
-
- def name(self):
- return 'FakeServerProcess'
-
- def has_crashed(self):
- return self.crashed
-
- def stop(self):
- pass
-
- def assert_crash(driver, error_line, crashed, name, pid, unresponsive=False):
- self.assertEquals(driver._check_for_driver_crash(error_line), crashed)
- self.assertEquals(driver._crashed_process_name, name)
- self.assertEquals(driver._crashed_pid, pid)
- self.assertEquals(driver._subprocess_was_unresponsive, unresponsive)
- driver.stop()
-
- driver._server_process = FakeServerProcess(False)
- assert_crash(driver, '', False, None, None)
-
- driver._crashed_process_name = None
- driver._crashed_pid = None
- driver._server_process = FakeServerProcess(False)
- driver._subprocess_was_unresponsive = False
- assert_crash(driver, '#CRASHED\n', True, 'FakeServerProcess', 1234)
-
- driver._crashed_process_name = None
- driver._crashed_pid = None
- driver._server_process = FakeServerProcess(False)
- driver._subprocess_was_unresponsive = False
- assert_crash(driver, '#CRASHED - WebProcess\n', True, 'WebProcess', None)
-
- driver._crashed_process_name = None
- driver._crashed_pid = None
- driver._server_process = FakeServerProcess(False)
- driver._subprocess_was_unresponsive = False
- assert_crash(driver, '#CRASHED - WebProcess (pid 8675)\n', True, 'WebProcess', 8675)
-
- driver._crashed_process_name = None
- driver._crashed_pid = None
- driver._server_process = FakeServerProcess(False)
- driver._subprocess_was_unresponsive = False
- assert_crash(driver, '#PROCESS UNRESPONSIVE - WebProcess (pid 8675)\n', True, 'WebProcess', 8675, True)
-
- driver._crashed_process_name = None
- driver._crashed_pid = None
- driver._server_process = FakeServerProcess(True)
- driver._subprocess_was_unresponsive = False
- assert_crash(driver, '', True, 'FakeServerProcess', 1234)
-
- def test_creating_a_port_does_not_write_to_the_filesystem(self):
- port = TestWebKitPort()
- driver = WebKitDriver(port, 0, pixel_tests=True)
- self.assertEquals(port._filesystem.written_files, {})
- self.assertEquals(port._filesystem.last_tmpdir, None)
-
- def test_stop_cleans_up_properly(self):
- port = TestWebKitPort()
- driver = WebKitDriver(port, 0, pixel_tests=True)
- driver.start(True, [])
- last_tmpdir = port._filesystem.last_tmpdir
- self.assertNotEquals(last_tmpdir, None)
- driver.stop()
- self.assertFalse(port._filesystem.isdir(last_tmpdir))
-
- def test_two_starts_cleans_up_properly(self):
- port = TestWebKitPort()
- driver = WebKitDriver(port, 0, pixel_tests=True)
- driver.start(True, [])
- last_tmpdir = port._filesystem.last_tmpdir
- driver._start(True, [])
- self.assertFalse(port._filesystem.isdir(last_tmpdir))
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver.py b/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver.py
index cfcb5a18c..b20ca98ee 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver.py
@@ -32,13 +32,13 @@ import signal
import subprocess
from webkitpy.layout_tests.port.server_process import ServerProcess
-from webkitpy.layout_tests.port.webkit import WebKitDriver
+from webkitpy.layout_tests.port.driver import Driver
from webkitpy.common.system.executive import Executive
_log = logging.getLogger(__name__)
-class XvfbDriver(WebKitDriver):
+class XvfbDriver(Driver):
def _start(self, pixel_tests, per_test_args):
# Collect the number of X servers running already and make
@@ -66,7 +66,7 @@ class XvfbDriver(WebKitDriver):
self._server_process = ServerProcess(self._port, server_name, self.cmd_line(pixel_tests, per_test_args), environment)
def stop(self):
- WebKitDriver.stop(self)
+ super(XvfbDriver, self).stop()
if getattr(self, '_xvfb_process', None):
try:
self._xvfb_process.terminate()
diff --git a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
index 60db587e0..d15166606 100755
--- a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
+++ b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
@@ -425,6 +425,8 @@ def parse_args(args=None):
# https://bugs.webkit.org/show_bug.cgi?id=91539.
optparse.make_option("--shard-ref-tests", action="store_true",
help="Run ref tests in dedicated shard(s). Enabled on Android by default."),
+ optparse.make_option("--additional-env-var", type="string", action="append", default=[],
+ help="Passes that environment variable to the tests (--additional-env-var=NAME=VALUE)"),
]))
option_group_definitions.append(("Miscellaneous Options", [
diff --git a/Tools/Scripts/webkitpy/performance_tests/perftest.py b/Tools/Scripts/webkitpy/performance_tests/perftest.py
index de63f3e8d..8623c0aee 100644
--- a/Tools/Scripts/webkitpy/performance_tests/perftest.py
+++ b/Tools/Scripts/webkitpy/performance_tests/perftest.py
@@ -99,7 +99,9 @@ class PerfTest(object):
# Following are for handle existing test like Dromaeo
re.compile(re.escape("""main frame - has 1 onunload handler(s)""")),
re.compile(re.escape("""frame "<!--framePath //<!--frame0-->-->" - has 1 onunload handler(s)""")),
- re.compile(re.escape("""frame "<!--framePath //<!--frame0-->/<!--frame0-->-->" - has 1 onunload handler(s)"""))]
+ re.compile(re.escape("""frame "<!--framePath //<!--frame0-->/<!--frame0-->-->" - has 1 onunload handler(s)""")),
+ # Following is for html5.html
+ re.compile(re.escape("""Blocked access to external URL http://www.whatwg.org/specs/web-apps/current-work/"""))]
_statistics_keys = ['avg', 'median', 'stdev', 'min', 'max']
diff --git a/Tools/Scripts/webkitpy/style/checker.py b/Tools/Scripts/webkitpy/style/checker.py
index 8cd8745bf..10f3448ec 100644
--- a/Tools/Scripts/webkitpy/style/checker.py
+++ b/Tools/Scripts/webkitpy/style/checker.py
@@ -178,8 +178,9 @@ _PATH_RULES_SPECIFIER = [
["-build/header_guard"]),
([# assembler has lots of opcodes that use underscores, so
# we don't check for underscores in that directory.
- "/Source/JavaScriptCore/assembler/"],
- ["-readability/naming"]),
+ "Source/JavaScriptCore/assembler/",
+ "Source/JavaScriptCore/jit/JIT"],
+ ["-readability/naming/underscores"]),
([# JITStubs has an usual syntax which causes false alarms for a few checks.
"JavaScriptCore/jit/JITStubs.cpp"],
["-readability/parameter_name",
@@ -219,7 +220,9 @@ _PATH_RULES_SPECIFIER = [
"Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer1.cpp",
"Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp",
"Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp",
- "Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp"],
+ "Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp",
+ "Source/WebCore/platform/network/soup/ProxyResolverSoup.cpp",
+ "Source/WebCore/platform/network/soup/ProxyResolverSoup.h"],
["-readability/naming"]),
# For third-party Python code, keep only the following checks--
diff --git a/Tools/Scripts/webkitpy/style/checkers/cpp.py b/Tools/Scripts/webkitpy/style/checkers/cpp.py
index ba1153087..78cd88250 100644
--- a/Tools/Scripts/webkitpy/style/checkers/cpp.py
+++ b/Tools/Scripts/webkitpy/style/checkers/cpp.py
@@ -3137,11 +3137,13 @@ def check_identifier_name_in_declaration(filename, line_number, line, file_state
and not modified_identifier.startswith('Eina_')
and not modified_identifier.startswith('Evas_')
and not modified_identifier.startswith('Ewk_')
+ and not modified_identifier.startswith('cti_')
and not modified_identifier.find('::qt_') >= 0
and not modified_identifier.find('::_q_') >= 0
and not modified_identifier == "const_iterator"
- and not modified_identifier == "vm_throw"):
- error(line_number, 'readability/naming', 4, identifier + " is incorrectly named. Don't use underscores in your identifier names.")
+ and not modified_identifier == "vm_throw"
+ and not modified_identifier == "DFG_OPERATION"):
+ error(line_number, 'readability/naming/underscores', 4, identifier + " is incorrectly named. Don't use underscores in your identifier names.")
# Check for variables named 'l', these are too easy to confuse with '1' in some fonts
if modified_identifier == 'l':
@@ -3564,6 +3566,7 @@ class CppChecker(object):
'readability/multiline_string',
'readability/parameter_name',
'readability/naming',
+ 'readability/naming/underscores',
'readability/null',
'readability/pass_ptr',
'readability/streams',
diff --git a/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py b/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py
index 1675c7010..339897fe8 100644
--- a/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py
+++ b/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py
@@ -4425,7 +4425,7 @@ class WebKitStyleTest(CppStyleTestBase):
'foo.cpp')
def test_names(self):
- name_underscore_error_message = " is incorrectly named. Don't use underscores in your identifier names. [readability/naming] [4]"
+ name_underscore_error_message = " is incorrectly named. Don't use underscores in your identifier names. [readability/naming/underscores] [4]"
name_tooshort_error_message = " is incorrectly named. Don't use the single letter 'l' as an identifier name. [readability/naming] [4]"
# Basic cases from WebKit style guide.
@@ -4569,11 +4569,11 @@ class WebKitStyleTest(CppStyleTestBase):
# Test that this doesn't also apply to files not in a 'gtk' directory.
self.assert_lint('void webkit_web_view_load(int var1, int var2)',
'webkit_web_view_load is incorrectly named. Don\'t use underscores in your identifier names.'
- ' [readability/naming] [4]', 'Source/Webkit/webkit/foo.cpp')
+ ' [readability/naming/underscores] [4]', 'Source/Webkit/webkit/foo.cpp')
# Test that this doesn't also apply to names that don't start with 'webkit_'.
self.assert_lint_one_of_many_errors_re('void otherkit_web_view_load(int var1, int var2)',
'otherkit_web_view_load is incorrectly named. Don\'t use underscores in your identifier names.'
- ' [readability/naming] [4]', 'Source/Webkit/webkit/foo.cpp')
+ ' [readability/naming/underscores] [4]', 'Source/Webkit/webkit/foo.cpp')
# There is an exception for some unit tests that begin with "tst_".
self.assert_lint('void tst_QWebFrame::arrayObjectEnumerable(int var1, int var2)', '')
diff --git a/Tools/Scripts/webkitpy/test/main.py b/Tools/Scripts/webkitpy/test/main.py
index abb297b2b..2968e7daa 100644
--- a/Tools/Scripts/webkitpy/test/main.py
+++ b/Tools/Scripts/webkitpy/test/main.py
@@ -24,6 +24,7 @@
"""unit testing code for webkitpy."""
import logging
+import multiprocessing
import optparse
import StringIO
import sys
@@ -63,8 +64,8 @@ class Tester(object):
help='do not run the integration tests')
parser.add_option('-p', '--pass-through', action='store_true', default=False,
help='be debugger friendly by passing captured output through to the system')
- parser.add_option('-j', '--child-processes', action='store', type='int', default=1,
- help='number of tests to run in parallel')
+ parser.add_option('-j', '--child-processes', action='store', type='int', default=(1 if sys.platform == 'win32' else multiprocessing.cpu_count()),
+ help='number of tests to run in parallel (default=%default)')
parser.epilog = ('[args...] is an optional list of modules, test_classes, or individual tests. '
'If no args are given, all the tests will be run.')