summaryrefslogtreecommitdiffstats
path: root/WebKitTools/Scripts/webkitpy/layout_tests
diff options
context:
space:
mode:
Diffstat (limited to 'WebKitTools/Scripts/webkitpy/layout_tests')
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests.py61
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py19
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py71
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/base.py19
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py33
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py42
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py8
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/test.py11
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py26
-rwxr-xr-xWebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py22
-rwxr-xr-xWebKitTools/Scripts/webkitpy/layout_tests/update_webgl_conformance_tests.py160
-rw-r--r--WebKitTools/Scripts/webkitpy/layout_tests/update_webgl_conformance_tests_unittest.py102
12 files changed, 466 insertions, 108 deletions
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests.py
index c543d91..51dcac8 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests.py
@@ -36,8 +36,10 @@ import os
import subprocess
import sys
import re
+import webkitpy.common.checkout.scm as scm
import webkitpy.common.system.executive as executive
import webkitpy.common.system.logutils as logutils
+import webkitpy.common.system.ospath as ospath
import webkitpy.layout_tests.port.factory as port_factory
_log = logutils.get_logger(__file__)
@@ -52,11 +54,14 @@ def port_fallbacks():
back on. All platforms fall back on 'base'.
"""
fallbacks = {_BASE_PLATFORM: []}
- for port_name in os.listdir(os.path.join('LayoutTests', 'platform')):
+ platform_dir = os.path.join(scm.find_checkout_root(), 'LayoutTests',
+ 'platform')
+ for port_name in os.listdir(platform_dir):
try:
platforms = port_factory.get(port_name).baseline_search_path()
except NotImplementedError:
- _log.error("'%s' lacks baseline_search_path(), please fix." % port_name)
+ _log.error("'%s' lacks baseline_search_path(), please fix."
+ % port_name)
fallbacks[port_name] = [_BASE_PLATFORM]
continue
fallbacks[port_name] = [os.path.basename(p) for p in platforms][1:]
@@ -102,7 +107,8 @@ def cluster_file_hashes(glob_pattern):
# Fill in the map.
cmd = ('git', 'ls-tree', '-r', 'HEAD', 'LayoutTests')
try:
- git_output = executive.Executive().run_command(cmd)
+ git_output = executive.Executive().run_command(cmd,
+ cwd=scm.find_checkout_root())
except OSError, e:
if e.errno == 2: # No such file or directory.
_log.error("Error: 'No such file' when running git.")
@@ -156,11 +162,28 @@ def has_intermediate_results(test, fallbacks, matching_platform,
return False
-def find_dups(hashes, port_fallbacks):
+def get_relative_test_path(filename, relative_to,
+ checkout_root=scm.find_checkout_root()):
+ """Constructs a relative path to |filename| from |relative_to|.
+ Args:
+ filename: The test file we're trying to get a relative path to.
+ relative_to: The absolute path we're relative to.
+ Returns:
+ A relative path to filename or None if |filename| is not below
+ |relative_to|.
+ """
+ layout_test_dir = os.path.join(checkout_root, 'LayoutTests')
+ abs_path = os.path.join(layout_test_dir, filename)
+ return ospath.relpath(abs_path, relative_to)
+
+
+def find_dups(hashes, port_fallbacks, relative_to):
"""Yields info about redundant test expectations.
Args:
hashes: a list of hashes as returned by cluster_file_hashes.
- port_fallbacks: a list of fallback information as returned by get_port_fallbacks.
+ port_fallbacks: a list of fallback information as returned by
+ get_port_fallbacks.
+ relative_to: the directory that we want the results relative to
Returns:
a tuple containing (test, platform, fallback, platforms)
"""
@@ -176,13 +199,24 @@ def find_dups(hashes, port_fallbacks):
# See if any of the platforms are redundant with each other.
for platform in platforms.keys():
for fallback in port_fallbacks[platform]:
- if fallback in platforms.keys():
- # We have to verify that there isn't an intermediate result
- # that causes this duplicate hash to exist.
- if not has_intermediate_results(test,
- port_fallbacks[platform], fallback):
- path = os.path.join('LayoutTests', platforms[platform])
- yield test, platform, fallback, path
+ if fallback not in platforms.keys():
+ continue
+ # We have to verify that there isn't an intermediate result
+ # that causes this duplicate hash to exist.
+ if has_intermediate_results(test, port_fallbacks[platform],
+ fallback):
+ continue
+ # We print the relative path so it's easy to pipe the results
+ # to xargs rm.
+ path = get_relative_test_path(platforms[platform], relative_to)
+ if not path:
+ continue
+ yield {
+ 'test': test,
+ 'platform': platform,
+ 'fallback': fallback,
+ 'path': path,
+ }
def deduplicate(glob_pattern):
@@ -194,5 +228,4 @@ def deduplicate(glob_pattern):
"""
fallbacks = port_fallbacks()
hashes = cluster_file_hashes(glob_pattern)
- return [{'test': test, 'path': path, 'platform': platform, 'fallback': fallback}
- for test, platform, fallback, path in find_dups(hashes, fallbacks)]
+ return list(find_dups(hashes, fallbacks, os.getcwd()))
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py
index be2e381..bb9604f 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/deduplicate_tests_unittest.py
@@ -186,3 +186,22 @@ class ListDuplicatesTest(unittest.TestCase):
'fallback': 'chromium-win',
'platform': 'chromium-linux'},
result[0])
+
+ def test_get_relative_test_path(self):
+ checkout_root = scm.find_checkout_root()
+ layout_test_dir = os.path.join(checkout_root, 'LayoutTests')
+ test_cases = (
+ ('platform/mac/test.html',
+ ('platform/mac/test.html', layout_test_dir)),
+ ('LayoutTests/platform/mac/test.html',
+ ('platform/mac/test.html', checkout_root)),
+ (None,
+ ('platform/mac/test.html', os.path.join(checkout_root, 'WebCore'))),
+ ('test.html',
+ ('platform/mac/test.html', os.path.join(layout_test_dir, 'platform/mac'))),
+ (None,
+ ('platform/mac/test.html', os.path.join(layout_test_dir, 'platform/win'))),
+ )
+ for expected, inputs in test_cases:
+ self.assertEquals(expected,
+ deduplicate_tests.get_relative_test_path(*inputs))
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 9b963ca..970de60 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
@@ -72,20 +72,19 @@ def log_stack(stack):
_log.error(' %s' % line.strip())
-def _process_output(port, test_info, test_types, test_args, configuration,
- output_dir, crash, timeout, test_run_time, actual_checksum,
+def _process_output(port, options, test_info, test_types, test_args,
+ crash, timeout, test_run_time, actual_checksum,
output, error):
"""Receives the output from a DumpRenderTree process, subjects it to a
number of tests, and returns a list of failure types the test produced.
Args:
port: port-specific hooks
+ options: command line options argument from optparse
proc: an active DumpRenderTree process
test_info: Object containing the test filename, uri and timeout
test_types: list of test types to subject the output to
test_args: arguments to be passed to each test
- configuration: Debug or Release
- output_dir: directory to put crash stack traces into
Returns: a TestResult object
"""
@@ -106,7 +105,8 @@ def _process_output(port, test_info, test_types, test_args, configuration,
_log.debug("Stacktrace for %s:\n%s" % (test_info.filename, error))
# Strip off "file://" since RelativeTestFilename expects
# filesystem paths.
- filename = os.path.join(output_dir, port.relative_test_filename(
+ filename = os.path.join(options.results_directory,
+ port.relative_test_filename(
test_info.filename))
filename = os.path.splitext(filename)[0] + "-stack.txt"
port.maybe_make_directory(os.path.split(filename)[0])
@@ -122,7 +122,7 @@ def _process_output(port, test_info, test_types, test_args, configuration,
start_diff_time = time.time()
new_failures = test_type.compare_output(port, test_info.filename,
output, local_test_args,
- configuration)
+ options.configuration)
# Don't add any more failures if we already have a crash, so we don't
# double-report those tests. We do double-report for timeouts since
# we still want to see the text and image output.
@@ -166,25 +166,23 @@ class TestResult(object):
class SingleTestThread(threading.Thread):
"""Thread wrapper for running a single test file."""
- def __init__(self, port, image_path, shell_args, test_info,
- test_types, test_args, configuration, output_dir):
+ def __init__(self, port, options, test_info, test_types, test_args):
"""
Args:
port: object implementing port-specific hooks
+ options: command line argument object from optparse
test_info: Object containing the test filename, uri and timeout
- output_dir: Directory to put crash stacks into.
- See TestShellThread for documentation of the remaining arguments.
+ test_types: A list of TestType objects to run the test output
+ against.
+ test_args: A TestArguments object to pass to each TestType.
"""
threading.Thread.__init__(self)
self._port = port
- self._image_path = image_path
- self._shell_args = shell_args
+ self._options = options
self._test_info = test_info
self._test_types = test_types
self._test_args = test_args
- self._configuration = configuration
- self._output_dir = output_dir
self._driver = None
def run(self):
@@ -194,17 +192,17 @@ class SingleTestThread(threading.Thread):
# FIXME: this is a separate routine to work around a bug
# in coverage: see http://bitbucket.org/ned/coveragepy/issue/85.
test_info = self._test_info
- self._driver = self._port.create_driver(self._image_path,
- self._shell_args)
+ self._driver = self._port.create_driver(self._test_args.png_path,
+ self._options)
self._driver.start()
start = time.time()
crash, timeout, actual_checksum, output, error = \
self._driver.run_test(test_info.uri.strip(), test_info.timeout,
test_info.image_hash())
end = time.time()
- self._test_result = _process_output(self._port,
+ self._test_result = _process_output(self._port, self._options,
test_info, self._test_types, self._test_args,
- self._configuration, self._output_dir, crash, timeout, end - start,
+ crash, timeout, end - start,
actual_checksum, output, error)
self._driver.stop()
@@ -248,12 +246,13 @@ class WatchableThread(threading.Thread):
class TestShellThread(WatchableThread):
- def __init__(self, port, filename_list_queue, result_queue,
- test_types, test_args, image_path, shell_args, options):
+ def __init__(self, port, options, filename_list_queue, result_queue,
+ test_types, test_args):
"""Initialize all the local state for this DumpRenderTree thread.
Args:
port: interface to port-specific hooks
+ options: command line options argument from optparse
filename_list_queue: A thread safe Queue class that contains lists
of tuples of (filename, uri) pairs.
result_queue: A thread safe Queue class that will contain tuples of
@@ -261,22 +260,17 @@ class TestShellThread(WatchableThread):
test_types: A list of TestType objects to run the test output
against.
test_args: A TestArguments object to pass to each TestType.
- shell_args: Any extra arguments to be passed to DumpRenderTree.
- options: A property dictionary as produced by optparse. The
- command-line options should match those expected by
- run_webkit_tests; they are typically passed via the
- run_webkit_tests.TestRunner class."""
+
+ """
WatchableThread.__init__(self)
self._port = port
+ self._options = options
self._filename_list_queue = filename_list_queue
self._result_queue = result_queue
self._filename_list = []
self._test_types = test_types
self._test_args = test_args
self._driver = None
- self._image_path = image_path
- self._shell_args = shell_args
- self._options = options
self._directory_timing_stats = {}
self._test_results = []
self._num_tests = 0
@@ -433,13 +427,11 @@ class TestShellThread(WatchableThread):
A TestResult
"""
- worker = SingleTestThread(self._port, self._image_path,
- self._shell_args,
+ worker = SingleTestThread(self._port,
+ self._options,
test_info,
self._test_types,
- self._test_args,
- self._options.configuration,
- self._options.results_directory)
+ self._test_args)
worker.start()
@@ -503,11 +495,11 @@ class TestShellThread(WatchableThread):
self._driver.run_test(test_info.uri, test_info.timeout, image_hash)
end = time.time()
- result = _process_output(self._port, test_info, self._test_types,
- self._test_args, self._options.configuration,
- self._options.results_directory, crash,
- timeout, end - start, actual_checksum,
- output, error)
+ result = _process_output(self._port, self._options,
+ test_info, self._test_types,
+ self._test_args, crash,
+ timeout, end - start, actual_checksum,
+ output, error)
self._test_results.append(result)
return result
@@ -521,7 +513,8 @@ class TestShellThread(WatchableThread):
# poll() is not threadsafe and can throw OSError due to:
# http://bugs.python.org/issue1731717
if (not self._driver or self._driver.poll() is not None):
- self._driver = self._port.create_driver(self._image_path, self._shell_args)
+ self._driver = self._port.create_driver(self._test_args.png_path,
+ self._options)
self._driver.start()
def _kill_dump_render_tree(self):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
index 9125f9e..70beac3 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
@@ -152,6 +152,16 @@ class Port(object):
While this is a generic routine, we include it in the Port
interface so that it can be overriden for testing purposes."""
+
+ # The filenames show up in the diff output, make sure they're
+ # raw bytes and not unicode, so that they don't trigger join()
+ # trying to decode the input.
+ def to_raw_bytes(str):
+ if isinstance(str, unicode):
+ return str.encode('utf-8')
+ return str
+ expected_filename = to_raw_bytes(expected_filename)
+ actual_filename = to_raw_bytes(actual_filename)
diff = difflib.unified_diff(expected_text.splitlines(True),
actual_text.splitlines(True),
expected_filename,
@@ -364,7 +374,7 @@ class Port(object):
results_filename in a users' browser."""
raise NotImplementedError('Port.show_html_results_file')
- def create_driver(self, png_path, options):
+ def create_driver(self, image_path, options):
"""Return a newly created base.Driver subclass for starting/stopping
the test driver."""
raise NotImplementedError('Port.create_driver')
@@ -678,7 +688,7 @@ class Port(object):
class Driver:
"""Abstract interface for the DumpRenderTree interface."""
- def __init__(self, port, png_path, options):
+ def __init__(self, port, png_path, options, executive):
"""Initialize a Driver to subsequently run tests.
Typically this routine will spawn DumpRenderTree in a config
@@ -688,7 +698,10 @@ class Driver:
png_path - an absolute path for the driver to write any image
data for a test (as a PNG). If no path is provided, that
indicates that pixel test results will not be checked.
- options - any port-specific driver options."""
+ options - command line options argument from optparse
+ executive - reference to the process-wide Executive object
+
+ """
raise NotImplementedError('Driver.__init__')
def run_test(self, uri, timeout, checksum):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py
index 1cc426f..780cd22 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py
@@ -66,7 +66,7 @@ class UnitTestPort(base.Port):
def _open_configuration_file(self):
if self._configuration_contents:
return NewStringIO(self._configuration_contents)
- return base.Port._open_configuration_file(self)
+ raise IOError
class PortTest(unittest.TestCase):
@@ -163,6 +163,33 @@ class PortTest(unittest.TestCase):
self.assertFalse(base._wdiff_available)
base._wdiff_available = True
+ def test_diff_text(self):
+ port = base.Port()
+ # Make sure that we don't run into decoding exceptions when the
+ # filenames are unicode, with regular or malformed input (expected or
+ # actual input is always raw bytes, not unicode).
+ port.diff_text('exp', 'act', 'exp.txt', 'act.txt')
+ port.diff_text('exp', 'act', u'exp.txt', 'act.txt')
+ port.diff_text('exp', 'act', u'a\xac\u1234\u20ac\U00008000', 'act.txt')
+
+ port.diff_text('exp' + chr(255), 'act', 'exp.txt', 'act.txt')
+ port.diff_text('exp' + chr(255), 'act', u'exp.txt', 'act.txt')
+
+ # Though expected and actual files should always be read in with no
+ # encoding (and be stored as str objects), test unicode inputs just to
+ # be safe.
+ port.diff_text(u'exp', 'act', 'exp.txt', 'act.txt')
+ port.diff_text(
+ u'a\xac\u1234\u20ac\U00008000', 'act', 'exp.txt', 'act.txt')
+
+ # And make sure we actually get diff output.
+ diff = port.diff_text('foo', 'bar', 'exp.txt', 'act.txt')
+ self.assertTrue('foo' in diff)
+ self.assertTrue('bar' in diff)
+ self.assertTrue('exp.txt' in diff)
+ self.assertTrue('act.txt' in diff)
+ self.assertFalse('nosuchthing' in diff)
+
def test_default_configuration_notfound(self):
port = UnitTestPort()
self.assertEqual(port.default_configuration(), "Release")
@@ -223,8 +250,8 @@ class VirtualTest(unittest.TestCase):
self.assertVirtual(port._shut_down_http_server, None)
def test_virtual_driver_method(self):
- self.assertRaises(NotImplementedError, base.Driver, base.Port, "", None)
- self.assertVirtual(base.Driver, base.Port, "", None)
+ self.assertRaises(NotImplementedError, base.Driver, base.Port(),
+ "", None, None)
def test_virtual_driver_methods(self):
class VirtualDriver(base.Driver):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py
index 896eab1..3fc4613 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py
@@ -194,13 +194,11 @@ class ChromiumPort(base.Port):
def create_driver(self, image_path, options):
"""Starts a new Driver and returns a handle to it."""
- if self._options.use_drt and sys.platform == 'darwin':
- return webkit.WebKitDriver(self, image_path, options, executive=self._executive)
- if self._options.use_drt:
- options += ['--test-shell']
- else:
- options += ['--layout-tests']
- return ChromiumDriver(self, image_path, options, executive=self._executive)
+ if options.use_drt and sys.platform == 'darwin':
+ return webkit.WebKitDriver(self, image_path, options,
+ executive=self._executive)
+ return ChromiumDriver(self, image_path, options,
+ executive=self._executive)
def start_helper(self):
helper_path = self._path_to_helper()
@@ -337,22 +335,32 @@ class ChromiumDriver(base.Driver):
def __init__(self, port, image_path, options, executive=Executive()):
self._port = port
- self._configuration = port._options.configuration
- # FIXME: _options is very confusing, because it's not an Options() element.
- # FIXME: These don't need to be passed into the constructor, but could rather
- # be passed into .start()
self._options = options
self._image_path = image_path
self._executive = executive
+ def _driver_args(self):
+ driver_args = []
+ if self._image_path:
+ driver_args.append("--pixel-tests=" + self._image_path)
+
+ if self._options.use_drt:
+ driver_args.append('--test-shell')
+ else:
+ driver_args.append('--layout-tests')
+
+ if self._options.startup_dialog:
+ driver_args.append('--testshell-startup-dialog')
+
+ if self._options.gp_fault_error_box:
+ driver_args.append('--gp-fault-error-box')
+ return driver_args
+
def start(self):
# FIXME: Should be an error to call this method twice.
- cmd = []
- # FIXME: We should not be grabbing at self._port._options.wrapper directly.
- cmd += self._command_wrapper(self._port._options.wrapper)
- cmd += [self._port._path_to_driver()]
- if self._options:
- cmd += self._options
+ cmd = self._command_wrapper(self._options.wrapper)
+ cmd.append(self._port._path_to_driver())
+ cmd += self._driver_args()
# We need to pass close_fds=True to work around Python bug #2320
# (otherwise we can hang when we kill DumpRenderTree when we are running
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py
index 1af01ad..4940e4c 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py
@@ -86,6 +86,7 @@ class DryRunPort(object):
port_name = port_name[len(pfx):]
else:
port_name = None
+ self._options = options
self.__delegate = factory.get(port_name, options)
def __getattr__(self, name):
@@ -116,16 +117,17 @@ class DryRunPort(object):
pass
def create_driver(self, image_path, options):
- return DryrunDriver(self, image_path, options)
+ return DryrunDriver(self, image_path, options, executive=None)
class DryrunDriver(base.Driver):
"""Dryrun implementation of the DumpRenderTree / Driver interface."""
- def __init__(self, port, image_path, test_driver_options):
+ def __init__(self, port, image_path, options, executive):
self._port = port
- self._driver_options = test_driver_options
+ self._options = options
self._image_path = image_path
+ self._executive = executive
self._layout_tests_dir = None
def poll(self):
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py
index a3a16c3..2ccddb0 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py
@@ -97,7 +97,7 @@ class TestPort(base.Port):
pass
def create_driver(self, image_path, options):
- return TestDriver(image_path, options, self)
+ return TestDriver(self, image_path, options, executive=None)
def start_http_server(self):
pass
@@ -139,10 +139,11 @@ class TestPort(base.Port):
class TestDriver(base.Driver):
"""Test/Dummy implementation of the DumpRenderTree interface."""
- def __init__(self, image_path, test_driver_options, port):
- self._driver_options = test_driver_options
- self._image_path = image_path
+ 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
def poll(self):
@@ -204,7 +205,7 @@ class TestDriver(base.Driver):
crash = False
timeout = False
output = basename + '-txt\n'
- if self._port.options().pixel_tests and (
+ if self._options.pixel_tests and (
'image' in basename or 'check' in basename):
checksum = basename + '-checksum\n'
with open(self._image_path, "w") as f:
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py
index b085ceb..88c9bdf 100644
--- a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py
@@ -199,7 +199,8 @@ class WebKitPort(base.Port):
webbrowser.open(uri, new=1)
def create_driver(self, image_path, options):
- return WebKitDriver(self, image_path, options, executive=self._executive)
+ return WebKitDriver(self, image_path, options,
+ executive=self._executive)
def test_base_platform_names(self):
# At the moment we don't use test platform names, but we have
@@ -405,22 +406,31 @@ class WebKitPort(base.Port):
class WebKitDriver(base.Driver):
"""WebKit implementation of the DumpRenderTree interface."""
- def __init__(self, port, image_path, driver_options, executive=Executive()):
+ def __init__(self, port, image_path, options, executive=Executive()):
self._port = port
- # FIXME: driver_options is never used.
self._image_path = image_path
+ self._options = options
+ self._executive = executive
self._driver_tempdir = tempfile.mkdtemp(prefix='DumpRenderTree-')
def __del__(self):
shutil.rmtree(self._driver_tempdir)
+ def _driver_args(self):
+ driver_args = []
+ if self._image_path:
+ driver_args.append('--pixel-tests')
+
+ # These are used by the Chromium DRT port
+ if self._options.use_drt:
+ driver_args.append('--test-shell')
+ return driver_args
+
def start(self):
- command = []
- # FIXME: We should not be grabbing at self._port._options.wrapper directly.
- command += self._command_wrapper(self._port._options.wrapper)
+ command = self._command_wrapper(self._options.wrapper)
command += [self._port._path_to_driver(), '-']
- if self._image_path:
- command.append('--pixel-tests')
+ command += self._driver_args()
+
environment = self._port.setup_environ_for_server()
environment['DYLD_FRAMEWORK_PATH'] = self._port._build_path()
environment['DUMPRENDERTREE_TEMP'] = self._driver_tempdir
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
index 2e2da6d..14d4f0e 100755
--- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
@@ -564,27 +564,18 @@ class TestRunner:
filename_queue.put(item)
return filename_queue
- def _get_dump_render_tree_args(self, index):
+ def _get_test_args(self, index):
"""Returns the tuple of arguments for tests and for DumpRenderTree."""
- shell_args = []
test_args = test_type_base.TestArguments()
- png_path = None
+ test_args.png_path = None
if self._options.pixel_tests:
png_path = os.path.join(self._options.results_directory,
"png_result%s.png" % index)
- shell_args.append("--pixel-tests=" + png_path)
test_args.png_path = png_path
-
test_args.new_baseline = self._options.new_baseline
test_args.reset_results = self._options.reset_results
- if self._options.startup_dialog:
- shell_args.append('--testshell-startup-dialog')
-
- if self._options.gp_fault_error_box:
- shell_args.append('--gp-fault-error-box')
-
- return test_args, png_path, shell_args
+ return test_args
def _contains_tests(self, subdir):
for test_file in self._test_files:
@@ -610,11 +601,10 @@ class TestRunner:
test_types.append(test_type(self._port,
self._options.results_directory))
- test_args, png_path, shell_args = \
- self._get_dump_render_tree_args(i)
+ test_args = self._get_test_args(i)
thread = dump_render_tree_thread.TestShellThread(self._port,
- filename_queue, self._result_queue, test_types, test_args,
- png_path, shell_args, self._options)
+ self._options, filename_queue, self._result_queue,
+ test_types, test_args)
if self._is_single_threaded():
thread.run_in_main_thread(self, result_summary)
else:
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/update_webgl_conformance_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/update_webgl_conformance_tests.py
new file mode 100755
index 0000000..f4c8098
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/update_webgl_conformance_tests.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2010 Google Inc. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+
+from __future__ import with_statement
+
+import glob
+import logging
+import optparse
+import os
+import re
+import sys
+import webkitpy.common.checkout.scm as scm
+
+_log = logging.getLogger("webkitpy.layout_tests."
+ "update-webgl-conformance-tests")
+
+
+def remove_first_line_comment(text):
+ return re.compile(r'^<!--.*?-->\s*', re.DOTALL).sub('', text)
+
+
+def translate_includes(text):
+ # Mapping of single filename to relative path under WebKit root.
+ # Assumption: these filenames are globally unique.
+ include_mapping = {
+ "js-test-style.css": "../../js/resources",
+ "js-test-pre.js": "../../js/resources",
+ "js-test-post.js": "../../js/resources",
+ "desktop-gl-constants.js": "resources",
+ }
+
+ for filename, path in include_mapping.items():
+ search = r'(?:[^"\'= ]*/)?' + re.escape(filename)
+ replace = os.path.join(path, filename)
+ text = re.sub(search, replace, text)
+
+ return text
+
+
+def translate_khronos_test(text):
+ """
+ This method translates the contents of a Khronos test to a WebKit test.
+ """
+
+ translateFuncs = [
+ remove_first_line_comment,
+ translate_includes,
+ ]
+
+ for f in translateFuncs:
+ text = f(text)
+
+ return text
+
+
+def update_file(in_filename, out_dir):
+ # check in_filename exists
+ # check out_dir exists
+ out_filename = os.path.join(out_dir, os.path.basename(in_filename))
+
+ _log.debug("Processing " + in_filename)
+ with open(in_filename, 'r') as in_file:
+ with open(out_filename, 'w') as out_file:
+ out_file.write(translate_khronos_test(in_file.read()))
+
+
+def update_directory(in_dir, out_dir):
+ for filename in glob.glob(os.path.join(in_dir, '*.html')):
+ update_file(os.path.join(in_dir, filename), out_dir)
+
+
+def default_out_dir():
+ current_scm = scm.detect_scm_system(os.path.dirname(sys.argv[0]))
+ if not current_scm:
+ return os.getcwd()
+ root_dir = current_scm.checkout_root
+ if not root_dir:
+ return os.getcwd()
+ out_dir = os.path.join(root_dir, "LayoutTests/fast/canvas/webgl")
+ if os.path.isdir(out_dir):
+ return out_dir
+ return os.getcwd()
+
+
+def configure_logging(options):
+ """Configures the logging system."""
+ log_fmt = '%(levelname)s: %(message)s'
+ log_datefmt = '%y%m%d %H:%M:%S'
+ log_level = logging.INFO
+ if options.verbose:
+ log_fmt = ('%(asctime)s %(filename)s:%(lineno)-4d %(levelname)s '
+ '%(message)s')
+ log_level = logging.DEBUG
+ logging.basicConfig(level=log_level, format=log_fmt,
+ datefmt=log_datefmt)
+
+
+def option_parser():
+ usage = "usage: %prog [options] (input file or directory)"
+ parser = optparse.OptionParser(usage=usage)
+ parser.add_option('-v', '--verbose',
+ action='store_true',
+ default=False,
+ help='include debug-level logging')
+ parser.add_option('-o', '--output',
+ action='store',
+ type='string',
+ default=default_out_dir(),
+ metavar='DIR',
+ help='specify an output directory to place files '
+ 'in [default: %default]')
+ return parser
+
+
+def main():
+ parser = option_parser()
+ (options, args) = parser.parse_args()
+ configure_logging(options)
+
+ if len(args) == 0:
+ _log.error("Must specify an input directory or filename.")
+ parser.print_help()
+ return 1
+
+ in_name = args[0]
+ if os.path.isfile(in_name):
+ update_file(in_name, options.output)
+ elif os.path.isdir(in_name):
+ update_directory(in_name, options.output)
+ else:
+ _log.error("'%s' is not a directory or a file.", in_name)
+ return 2
+
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/update_webgl_conformance_tests_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/update_webgl_conformance_tests_unittest.py
new file mode 100644
index 0000000..7393b70
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/update_webgl_conformance_tests_unittest.py
@@ -0,0 +1,102 @@
+#!/usr/bin/python
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "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 THE COPYRIGHT
+# OWNER 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.
+
+"""Unit tests for update_webgl_conformance_tests."""
+
+import unittest
+from webkitpy.layout_tests import update_webgl_conformance_tests as webgl
+
+
+def construct_script(name):
+ return "<script src=\"" + name + "\"></script>\n"
+
+
+def construct_style(name):
+ return "<link rel=\"stylesheet\" href=\"" + name + "\">"
+
+
+class TestTranslation(unittest.TestCase):
+ def assert_unchanged(self, text):
+ self.assertEqual(text, webgl.translate_khronos_test(text))
+
+ def assert_translate(self, input, output):
+ self.assertEqual(output, webgl.translate_khronos_test(input))
+
+ def test_simple_unchanged(self):
+ self.assert_unchanged("")
+ self.assert_unchanged("<html></html>")
+
+ def test_header_strip(self):
+ single_line_header = "<!-- single line header. -->"
+ multi_line_header = """<!-- this is a multi-line
+ header. it should all be removed too.
+ -->"""
+ text = "<html></html>"
+ self.assert_translate(single_line_header, "")
+ self.assert_translate(single_line_header + text, text)
+ self.assert_translate(multi_line_header + text, text)
+
+ def dont_strip_other_headers(self):
+ self.assert_unchanged("<html>\n<!-- don't remove comments on other lines. -->\n</html>")
+
+ def test_include_rewriting(self):
+ # Mappings to None are unchanged
+ styles = {
+ "../resources/js-test-style.css": "../../js/resources/js-test-style.css",
+ "fail.css": None,
+ "resources/stylesheet.css": None,
+ "../resources/style.css": None,
+ }
+ scripts = {
+ "../resources/js-test-pre.js": "../../js/resources/js-test-pre.js",
+ "../resources/js-test-post.js": "../../js/resources/js-test-post.js",
+ "../resources/desktop-gl-constants.js": "resources/desktop-gl-constants.js",
+
+ "resources/shadow-offset.js": None,
+ "../resources/js-test-post-async.js": None,
+ }
+
+ input_text = ""
+ output_text = ""
+ for input, output in styles.items():
+ input_text += construct_style(input)
+ output_text += construct_style(output if output else input)
+ for input, output in scripts.items():
+ input_text += construct_script(input)
+ output_text += construct_script(output if output else input)
+
+ head = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">\n<html>\n<head>\n'
+ foot = '</head>\n<body>\n</body>\n</html>'
+ input_text = head + input_text + foot
+ output_text = head + output_text + foot
+ self.assert_translate(input_text, output_text)
+
+
+if __name__ == '__main__':
+ unittest.main()