summaryrefslogtreecommitdiffstats
path: root/Tools/Scripts/webkitpy/layout_tests/port/test.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/Scripts/webkitpy/layout_tests/port/test.py')
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/test.py303
1 files changed, 137 insertions, 166 deletions
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/test.py b/Tools/Scripts/webkitpy/layout_tests/port/test.py
index 935881c..5df5c2d 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/test.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/test.py
@@ -30,12 +30,10 @@
"""Dummy Port implementation used for testing."""
from __future__ import with_statement
-import codecs
-import fnmatch
-import os
-import sys
import time
+from webkitpy.common.system import filesystem_mock
+
from webkitpy.layout_tests.layout_package import test_output
import base
@@ -64,8 +62,7 @@ class TestInstance:
# This is an in-memory list of tests, what we want them to produce, and
# what we want to claim are the expected results.
class TestList:
- def __init__(self, port):
- self.port = port
+ def __init__(self):
self.tests = {}
def add(self, name, **kwargs):
@@ -84,66 +81,141 @@ class TestList:
return self.tests[item]
+def unit_test_list():
+ tests = TestList()
+ tests.add('failures/expected/checksum.html',
+ actual_checksum='checksum_fail-checksum')
+ tests.add('failures/expected/crash.html', crash=True)
+ tests.add('failures/expected/exception.html', exception=True)
+ tests.add('failures/expected/timeout.html', timeout=True)
+ tests.add('failures/expected/hang.html', hang=True)
+ tests.add('failures/expected/missing_text.html',
+ expected_text=None)
+ tests.add('failures/expected/image.html',
+ actual_image='image_fail-png',
+ expected_image='image-png')
+ tests.add('failures/expected/image_checksum.html',
+ actual_checksum='image_checksum_fail-checksum',
+ actual_image='image_checksum_fail-png')
+ tests.add('failures/expected/keyboard.html',
+ keyboard=True)
+ tests.add('failures/expected/missing_check.html',
+ expected_checksum=None)
+ tests.add('failures/expected/missing_image.html',
+ expected_image=None)
+ tests.add('failures/expected/missing_text.html',
+ expected_text=None)
+ tests.add('failures/expected/newlines_leading.html',
+ expected_text="\nfoo\n",
+ actual_text="foo\n")
+ tests.add('failures/expected/newlines_trailing.html',
+ expected_text="foo\n\n",
+ actual_text="foo\n")
+ tests.add('failures/expected/newlines_with_excess_CR.html',
+ expected_text="foo\r\r\r\n",
+ actual_text="foo\n")
+ tests.add('failures/expected/text.html',
+ actual_text='text_fail-png')
+ tests.add('failures/unexpected/crash.html', crash=True)
+ tests.add('failures/unexpected/text-image-checksum.html',
+ actual_text='text-image-checksum_fail-txt',
+ actual_checksum='text-image-checksum_fail-checksum')
+ tests.add('failures/unexpected/timeout.html', timeout=True)
+ tests.add('http/tests/passes/text.html')
+ tests.add('http/tests/ssl/text.html')
+ tests.add('passes/error.html', error='stuff going to stderr')
+ tests.add('passes/image.html')
+ tests.add('passes/platform_image.html')
+ # Text output files contain "\r\n" on Windows. This may be
+ # helpfully filtered to "\r\r\n" by our Python/Cygwin tooling.
+ tests.add('passes/text.html',
+ expected_text='\nfoo\n\n',
+ actual_text='\nfoo\r\n\r\r\n')
+ tests.add('websocket/tests/passes/text.html')
+ return tests
+
+
+# Here we use a non-standard location for the layout tests, to ensure that
+# this works. The path contains a '.' in the name because we've seen bugs
+# related to this before.
+
+LAYOUT_TEST_DIR = '/test.checkout/LayoutTests'
+
+
+# Here we synthesize an in-memory filesystem from the test list
+# in order to fully control the test output and to demonstrate that
+# we don't need a real filesystem to run the tests.
+
+def unit_test_filesystem(files=None):
+ """Return the FileSystem object used by the unit tests."""
+ test_list = unit_test_list()
+ files = files or {}
+
+ def add_file(files, test, suffix, contents):
+ dirname = test.name[0:test.name.rfind('/')]
+ base = test.base
+ path = LAYOUT_TEST_DIR + '/' + dirname + '/' + base + suffix
+ files[path] = contents
+
+ # Add each test and the expected output, if any.
+ for test in test_list.tests.values():
+ add_file(files, test, '.html', '')
+ add_file(files, test, '-expected.txt', test.expected_text)
+ add_file(files, test, '-expected.checksum', test.expected_checksum)
+ add_file(files, test, '-expected.png', test.expected_image)
+
+ # Add the test_expectations file.
+ files[LAYOUT_TEST_DIR + '/platform/test/test_expectations.txt'] = """
+WONTFIX : failures/expected/checksum.html = IMAGE
+WONTFIX : failures/expected/crash.html = CRASH
+// This one actually passes because the checksums will match.
+WONTFIX : failures/expected/image.html = PASS
+WONTFIX : failures/expected/image_checksum.html = IMAGE
+WONTFIX : failures/expected/missing_check.html = MISSING PASS
+WONTFIX : failures/expected/missing_image.html = MISSING PASS
+WONTFIX : failures/expected/missing_text.html = MISSING PASS
+WONTFIX : failures/expected/newlines_leading.html = TEXT
+WONTFIX : failures/expected/newlines_trailing.html = TEXT
+WONTFIX : failures/expected/newlines_with_excess_CR.html = TEXT
+WONTFIX : failures/expected/text.html = TEXT
+WONTFIX : failures/expected/timeout.html = TIMEOUT
+WONTFIX SKIP : failures/expected/hang.html = TIMEOUT
+WONTFIX SKIP : failures/expected/keyboard.html = CRASH
+WONTFIX SKIP : failures/expected/exception.html = CRASH
+"""
+
+ fs = filesystem_mock.MockFileSystem(files)
+ fs._tests = test_list
+ return fs
+
+
class TestPort(base.Port):
"""Test implementation of the Port interface."""
def __init__(self, **kwargs):
+ # FIXME: what happens if we're not passed in the test filesystem
+ # and the tests don't match what's in the filesystem?
+ #
+ # We'll leave as is for now to avoid unnecessary dependencies while
+ # converting all of the unit tests over to using
+ # unit_test_filesystem(). If things get out of sync the tests should
+ # fail in fairly obvious ways. Eventually we want to just do:
+ #
+ # assert kwargs['filesystem']._tests
+ # self._tests = kwargs['filesystem']._tests
+
+ if 'filesystem' not in kwargs or kwargs['filesystem'] is None:
+ kwargs['filesystem'] = unit_test_filesystem()
+ self._tests = kwargs['filesystem']._tests
+ else:
+ self._tests = unit_test_list()
+
+ kwargs.setdefault('port_name', 'test')
base.Port.__init__(self, **kwargs)
- tests = TestList(self)
- tests.add('failures/expected/checksum.html',
- actual_checksum='checksum_fail-checksum')
- tests.add('failures/expected/crash.html', crash=True)
- tests.add('failures/expected/exception.html', exception=True)
- tests.add('failures/expected/timeout.html', timeout=True)
- tests.add('failures/expected/hang.html', hang=True)
- tests.add('failures/expected/missing_text.html',
- expected_text=None)
- tests.add('failures/expected/image.html',
- actual_image='image_fail-png',
- expected_image='image-png')
- tests.add('failures/expected/image_checksum.html',
- actual_checksum='image_checksum_fail-checksum',
- actual_image='image_checksum_fail-png')
- tests.add('failures/expected/keyboard.html',
- keyboard=True)
- tests.add('failures/expected/missing_check.html',
- expected_checksum=None)
- tests.add('failures/expected/missing_image.html',
- expected_image=None)
- tests.add('failures/expected/missing_text.html',
- expected_text=None)
- tests.add('failures/expected/newlines_leading.html',
- expected_text="\nfoo\n",
- actual_text="foo\n")
- tests.add('failures/expected/newlines_trailing.html',
- expected_text="foo\n\n",
- actual_text="foo\n")
- tests.add('failures/expected/newlines_with_excess_CR.html',
- expected_text="foo\r\r\r\n",
- actual_text="foo\n")
- tests.add('failures/expected/text.html',
- actual_text='text_fail-png')
- tests.add('failures/unexpected/crash.html', crash=True)
- tests.add('failures/unexpected/text-image-checksum.html',
- actual_text='text-image-checksum_fail-txt',
- actual_checksum='text-image-checksum_fail-checksum')
- tests.add('failures/unexpected/timeout.html', timeout=True)
- tests.add('http/tests/passes/text.html')
- tests.add('http/tests/ssl/text.html')
- tests.add('passes/error.html', error='stuff going to stderr')
- tests.add('passes/image.html')
- tests.add('passes/platform_image.html')
- # Text output files contain "\r\n" on Windows. This may be
- # helpfully filtered to "\r\r\n" by our Python/Cygwin tooling.
- tests.add('passes/text.html',
- expected_text='\nfoo\n\n',
- actual_text='\nfoo\r\n\r\r\n')
- tests.add('websocket/tests/passes/text.html')
- self._tests = tests
def baseline_path(self):
- return os.path.join(self.layout_tests_dir(), 'platform',
- self.name() + self.version())
+ return self._filesystem.join(self.layout_tests_dir(), 'platform',
+ self.name() + self.version())
def baseline_search_path(self):
return [self.baseline_path()]
@@ -155,92 +227,12 @@ class TestPort(base.Port):
diff_filename=None):
diffed = actual_contents != expected_contents
if diffed and diff_filename:
- with codecs.open(diff_filename, "w", "utf-8") as diff_fh:
- diff_fh.write("< %s\n---\n> %s\n" %
- (expected_contents, actual_contents))
+ self._filesystem.write_text_file(diff_filename,
+ "< %s\n---\n> %s\n" % (expected_contents, actual_contents))
return diffed
- def expected_checksum(self, test):
- test = self.relative_test_filename(test)
- return self._tests[test].expected_checksum
-
- def expected_image(self, test):
- test = self.relative_test_filename(test)
- return self._tests[test].expected_image
-
- def expected_text(self, test):
- test = self.relative_test_filename(test)
- text = self._tests[test].expected_text
- if not text:
- text = ''
- return text
-
- def tests(self, paths):
- # Test the idea of port-specific overrides for test lists. Also
- # keep in memory to speed up the test harness.
- if not paths:
- paths = ['*']
-
- matched_tests = []
- for p in paths:
- if self.path_isdir(p):
- matched_tests.extend(fnmatch.filter(self._tests.keys(), p + '*'))
- else:
- matched_tests.extend(fnmatch.filter(self._tests.keys(), p))
- layout_tests_dir = self.layout_tests_dir()
- return set([os.path.join(layout_tests_dir, p) for p in matched_tests])
-
- def path_exists(self, path):
- # used by test_expectations.py and printing.py
- rpath = self.relative_test_filename(path)
- if rpath in self._tests:
- return True
- if self.path_isdir(rpath):
- return True
- if rpath.endswith('-expected.txt'):
- test = rpath.replace('-expected.txt', '.html')
- return (test in self._tests and
- self._tests[test].expected_text)
- if rpath.endswith('-expected.checksum'):
- test = rpath.replace('-expected.checksum', '.html')
- return (test in self._tests and
- self._tests[test].expected_checksum)
- if rpath.endswith('-expected.png'):
- test = rpath.replace('-expected.png', '.html')
- return (test in self._tests and
- self._tests[test].expected_image)
- return False
-
def layout_tests_dir(self):
- return self.path_from_webkit_base('Tools', 'Scripts',
- 'webkitpy', 'layout_tests', 'data')
-
- def path_isdir(self, path):
- # Used by test_expectations.py
- #
- # We assume that a path is a directory if we have any tests
- # that whose prefix matches the path plus a directory modifier
- # and not a file extension.
- if path[-1] != '/':
- path += '/'
-
- # FIXME: Directories can have a dot in the name. We should
- # probably maintain a white list of known cases like CSS2.1
- # and check it here in the future.
- if path.find('.') != -1:
- # extension separator found, assume this is a file
- return False
-
- # strip out layout tests directory path if found. The tests
- # keys are relative to it.
- tests_dir = self.layout_tests_dir()
- if path.startswith(tests_dir):
- path = path[len(tests_dir) + 1:]
-
- return any([t.startswith(path) for t in self._tests.keys()])
-
- def test_dirs(self):
- return ['passes', 'failures']
+ return LAYOUT_TEST_DIR
def name(self):
return self._name
@@ -269,33 +261,12 @@ class TestPort(base.Port):
def stop_websocket_server(self):
pass
- def test_expectations(self):
- """Returns the test expectations for this port.
-
- Basically this string should contain the equivalent of a
- test_expectations file. See test_expectations.py for more details."""
- return """
-WONTFIX : failures/expected/checksum.html = IMAGE
-WONTFIX : failures/expected/crash.html = CRASH
-// This one actually passes because the checksums will match.
-WONTFIX : failures/expected/image.html = PASS
-WONTFIX : failures/expected/image_checksum.html = IMAGE
-WONTFIX : failures/expected/missing_check.html = MISSING PASS
-WONTFIX : failures/expected/missing_image.html = MISSING PASS
-WONTFIX : failures/expected/missing_text.html = MISSING PASS
-WONTFIX : failures/expected/newlines_leading.html = TEXT
-WONTFIX : failures/expected/newlines_trailing.html = TEXT
-WONTFIX : failures/expected/newlines_with_excess_CR.html = TEXT
-WONTFIX : failures/expected/text.html = TEXT
-WONTFIX : failures/expected/timeout.html = TIMEOUT
-WONTFIX SKIP : failures/expected/hang.html = TIMEOUT
-WONTFIX SKIP : failures/expected/keyboard.html = CRASH
-WONTFIX SKIP : failures/expected/exception.html = CRASH
-"""
-
def test_base_platform_names(self):
return ('mac', 'win')
+ def test_expectations(self):
+ return self._filesystem.read_text_file(LAYOUT_TEST_DIR + '/platform/test/test_expectations.txt')
+
def test_platform_name(self):
return 'mac'