summaryrefslogtreecommitdiff
path: root/Tools/Scripts/webkitpy/layout_tests
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/Scripts/webkitpy/layout_tests')
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_finder.py8
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/controllers/manager.py3
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py11
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py6
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py23
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/base.py29
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py6
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/builders.py22
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/chromium.py22
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py123
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py4
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_linux.py17
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py8
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py3
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/chromium_port_testcase.py9
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/driver.py17
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/efl.py9
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py2
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/gtk.py15
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/port/port_testcase.py27
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/qt.py18
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/qt_unittest.py22
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/server_process.py24
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py14
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/test.py5
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver.py42
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver_unittest.py52
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py11
-rwxr-xr-xTools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py19
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/servers/apache_http_server.py2
30 files changed, 381 insertions, 192 deletions
diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_finder.py b/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_finder.py
index a7b49831c..6447c8fb4 100644
--- a/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_finder.py
+++ b/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_finder.py
@@ -106,11 +106,9 @@ class LayoutTestFinder(object):
tests_to_skip = all_tests - tests_to_skip
elif self._options.skipped == 'ignore':
tests_to_skip = set()
- elif self._options.skipped == 'default':
- pass # listed for completeness
-
- # make sure we're explicitly running any tests passed on the command line.
- tests_to_skip -= paths
+ elif self._options.skipped != 'always':
+ # make sure we're explicitly running any tests passed on the command line; equivalent to 'default'.
+ tests_to_skip -= paths
# unless of course we don't want to run the HTTP tests :)
if not self._options.http:
diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py b/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
index d06ed7153..c0a70e615 100644
--- a/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
+++ b/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
@@ -239,8 +239,9 @@ def summarize_results(port_obj, expectations, result_summary, retry_summary, tes
try:
# We only use the svn revision for using trac links in the results.html file,
# Don't do this by default since it takes >100ms.
+ # FIXME: Do we really need to populate this both here and in the json_results_generator?
if use_trac_links_in_results_html(port_obj):
- port_obj.host._initialize_scm()
+ port_obj.host.initialize_scm()
results['revision'] = port_obj.host.scm().head_svn_revision()
except Exception, e:
_log.warn("Failed to determine svn revision for checkout (cwd: %s, webkit_base: %s), leaving 'revision' key blank in full_results.json.\n%s" % (port_obj._filesystem.getcwd(), port_obj.path_from_webkit_base(), e))
diff --git a/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py b/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py
index c7d7c3eb7..73834f0ad 100644
--- a/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py
+++ b/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py
@@ -281,7 +281,8 @@ class JSONResultsGeneratorBase(object):
results_for_builder = results_json[builder_name]
- self._insert_generic_metadata(results_for_builder)
+ if builder_name:
+ self._insert_generic_metadata(results_for_builder)
self._insert_failure_summaries(results_for_builder)
@@ -377,15 +378,17 @@ class JSONResultsGeneratorBase(object):
return self.__class__.PASS_RESULT
- # FIXME: Callers should use scm.py instead.
- # FIXME: Identify and fix the run-time errors that were observed on Windows
- # chromium buildbot when we had updated this code to use scm.py once before.
def _get_svn_revision(self, in_directory):
"""Returns the svn revision for the given directory.
Args:
in_directory: The directory where svn is to be run.
"""
+
+ # FIXME: We initialize this here in order to engage the stupid windows hacks :).
+ # We can't reuse an existing scm object because the specific directories may
+ # be part of other checkouts.
+ self._port.host.initialize_scm()
scm = SCMDetector(self._filesystem, self._executive).detect_scm_system(in_directory)
if scm:
return scm.svn_revision(in_directory)
diff --git a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
index 42b518f7f..b48c5b933 100644
--- a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
+++ b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
@@ -155,7 +155,7 @@ class TestExpectationParser(object):
else:
parsed_specifiers.add(modifier)
- if not expectation_line.parsed_bug_modifiers and not has_wontfix and not has_bugid:
+ if not expectation_line.parsed_bug_modifiers and not has_wontfix and not has_bugid and self._port.warn_if_bug_missing_in_test_expectations():
expectation_line.warnings.append(self.MISSING_BUG_WARNING)
if self._allow_rebaseline_modifier and self.REBASELINE_MODIFIER in modifiers:
@@ -869,7 +869,7 @@ class TestExpectations(object):
return self._model
def get_rebaselining_failures(self):
- return self._model.get_test_set(REBASELINE, IMAGE) | self._model.get_test_set(REBASELINE, FAIL)
+ return self._model.get_test_set(REBASELINE)
# FIXME: Change the callsites to use TestExpectationsModel and remove.
def get_expectations(self, test):
@@ -970,7 +970,7 @@ class TestExpectations(object):
expectation.name in except_these_tests and
'rebaseline' in expectation.parsed_modifiers))
- return self.list_to_string(filter(without_rebaseline_modifier, self._expectations))
+ return self.list_to_string(filter(without_rebaseline_modifier, self._expectations), reconstitute_only_these=[])
def _add_expectations(self, expectation_list):
for expectation_line in expectation_list:
diff --git a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
index c5606071d..c3fc02658 100644
--- a/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
@@ -179,8 +179,7 @@ class MiscTests(Base):
"Bug(rniwa) disabled-test.html-disabled [ ImageOnlyFailure ]", is_lint_mode=True)
self.assertFalse(True, "ParseError wasn't raised")
except ParseError, e:
- warnings = ("expectations:1 Test lacks BUG modifier. failures/expected/text.html\n"
- "expectations:1 Unrecognized modifier 'foo' failures/expected/text.html\n"
+ warnings = ("expectations:1 Unrecognized modifier 'foo' failures/expected/text.html\n"
"expectations:2 Path does not exist. non-existent-test.html")
self.assertEqual(str(e), warnings)
@@ -372,7 +371,9 @@ class SemanticTests(Base):
def test_missing_bugid(self):
self.parse_exp('failures/expected/text.html [ Failure ]')
- self.assertTrue(self._exp.has_warnings())
+ self.assertFalse(self._exp.has_warnings())
+
+ self._port.warn_if_bug_missing_in_test_expectations = lambda: True
self.parse_exp('failures/expected/text.html [ Failure ]')
line = self._exp._model.get_expectation_line('failures/expected/text.html')
@@ -512,8 +513,22 @@ class RebaseliningTest(Base):
'Bug(z) failures/expected/crash.html [ Crash ]\n',
'Bug(x0) failures/expected/image.html [ Crash ]\n')
+ # Ensure that we don't modify unrelated lines, even if we could rewrite them.
+ # i.e., the second line doesn't get rewritten to "Bug(y) failures/expected/skip.html"
+ self.assertRemove('Bug(x) failures/expected/text.html [ Failure Rebaseline ]\n'
+ 'Bug(Y) failures/expected/image.html [ Skip ]\n'
+ 'Bug(z) failures/expected/crash.html\n',
+ '',
+ ['failures/expected/text.html'],
+ 'Bug(Y) failures/expected/image.html [ Skip ]\n'
+ 'Bug(z) failures/expected/crash.html\n',
+ '')
+
+ def test_get_rebaselining_failures(self):
+ # Make sure we find a test as needing a rebaseline even if it is not marked as a failure.
+ self.parse_exp('Bug(x) failures/expected/text.html [ Rebaseline ]\n')
+ self.assertEqual(len(self._exp.get_rebaselining_failures()), 1)
- def test_no_get_rebaselining_failures(self):
self.parse_exp(self.get_basic_expectations())
self.assertEqual(len(self._exp.get_rebaselining_failures()), 0)
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/base.py b/Tools/Scripts/webkitpy/layout_tests/port/base.py
index cd57032e9..ae55c684d 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -182,6 +182,10 @@ class Port(object):
"""Return the number of DumpRenderTree instances to use for this port."""
return self._executive.cpu_count()
+ def default_max_locked_shards(self):
+ """Return the number of "locked" shards to run in parallel (like the http tests)."""
+ return 1
+
def worker_startup_delay_secs(self):
# FIXME: If we start workers up too quickly, DumpRenderTree appears
# to thrash on something and time out its first few tests. Until
@@ -870,6 +874,7 @@ class Port(object):
# Most ports (?):
'WEBKIT_TESTFONTS',
+ 'WEBKITOUTPUTDIR',
]
for variable in variables_to_copy:
self._copy_value_from_environ_if_set(clean_env, variable)
@@ -997,6 +1002,9 @@ class Port(object):
# some ports have Skipped files which are returned as part of test_expectations().
return self._filesystem.exists(self.path_to_test_expectations_file())
+ def warn_if_bug_missing_in_test_expectations(self):
+ return False
+
def expectations_dict(self):
"""Returns an OrderedDict of name -> expectations strings.
The names are expected to be (but not required to be) paths in the filesystem.
@@ -1162,9 +1170,18 @@ class Port(object):
return "apache2-httpd.conf"
def _path_to_apache_config_file(self):
- """Returns the full path to the apache binary.
+ """Returns the full path to the apache configuration file.
+
+ If the WEBKIT_HTTP_SERVER_CONF_PATH environment variable is set, its
+ contents will be used instead.
This is needed only by ports that use the apache_http_server module."""
+ config_file_from_env = os.environ.get('WEBKIT_HTTP_SERVER_CONF_PATH')
+ if config_file_from_env:
+ if not self._filesystem.exists(config_file_from_env):
+ raise IOError('%s was not found on the system' % config_file_from_env)
+ return config_file_from_env
+
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)
@@ -1223,11 +1240,15 @@ class Port(object):
This is needed only by ports that use the http_server.py module."""
raise NotImplementedError('Port._path_to_lighttpd_php')
+ @memoized
def _path_to_wdiff(self):
"""Returns the full path to the wdiff binary, or None if it is not available.
This is likely used only by wdiff_text()"""
- return 'wdiff'
+ for path in ("/usr/bin/wdiff", "/usr/bin/dwdiff"):
+ if self._filesystem.exists(path):
+ return path
+ return None
def _webkit_baseline_path(self, platform):
"""Return the full path to the top of the baseline tree for a
@@ -1275,7 +1296,7 @@ class Port(object):
base_tests = self._real_tests([suite.base])
suite.tests = {}
for test in base_tests:
- suite.tests[test.replace(suite.base, suite.name)] = test
+ suite.tests[test.replace(suite.base, suite.name, 1)] = test
return suites
def _virtual_tests(self, paths, suites):
@@ -1292,7 +1313,7 @@ class Port(object):
def lookup_virtual_test_base(self, test_name):
for suite in self.populated_virtual_test_suites():
if test_name.startswith(suite.name):
- return test_name.replace(suite.name, suite.base)
+ return test_name.replace(suite.name, suite.base, 1)
return None
def lookup_virtual_test_args(self, test_name):
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
index f6a6eb01f..e9b2f060d 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
@@ -437,11 +437,15 @@ class PortTest(unittest.TestCase):
tests = port.tests(['passes'])
self.assertTrue('passes/text.html' in tests)
+ self.assertTrue('passes/passes/test-virtual-passes.html' in tests)
self.assertFalse('virtual/passes/text.html' in tests)
tests = port.tests(['virtual/passes'])
self.assertFalse('passes/text.html' in tests)
- self.assertTrue('virtual/passes/text.html' in tests)
+ self.assertTrue('virtual/passes/test-virtual-passes.html' in tests)
+ self.assertTrue('virtual/passes/passes/test-virtual-passes.html' in tests)
+ self.assertFalse('virtual/passes/test-virtual-virtual/passes.html' in tests)
+ self.assertFalse('virtual/passes/virtual/passes/test-virtual-passes.html' in tests)
def test_build_path(self):
port = self.make_port(options=optparse.Values({'build_directory': '/my-build-directory/'}))
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/builders.py b/Tools/Scripts/webkitpy/layout_tests/port/builders.py
index 3d03fc7af..605b8cccc 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/builders.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/builders.py
@@ -37,16 +37,16 @@ from webkitpy.common.memoized import memoized
# * specifiers -- a set of specifiers, representing configurations covered by this builder.
_exact_matches = {
# These builders are on build.chromium.org.
- "Webkit Win": {"port_name": "chromium-win-xp", "specifiers": set(["xp", "release"])},
- "Webkit Win7": {"port_name": "chromium-win-win7", "specifiers": set(["win7"])},
- "Webkit Win (dbg)(1)": {"port_name": "chromium-win-xp", "specifiers": set(["win", "debug"])},
- "Webkit Win (dbg)(2)": {"port_name": "chromium-win-xp", "specifiers": set(["win", "debug"])},
- "Webkit Linux": {"port_name": "chromium-linux-x86_64", "specifiers": set(["linux", "x86_64", "release"])},
- "Webkit Linux 32": {"port_name": "chromium-linux-x86", "specifiers": set(["linux", "x86"])},
- "Webkit Linux (dbg)": {"port_name": "chromium-linux-x86_64", "specifiers": set(["linux", "debug"])},
- "Webkit Mac10.6": {"port_name": "chromium-mac-snowleopard", "specifiers": set(["snowleopard"])},
- "Webkit Mac10.6 (dbg)": {"port_name": "chromium-mac-snowleopard", "specifiers": set(["snowleopard", "debug"])},
- "Webkit Mac10.7": {"port_name": "chromium-mac-lion", "specifiers": set(["lion"])},
+ "WebKit XP": {"port_name": "chromium-win-xp", "specifiers": set(["xp", "release"])},
+ "WebKit Win7": {"port_name": "chromium-win-win7", "specifiers": set(["win7"])},
+ "WebKit Win7 (dbg)(1)": {"port_name": "chromium-win-xp", "specifiers": set(["win", "debug"])},
+ "WebKit Win7 (dbg)(2)": {"port_name": "chromium-win-xp", "specifiers": set(["win", "debug"])},
+ "WebKit Linux": {"port_name": "chromium-linux-x86_64", "specifiers": set(["linux", "x86_64", "release"])},
+ "WebKit Linux 32": {"port_name": "chromium-linux-x86", "specifiers": set(["linux", "x86"])},
+ "WebKit Linux (dbg)": {"port_name": "chromium-linux-x86_64", "specifiers": set(["linux", "debug"])},
+ "WebKit Mac10.6": {"port_name": "chromium-mac-snowleopard", "specifiers": set(["snowleopard"])},
+ "WebKit Mac10.6 (dbg)": {"port_name": "chromium-mac-snowleopard", "specifiers": set(["snowleopard", "debug"])},
+ "WebKit Mac10.7": {"port_name": "chromium-mac-lion", "specifiers": set(["lion"])},
# These builders are on build.webkit.org.
"Apple MountainLion Release WK1 (Tests)": {"port_name": "mac-mountainlion", "specifiers": set(["mountainlion"]), "rebaseline_override_dir": "mac"},
@@ -92,6 +92,8 @@ _ports_without_builders = [
"qt-mac",
"qt-win",
"qt-wk2",
+ # FIXME: Move to _extact_matches.
+ "chromium-android",
]
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
index 44c98a383..c310eb15b 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
@@ -53,6 +53,7 @@ class ChromiumPort(Port):
ALL_SYSTEMS = (
('snowleopard', 'x86'),
('lion', 'x86'),
+ ('mountainlion', 'x86'),
('xp', 'x86'),
('win7', 'x86'),
('lucid', 'x86'),
@@ -62,13 +63,13 @@ class ChromiumPort(Port):
('icecreamsandwich', 'x86'))
ALL_BASELINE_VARIANTS = [
- 'chromium-mac-lion', 'chromium-mac-snowleopard', 'chromium-mac-leopard',
+ 'chromium-mac-mountainlion', 'chromium-mac-lion', 'chromium-mac-snowleopard',
'chromium-win-win7', 'chromium-win-xp',
'chromium-linux-x86_64', 'chromium-linux-x86',
]
CONFIGURATION_SPECIFIER_MACROS = {
- 'mac': ['snowleopard', 'lion'],
+ 'mac': ['snowleopard', 'lion', 'mountainlion'],
'win': ['xp', 'win7'],
'linux': ['lucid'],
'android': ['icecreamsandwich'],
@@ -111,6 +112,13 @@ class ChromiumPort(Port):
def is_chromium(self):
return True
+ def default_max_locked_shards(self):
+ """Return the number of "locked" shards to run in parallel (like the http tests)."""
+ max_locked_shards = int(self.default_child_processes()) / 4
+ if not max_locked_shards:
+ return 1
+ return max_locked_shards
+
def default_pixel_tests(self):
return True
@@ -332,13 +340,16 @@ class ChromiumPort(Port):
'win_layout_rel',
])
+ def warn_if_bug_missing_in_test_expectations(self):
+ return True
+
def expectations_files(self):
paths = [self.path_to_test_expectations_file()]
skia_expectations_path = self.path_from_chromium_base('skia', 'skia_test_expectations.txt')
+ # FIXME: we should probably warn if this file is missing in some situations.
+ # See the discussion in webkit.org/b/97699.
if self._filesystem.exists(skia_expectations_path):
paths.append(skia_expectations_path)
- else:
- _log.warning("Using the chromium port without having the downstream skia_test_expectations.txt file checked out. Expectations related things might be wonky.")
builder_name = self.get_option('builder_name', 'DUMMY_BUILDER_NAME')
if builder_name == 'DUMMY_BUILDER_NAME' or '(deps)' in builder_name or builder_name in self.try_builder_names:
@@ -376,6 +387,9 @@ class ChromiumPort(Port):
VirtualTestSuite('platform/chromium/virtual/gpu/fast/hidpi',
'fast/hidpi',
['--force-compositing-mode']),
+ VirtualTestSuite('platform/chromium/virtual/softwarecompositing',
+ 'compositing',
+ ['--enable-software-compositing']),
]
#
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py
index 3dfeab7a3..e246b8870 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py
@@ -77,45 +77,51 @@ TEST_PATH_PREFIX = '/all-tests'
FORWARD_PORTS = '8000 8080 8443 8880 9323'
MS_TRUETYPE_FONTS_DIR = '/usr/share/fonts/truetype/msttcorefonts/'
+MS_TRUETYPE_FONTS_PACKAGE = 'ttf-mscorefonts-installer'
# Timeout in seconds to wait for start/stop of DumpRenderTree.
DRT_START_STOP_TIMEOUT_SECS = 10
-# List of fonts that layout tests expect, copied from DumpRenderTree/gtk/TestShellX11.cpp.
+# List of fonts that layout tests expect, copied from DumpRenderTree/chromium/TestShellX11.cpp.
HOST_FONT_FILES = [
- [MS_TRUETYPE_FONTS_DIR, 'Arial.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Arial_Bold.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Arial_Bold_Italic.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Arial_Italic.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Comic_Sans_MS.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Comic_Sans_MS_Bold.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Courier_New.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Courier_New_Bold.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Courier_New_Bold_Italic.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Courier_New_Italic.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Georgia.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Georgia_Bold.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Georgia_Bold_Italic.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Georgia_Italic.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Impact.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Trebuchet_MS.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Trebuchet_MS_Bold.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Trebuchet_MS_Bold_Italic.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Trebuchet_MS_Italic.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Times_New_Roman.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Times_New_Roman_Bold.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Times_New_Roman_Bold_Italic.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Times_New_Roman_Italic.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Verdana.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Verdana_Bold.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Verdana_Bold_Italic.ttf'],
- [MS_TRUETYPE_FONTS_DIR, 'Verdana_Italic.ttf'],
+ [[MS_TRUETYPE_FONTS_DIR], 'Arial.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Arial_Bold.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Arial_Bold_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Arial_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Comic_Sans_MS.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Comic_Sans_MS_Bold.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Courier_New.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Courier_New_Bold.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Courier_New_Bold_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Courier_New_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Georgia.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Georgia_Bold.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Georgia_Bold_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Georgia_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Impact.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Trebuchet_MS.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Trebuchet_MS_Bold.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Trebuchet_MS_Bold_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Trebuchet_MS_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Times_New_Roman.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Times_New_Roman_Bold.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Times_New_Roman_Bold_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Times_New_Roman_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Verdana.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Verdana_Bold.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Verdana_Bold_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
+ [[MS_TRUETYPE_FONTS_DIR], 'Verdana_Italic.ttf', MS_TRUETYPE_FONTS_PACKAGE],
# The Microsoft font EULA
- ['/usr/share/doc/ttf-mscorefonts-installer/', 'READ_ME!.gz'],
- ['/usr/share/fonts/truetype/ttf-dejavu/', 'DejaVuSans.ttf'],
+ [['/usr/share/doc/ttf-mscorefonts-installer/'], 'READ_ME!.gz', MS_TRUETYPE_FONTS_PACKAGE],
+ # Other fonts: Arabic, CJK, Indic, Thai, etc.
+ [['/usr/share/fonts/truetype/ttf-dejavu/'], 'DejaVuSans.ttf', 'ttf-dejavu'],
+ [['/usr/share/fonts/truetype/kochi/'], 'kochi-mincho.ttf', 'ttf-kochi-mincho'],
+ [['/usr/share/fonts/truetype/ttf-indic-fonts-core/'], 'lohit_hi.ttf', 'ttf-indic-fonts-core'],
+ [['/usr/share/fonts/truetype/ttf-indic-fonts-core/'], 'lohit_ta.ttf', 'ttf-indic-fonts-core'],
+ [['/usr/share/fonts/truetype/ttf-indic-fonts-core/'], 'MuktiNarrow.ttf', 'ttf-indic-fonts-core'],
+ [['/usr/share/fonts/truetype/thai/', '/usr/share/fonts/truetype/tlwg/'], 'Garuda.ttf', 'fonts-tlwg-garuda'],
+ [['/usr/share/fonts/truetype/ttf-indic-fonts-core/', '/usr/share/fonts/truetype/ttf-punjabi-fonts/'], 'lohit_pa.ttf', 'ttf-indic-fonts-core'],
]
-# Should increase this version after changing HOST_FONT_FILES.
-FONT_FILES_VERSION = 2
DEVICE_FONTS_DIR = DEVICE_DRT_DIR + 'fonts/'
@@ -198,7 +204,8 @@ class ChromiumAndroidPort(chromium.ChromiumPort):
def check_build(self, needs_http):
result = super(ChromiumAndroidPort, self).check_build(needs_http)
- result = self.check_wdiff() and result
+ result = self._check_file_exists(self._path_to_md5sum(), 'md5sum utility') and result
+ result = self._check_file_exists(self._path_to_forwarder(), 'forwarder utility') and result
if not result:
_log.error('For complete Android build requirements, please see:')
_log.error('')
@@ -207,11 +214,15 @@ class ChromiumAndroidPort(chromium.ChromiumPort):
return result
def check_sys_deps(self, needs_http):
- for (font_dir, font_file) in HOST_FONT_FILES:
- font_path = font_dir + font_file
- if not self._check_file_exists(font_path, 'font file'):
- _log.error('You are missing %s. Try installing msttcorefonts. '
- 'See build instructions.' % font_path)
+ for (font_dirs, font_file, package) in HOST_FONT_FILES:
+ exists = False
+ for font_dir in font_dirs:
+ font_path = font_dir + font_file
+ if self._check_file_exists(font_path, '', logging=False):
+ exists = True
+ break
+ if not exists:
+ _log.error('You are missing %s under %s. Try installing %s. See build instructions.' % (font_file, font_dirs, package))
return False
return True
@@ -271,6 +282,9 @@ class ChromiumAndroidPort(chromium.ChromiumPort):
def _path_to_forwarder(self):
return self._build_path('forwarder')
+ def _path_to_md5sum(self):
+ return self._build_path(MD5SUM_DEVICE_FILE_NAME)
+
def _path_to_image_diff(self):
return self._host_port._path_to_image_diff()
@@ -330,12 +344,10 @@ class ChromiumAndroidDriver(driver.Driver):
super(ChromiumAndroidDriver, self).__del__()
def _setup_md5sum_and_push_data_if_needed(self):
- self._md5sum_path = self._port._build_path_with_configuration(self._port.get_option('configuration'), MD5SUM_DEVICE_FILE_NAME)
- assert os.path.exists(self._md5sum_path)
-
+ self._md5sum_path = self._port._path_to_md5sum()
if not self._file_exists_on_device(MD5SUM_DEVICE_PATH):
if not self._push_to_device(self._md5sum_path, MD5SUM_DEVICE_PATH):
- _log.error('Could not push md5sum to device')
+ raise AssertionError('Could not push md5sum to device')
self._push_executable()
self._push_fonts()
@@ -401,31 +413,20 @@ class ChromiumAndroidDriver(driver.Driver):
self._abort('Failed to install %s onto device: %s' % (drt_host_path, install_result))
def _push_fonts(self):
- if not self._check_version(DEVICE_FONTS_DIR, FONT_FILES_VERSION):
- self._log_debug('Pushing fonts')
- path_to_ahem_font = self._port._build_path('AHEM____.TTF')
- self._push_to_device(path_to_ahem_font, DEVICE_FONTS_DIR + 'AHEM____.TTF')
- for (host_dir, font_file) in HOST_FONT_FILES:
- self._push_to_device(host_dir + font_file, DEVICE_FONTS_DIR + font_file)
- self._link_device_file('/system/fonts/DroidSansFallback.ttf', DEVICE_FONTS_DIR + 'DroidSansFallback.ttf')
- self._update_version(DEVICE_FONTS_DIR, FONT_FILES_VERSION)
+ self._log_debug('Pushing fonts')
+ path_to_ahem_font = self._port._build_path('AHEM____.TTF')
+ self._push_file_if_needed(path_to_ahem_font, DEVICE_FONTS_DIR + 'AHEM____.TTF')
+ for (host_dirs, font_file, package) in HOST_FONT_FILES:
+ for host_dir in host_dirs:
+ host_font_path = host_dir + font_file
+ if self._port._check_file_exists(host_font_path, '', logging=False):
+ self._push_file_if_needed(host_font_path, DEVICE_FONTS_DIR + font_file)
def _push_test_resources(self):
self._log_debug('Pushing test resources')
for resource in TEST_RESOURCES_TO_PUSH:
self._push_file_if_needed(self._port.layout_tests_dir() + '/' + resource, DEVICE_LAYOUT_TESTS_DIR + resource)
- def _check_version(self, dir, version):
- assert(dir.endswith('/'))
- try:
- device_version = int(self._run_adb_command(['shell', 'cat %sVERSION || echo 0' % dir]))
- return device_version == version
- except:
- return False
-
- def _update_version(self, dir, version):
- self._run_adb_command(['shell', 'echo %d > %sVERSION' % (version, dir)])
-
def _run_adb_command(self, cmd, ignore_error=False):
self._log_debug('Run adb command: ' + str(cmd))
if ignore_error:
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 2ffb77979..bb4229e65 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_android_unittest.py
@@ -30,6 +30,7 @@ import optparse
import StringIO
import time
import unittest
+import sys
from webkitpy.common.system import executive_mock
from webkitpy.common.system.executive_mock import MockExecutive2
@@ -244,7 +245,8 @@ class ChromiumAndroidDriverTest(unittest.TestCase):
def test_command_from_driver_input(self):
driver_input = driver.DriverInput('foo/bar/test.html', 10, 'checksum', True)
expected_command = "/data/local/tmp/third_party/WebKit/LayoutTests/foo/bar/test.html'--pixel-test'checksum\n"
- self.assertEquals(self.driver._command_from_driver_input(driver_input), expected_command)
+ if (sys.platform != "cygwin"):
+ self.assertEquals(self.driver._command_from_driver_input(driver_input), expected_command)
driver_input = driver.DriverInput('http/tests/foo/bar/test.html', 10, 'checksum', True)
expected_command = "http://127.0.0.1:8000/foo/bar/test.html'--pixel-test'checksum\n"
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
index fa8c274ea..a2252c1b3 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
@@ -155,14 +155,6 @@ class ChromiumLinuxPort(chromium.ChromiumPort):
else:
return '/usr/sbin/apache2'
- def _path_to_apache_config_file(self):
- if self._is_redhat_based():
- config_name = 'fedora-httpd.conf'
- else:
- config_name = 'apache2-debian-httpd.conf'
-
- return self._filesystem.join(self.layout_tests_dir(), 'http', 'conf', config_name)
-
def _path_to_lighttpd(self):
return "/usr/sbin/lighttpd"
@@ -178,12 +170,3 @@ class ChromiumLinuxPort(chromium.ChromiumPort):
def _path_to_helper(self):
return None
-
- def _path_to_wdiff(self):
- if self._is_redhat_based():
- return '/usr/bin/dwdiff'
- else:
- return '/usr/bin/wdiff'
-
- def _is_redhat_based(self):
- return self._filesystem.exists(self._filesystem.join('/etc', 'redhat-release'))
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
index db82d5c79..08c1ede0f 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
@@ -94,6 +94,14 @@ class ChromiumMacPort(chromium.ChromiumPort):
def operating_system(self):
return 'mac'
+ def expectations_files(self):
+ # FIXME: This is a temporary hack while getting the 10.8 baselines up to date.
+ # See https://bugs.webkit.org/show_bug.cgi?id=99505
+ files = super(ChromiumMacPort, self).expectations_files()
+ if self.name() == 'chromium-mac-mountainlion':
+ files.append(self._filesystem.join(self._webkit_baseline_path(self.name()), 'TestExpectations'))
+ return files
+
#
# PROTECTED METHODS
#
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py
index edf92ea20..14e5a2b84 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py
@@ -95,6 +95,9 @@ class ChromiumMacPortTest(chromium_port_testcase.ChromiumPortTestCase):
def test_path_to_image_diff(self):
self.assertEquals(self.make_port()._path_to_image_diff(), '/mock-checkout/out/Release/ImageDiff')
+ def test_ml_expectations(self):
+ self.assertTrue(self.make_port(port_name='chromium-mac-mountainlion').expectations_files()[-1].endswith('-mountainlion/TestExpectations'))
+ self.assertFalse(self.make_port(port_name='chromium-mac-lion').expectations_files()[-1].endswith('-mountainlion/TestExpectations'))
if __name__ == '__main__':
port_testcase.main()
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/chromium_port_testcase.py b/Tools/Scripts/webkitpy/layout_tests/port/chromium_port_testcase.py
index fb90d1b9b..a082a131c 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/chromium_port_testcase.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/chromium_port_testcase.py
@@ -48,6 +48,13 @@ class ChromiumPortTestCase(port_testcase.PortTestCase):
port = self.make_port()
port.check_build(needs_http=True)
+ def test_default_max_locked_shards(self):
+ port = self.make_port()
+ port.default_child_processes = lambda: 16
+ self.assertEquals(port.default_max_locked_shards(), 4)
+ port.default_child_processes = lambda: 2
+ self.assertEquals(port.default_max_locked_shards(), 1)
+
def test_default_timeout_ms(self):
self.assertEquals(self.make_port(options=MockOptions(configuration='Release')).default_timeout_ms(), 6000)
self.assertEquals(self.make_port(options=MockOptions(configuration='Debug')).default_timeout_ms(), 12000)
@@ -72,6 +79,8 @@ class ChromiumPortTestCase(port_testcase.PortTestCase):
TestConfiguration('snowleopard', 'x86', 'release'),
TestConfiguration('lion', 'x86', 'debug'),
TestConfiguration('lion', 'x86', 'release'),
+ TestConfiguration('mountainlion', 'x86', 'debug'),
+ TestConfiguration('mountainlion', 'x86', 'release'),
TestConfiguration('xp', 'x86', 'debug'),
TestConfiguration('xp', 'x86', 'release'),
TestConfiguration('win7', 'x86', 'debug'),
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/driver.py b/Tools/Scripts/webkitpy/layout_tests/port/driver.py
index 4bf53d46a..7993d0577 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/driver.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/driver.py
@@ -76,7 +76,7 @@ class DriverOutput(object):
strip_patterns.append((re.compile('scrolled to [0-9]+,[0-9]+'), 'scrolled'))
def __init__(self, text, image, image_hash, audio, crash=False,
- test_time=0, timeout=False, error='', crashed_process_name='??',
+ test_time=0, measurements=None, timeout=False, error='', crashed_process_name='??',
crashed_pid=None, crash_log=None):
# FIXME: Args could be renamed to better clarify what they do.
self.text = text
@@ -89,6 +89,7 @@ class DriverOutput(object):
self.crashed_pid = crashed_pid
self.crash_log = crash_log
self.test_time = test_time
+ self.measurements = measurements
self.timeout = timeout
self.error = error # stderr output
@@ -138,6 +139,8 @@ class Driver(object):
self.err_seen_eof = False
self._server_process = None
+ self._measurements = {}
+
def __del__(self):
self.stop()
@@ -193,7 +196,7 @@ class Driver(object):
crash_log += '\nstdout:\n%s\nstderr:\n%s\n' % (text, self.error_from_test)
return DriverOutput(text, image, actual_image_hash, audio,
- crash=crashed, test_time=time.time() - test_begin_time,
+ crash=crashed, test_time=time.time() - test_begin_time, measurements=self._measurements,
timeout=timed_out, error=self.error_from_test,
crashed_process_name=self._crashed_process_name,
crashed_pid=self._crashed_pid, crash_log=crash_log)
@@ -360,6 +363,10 @@ class Driver(object):
def _read_first_block(self, deadline):
# returns (text_content, audio_content)
block = self._read_block(deadline)
+ if block.malloc:
+ self._measurements['Malloc'] = float(block.malloc)
+ if block.js_heap:
+ self._measurements['JSHeap'] = float(block.js_heap)
if block.content_type == 'audio/wav':
return (None, block.decoded_content)
return (block.decoded_content, None)
@@ -384,7 +391,9 @@ class Driver(object):
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')):
+ or self._read_header(block, line, 'ActualHash: ', 'content_hash')
+ or self._read_header(block, line, 'DumpMalloc: ', 'malloc')
+ or self._read_header(block, line, 'DumpJSHeap: ', 'js_heap')):
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.
@@ -450,6 +459,8 @@ class ContentBlock(object):
# 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
+ self.malloc = None
+ self.js_heap = None
def decode_content(self):
if self.encoding == 'base64' and self.content is not None:
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/efl.py b/Tools/Scripts/webkitpy/layout_tests/port/efl.py
index 269146aed..1022cd7b7 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/efl.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/efl.py
@@ -32,7 +32,7 @@ import os
from webkitpy.layout_tests.models.test_configuration import TestConfiguration
from webkitpy.layout_tests.port.base import Port
from webkitpy.layout_tests.port.pulseaudio_sanitizer import PulseAudioSanitizer
-
+from webkitpy.layout_tests.port.xvfbdriver import XvfbDriver
class EflPort(Port, PulseAudioSanitizer):
port_name = 'efl'
@@ -80,6 +80,9 @@ class EflPort(Port, PulseAudioSanitizer):
def _generate_all_test_configurations(self):
return [TestConfiguration(version=self._version, architecture='x86', build_type=build_type) for build_type in self.ALL_BUILD_TYPES]
+ def _driver_class(self):
+ return XvfbDriver
+
def _path_to_driver(self):
return self._build_path('bin', self.driver_name())
@@ -98,18 +101,22 @@ class EflPort(Port, PulseAudioSanitizer):
search_paths = []
if self.get_option('webkit_test_runner'):
search_paths.append(self.port_name + '-wk2')
+ search_paths.append('wk2')
else:
search_paths.append(self.port_name + '-wk1')
search_paths.append(self.port_name)
return search_paths
def expectations_files(self):
+ # FIXME: We should be able to use the default algorithm here.
return list(reversed([self._filesystem.join(self._webkit_baseline_path(p), 'TestExpectations') for p in self._search_paths()]))
def show_results_html_file(self, results_filename):
# FIXME: We should find a way to share this implmentation with Gtk,
# or teach run-launcher how to call run-safari and move this down to WebKitPort.
run_launcher_args = ["file://%s" % results_filename]
+ if self.get_option('webkit_test_runner'):
+ run_launcher_args.append('-2')
# FIXME: old-run-webkit-tests also added ["-graphicssystem", "raster", "-style", "windows"]
# FIXME: old-run-webkit-tests converted results_filename path for cygwin.
self._run_script("run-launcher", run_launcher_args)
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
index bb077c40a..2980c2d23 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
@@ -105,7 +105,7 @@ class FactoryTest(unittest.TestCase):
self.assertRaises(NotImplementedError, factory.PortFactory(MockSystemHost(os_name='vms')).get)
def test_get_from_builder_name(self):
- self.assertEquals(factory.PortFactory(MockSystemHost()).get_from_builder_name('Webkit Mac10.7').name(),
+ self.assertEquals(factory.PortFactory(MockSystemHost()).get_from_builder_name('WebKit Mac10.7').name(),
'chromium-mac-lion')
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/gtk.py b/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
index f02d14819..6c57b5363 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/gtk.py
@@ -41,6 +41,9 @@ class GtkPort(Port, PulseAudioSanitizer):
def expectations_files(self):
return [self._filesystem.join(self._webkit_baseline_path(d), 'TestExpectations') for d in self._skipped_file_search_paths()]
+ def warn_if_bug_missing_in_test_expectations(self):
+ return True
+
def _port_flag_for_scripts(self):
return "--gtk"
@@ -89,18 +92,6 @@ class GtkPort(Port, PulseAudioSanitizer):
def _path_to_image_diff(self):
return self._build_path('Programs', 'ImageDiff')
- def _path_to_apache(self):
- if self._is_redhat_based():
- return '/usr/sbin/httpd'
- else:
- return '/usr/sbin/apache2'
-
- def _path_to_wdiff(self):
- if self._is_redhat_based():
- return '/usr/bin/dwdiff'
- else:
- return '/usr/bin/wdiff'
-
def _path_to_webcore_library(self):
gtk_library_names = [
"libwebkitgtk-1.0.so",
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py b/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
index 985241ede..f704a7a13 100755
--- a/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
@@ -30,6 +30,7 @@
import errno
import logging
+import os
import socket
import sys
import time
@@ -89,6 +90,13 @@ class PortTestCase(unittest.TestCase):
port_name = self.port_maker.determine_full_port_name(host, options, port_name)
return self.port_maker(host, port_name, options=options, config=config, **kwargs)
+ def test_default_max_locked_shards(self):
+ port = self.make_port()
+ port.default_child_processes = lambda: 16
+ self.assertEquals(port.default_max_locked_shards(), 1)
+ port.default_child_processes = lambda: 2
+ self.assertEquals(port.default_max_locked_shards(), 1)
+
def test_default_timeout_ms(self):
self.assertEquals(self.make_port(options=MockOptions(configuration='Release')).default_timeout_ms(), 35000)
self.assertEquals(self.make_port(options=MockOptions(configuration='Debug')).default_timeout_ms(), 35000)
@@ -582,10 +590,29 @@ class PortTestCase(unittest.TestCase):
def test_path_to_apache_config_file(self):
port = TestWebKitPort()
+
+ saved_environ = os.environ.copy()
+ try:
+ os.environ['WEBKIT_HTTP_SERVER_CONF_PATH'] = '/path/to/httpd.conf'
+ self.assertRaises(IOError, port._path_to_apache_config_file)
+ port._filesystem.write_text_file('/existing/httpd.conf', 'Hello, world!')
+ os.environ['WEBKIT_HTTP_SERVER_CONF_PATH'] = '/existing/httpd.conf'
+ self.assertEquals(port._path_to_apache_config_file(), '/existing/httpd.conf')
+ finally:
+ os.environ = saved_environ.copy()
+
# 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')
+ # Check that even if we mock out _apache_config_file_name, the environment variable takes precedence.
+ saved_environ = os.environ.copy()
+ try:
+ os.environ['WEBKIT_HTTP_SERVER_CONF_PATH'] = '/existing/httpd.conf'
+ self.assertEquals(port._path_to_apache_config_file(), '/existing/httpd.conf')
+ finally:
+ os.environ = saved_environ.copy()
+
def test_check_build(self):
port = self.make_port(options=MockOptions(build=True))
self.build_called = False
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/qt.py b/Tools/Scripts/webkitpy/layout_tests/port/qt.py
index 828a80d64..5b8342d9c 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/qt.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/qt.py
@@ -88,9 +88,9 @@ class QtPort(Port):
def _path_to_webcore_library(self):
if self.operating_system() == 'mac':
- return self._build_path('lib/QtWebKit.framework/QtWebKit')
+ return self._build_path('lib/QtWebKitWidgets.framework/QtWebKitWidgets')
else:
- return self._build_path('lib/libQtWebKit.so')
+ return self._build_path('lib/libQtWebKitWidgets.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.
@@ -135,23 +135,21 @@ class QtPort(Port):
search_paths.append('qt-4.8')
elif version:
search_paths.append('qt-5.0')
- search_paths.append(self.port_name + '-' + self.host.platform.os_name)
+ search_paths.append(self.port_name + '-' + self.operating_system())
search_paths.append(self.port_name)
return search_paths
def default_baseline_search_path(self):
return map(self._webkit_baseline_path, self._search_paths())
- def _skipped_file_search_paths(self):
- skipped_path = self._search_paths()
- if self.get_option('webkit_test_runner') and '5.0' in self.qt_version():
- skipped_path.append('wk2')
- return skipped_path
-
def expectations_files(self):
+ paths = self._search_paths()
+ if self.get_option('webkit_test_runner'):
+ paths.append('wk2')
+
# expectations_files() uses the directories listed in _search_paths reversed.
# e.g. qt -> qt-linux -> qt-4.8
- return list(reversed([self._filesystem.join(self._webkit_baseline_path(p), 'TestExpectations') for p in self._search_paths()]))
+ return list(reversed([self._filesystem.join(self._webkit_baseline_path(p), 'TestExpectations') for p in paths]))
def setup_environ_for_server(self, server_name=None):
clean_env = super(QtPort, self).setup_environ_for_server(server_name)
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/qt_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/qt_unittest.py
index 374b10270..cf09bd8e0 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/qt_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/qt_unittest.py
@@ -71,14 +71,6 @@ class QtPortTest(port_testcase.PortTestCase):
absolute_search_paths = map(port._webkit_baseline_path, search_paths)
self.assertEquals(port.baseline_search_path(), absolute_search_paths)
- def _assert_skipped_path(self, search_paths, os_name, use_webkit2=False, qt_version='4.8'):
- host = MockSystemHost(os_name=os_name)
- host.executive = MockExecutive2(self._qt_version(qt_version))
- port_name = 'qt-' + os_name
- port = self.make_port(host=host, qt_version=qt_version, port_name=port_name,
- options=MockOptions(webkit_test_runner=use_webkit2, platform='qt'))
- self.assertEquals(port._skipped_file_search_paths(), search_paths)
-
def _assert_expectations_files(self, search_paths, os_name, use_webkit2=False, qt_version='4.8'):
# FIXME: Port constructors should not "parse" the port name, but
# rather be passed components (directly or via setters). Once
@@ -100,19 +92,13 @@ class QtPortTest(port_testcase.PortTestCase):
for case in self.search_paths_cases:
self._assert_search_path(**case)
- def test_skipped_file_search_path(self):
- caselist = self.search_paths_cases[:]
- for case in caselist:
- if case['use_webkit2'] and case['qt_version'] == '5.0':
- case['search_paths'].append("wk2")
- self._assert_skipped_path(**case)
-
def test_expectations_files(self):
for case in self.search_paths_cases:
expectations_case = deepcopy(case)
- expectations_case['search_paths'] = []
- for path in reversed(case['search_paths']):
- expectations_case['search_paths'].append('/mock-checkout/LayoutTests/platform/%s/TestExpectations' % (path))
+ if expectations_case['use_webkit2']:
+ expectations_case['search_paths'].append("wk2")
+ expectations_case['search_paths'].reverse()
+ expectations_case['search_paths'] = map(lambda path: '/mock-checkout/LayoutTests/platform/%s/TestExpectations' % (path), expectations_case['search_paths'])
self._assert_expectations_files(**expectations_case)
def test_show_results_html_file(self):
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/server_process.py b/Tools/Scripts/webkitpy/layout_tests/port/server_process.py
index bfa6aab80..bfdf8301b 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/server_process.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/server_process.py
@@ -84,6 +84,17 @@ class ServerProcess(object):
return self._pid
def _reset(self):
+ if getattr(self, '_proc', None):
+ if self._proc.stdin:
+ self._proc.stdin.close()
+ self._proc.stdin = None
+ if self._proc.stdout:
+ self._proc.stdout.close()
+ self._proc.stdout = None
+ if self._proc.stderr:
+ self._proc.stderr.close()
+ self._proc.stderr = None
+
self._proc = None
self._output = str() # bytesarray() once we require Python 2.6
self._error = str() # bytesarray() once we require Python 2.6
@@ -321,8 +332,11 @@ class ServerProcess(object):
now = time.time()
self._proc.stdin.close()
+ self._proc.stdin = None
+ killed = False
if not timeout_secs:
self._kill()
+ killed = True
elif not self._host.platform.is_win():
# FIXME: Why aren't we calling this on win?
deadline = now + timeout_secs
@@ -331,13 +345,15 @@ class ServerProcess(object):
if self._proc.poll() is None:
_log.warning('stopping %s timed out, killing it' % self._name)
self._kill()
+ killed = True
_log.warning('killed')
# read any remaining data on the pipes and return it.
- if self._use_win32_apis:
- self._wait_for_data_and_update_buffers_using_win32_apis(now)
- else:
- self._wait_for_data_and_update_buffers_using_select(now, stopping=True)
+ if not killed:
+ if self._use_win32_apis:
+ self._wait_for_data_and_update_buffers_using_win32_apis(now)
+ else:
+ self._wait_for_data_and_update_buffers_using_select(now, stopping=True)
out, err = self._output, self._error
self._reset()
return (out, err)
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py
index 48c41e6f2..7a5ac45d4 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py
@@ -57,6 +57,7 @@ class TrivialMockPort(object):
class MockFile(object):
def __init__(self, server_process):
self._server_process = server_process
+ self.closed = False
def fileno(self):
return 1
@@ -66,7 +67,7 @@ class MockFile(object):
raise IOError
def close(self):
- pass
+ self.closed = True
class MockProc(object):
@@ -87,6 +88,8 @@ class FakeServerProcess(server_process.ServerProcess):
def _start(self):
self._proc = MockProc(self)
self.stdin = self._proc.stdin
+ self.stdout = self._proc.stdout
+ self.stderr = self._proc.stderr
self._pid = self._proc.pid
self.broken_pipes = []
@@ -121,6 +124,15 @@ class TestServerProcess(unittest.TestCase):
proc.stop(0)
+ def test_cleanup(self):
+ port_obj = TrivialMockPort()
+ server_process = FakeServerProcess(port_obj=port_obj, name="test", cmd=["test"])
+ server_process._start()
+ server_process.stop()
+ self.assertTrue(server_process.stdin.closed)
+ self.assertTrue(server_process.stdout.closed)
+ self.assertTrue(server_process.stderr.closed)
+
def test_broken_pipe(self):
port_obj = TrivialMockPort()
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/test.py b/Tools/Scripts/webkitpy/layout_tests/port/test.py
index d008d995d..726575614 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/test.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/test.py
@@ -239,6 +239,11 @@ layer at (0,0) size 800x34
actual_image='image_not_in_pixeldir-pngtEXtchecksum\x00checksum_fail',
expected_image='image_not_in_pixeldir-pngtEXtchecksum\x00checksum-png')
+ # For testing that virtual test suites don't expand names containing themselves
+ # See webkit.org/b/97925 and base_unittest.PortTest.test_tests().
+ tests.add('passes/test-virtual-passes.html')
+ tests.add('passes/passes/test-virtual-passes.html')
+
return tests
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver.py b/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver.py
index 7e386a108..b927720db 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver.py
@@ -28,41 +28,60 @@
import logging
import os
+import re
+import time
from webkitpy.layout_tests.port.server_process import ServerProcess
from webkitpy.layout_tests.port.driver import Driver
+from webkitpy.common.system.file_lock import FileLock
_log = logging.getLogger(__name__)
class XvfbDriver(Driver):
- def _start(self, pixel_tests, per_test_args):
-
- # Collect the number of X servers running already and make
- # sure our Xvfb process doesn't clash with any of them.
- def x_filter(process_name):
- return process_name.find("Xorg") > -1
+ def __init__(self, *args, **kwargs):
+ Driver.__init__(self, *args, **kwargs)
+ self._guard_lock = None
+ self._startup_delay_secs = 1.0
- running_displays = len(self._port.host.executive.running_pids(x_filter))
+ def _next_free_display(self):
+ running_pids = self._port.host.executive.run_command(['ps', '-eo', 'comm,command'])
+ reserved_screens = set()
+ for pid in running_pids.split('\n'):
+ match = re.match('(X|Xvfb|Xorg)\s+.*\s:(?P<screen_number>\d+)', pid)
+ if match:
+ reserved_screens.add(int(match.group('screen_number')))
+ for i in range(99):
+ if i not in reserved_screens:
+ _guard_lock_file = self._port.host.filesystem.join('/tmp', 'WebKitXvfb.lock.%i' % i)
+ self._guard_lock = FileLock(_guard_lock_file)
+ if self._guard_lock.acquire_lock():
+ return i
+ def _start(self, pixel_tests, per_test_args):
# Use even displays for pixel tests and odd ones otherwise. When pixel tests are disabled,
# DriverProxy creates two drivers, one for normal and the other for ref tests. Both have
# the same worker number, so this prevents them from using the same Xvfb instance.
- display_id = self._worker_number * 2 + running_displays
- if pixel_tests:
- display_id += 1
+ display_id = self._next_free_display()
self._lock_file = "/tmp/.X%d-lock" % display_id
run_xvfb = ["Xvfb", ":%d" % display_id, "-screen", "0", "800x600x24", "-nolisten", "tcp"]
with open(os.devnull, 'w') as devnull:
self._xvfb_process = self._port.host.executive.popen(run_xvfb, stderr=devnull)
+ # Crashes intend to occur occasionally in the first few tests that are run through each
+ # worker because the Xvfb display isn't ready yet. Halting execution a bit should avoid that.
+ time.sleep(self._startup_delay_secs)
+
server_name = self._port.driver_name()
environment = self._port.setup_environ_for_server(server_name)
# We must do this here because the DISPLAY number depends on _worker_number
environment['DISPLAY'] = ":%d" % display_id
# Drivers should use separate application cache locations
environment['XDG_CACHE_HOME'] = self._port.host.filesystem.join(self._port.results_directory(), '%s-appcache-%d' % (server_name, self._worker_number))
+ self._driver_tempdir = self._port._filesystem.mkdtemp(prefix='%s-' % self._port.driver_name())
+ 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
@@ -71,6 +90,9 @@ class XvfbDriver(Driver):
def stop(self):
super(XvfbDriver, self).stop()
+ if self._guard_lock:
+ self._guard_lock.release_lock()
+ self._guard_lock = None
if getattr(self, '_xvfb_process', None):
self._port.host.executive.kill_process(self._xvfb_process.pid)
self._xvfb_process = None
diff --git a/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver_unittest.py b/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver_unittest.py
index 37a2fbd4d..220dd3517 100644
--- a/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver_unittest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/port/xvfbdriver_unittest.py
@@ -30,6 +30,7 @@ import unittest
from webkitpy.common.system.deprecated_logging import log
from webkitpy.common.system.filesystem_mock import MockFileSystem
+from webkitpy.common.system.executive_mock import MockExecutive2
from webkitpy.common.system.outputcapture import OutputCapture
from webkitpy.common.system.systemhost_mock import MockSystemHost
from webkitpy.layout_tests.port import Port
@@ -39,13 +40,14 @@ from webkitpy.layout_tests.port.xvfbdriver import XvfbDriver
class XvfbDriverTest(unittest.TestCase):
- def make_driver(self, worker_number=0, xorg_running=False):
- port = Port(host=MockSystemHost(log_executive=True), config=MockConfig())
+ def make_driver(self, worker_number=0, xorg_running=False, executive=None):
+ port = Port(host=MockSystemHost(log_executive=True, executive=executive), config=MockConfig())
port._server_process_constructor = MockServerProcess
if xorg_running:
port._executive._running_pids['Xorg'] = 108
driver = XvfbDriver(port, worker_number=worker_number, pixel_tests=True)
+ driver._startup_delay_secs = 0
return driver
def cleanup_driver(self, driver):
@@ -61,26 +63,54 @@ class XvfbDriverTest(unittest.TestCase):
def test_start_no_pixel_tests(self):
driver = self.make_driver()
- expected_stderr = "MOCK running_pids: []\nMOCK popen: ['Xvfb', ':0', '-screen', '0', '800x600x24', '-nolisten', 'tcp']\n"
+ expected_stderr = "MOCK run_command: ['ps', '-eo', 'comm,command'], cwd=None\nMOCK popen: ['Xvfb', ':0', '-screen', '0', '800x600x24', '-nolisten', 'tcp']\n"
self.assertDriverStartSuccessful(driver, expected_stderr=expected_stderr, expected_display=":0")
self.cleanup_driver(driver)
def test_start_pixel_tests(self):
driver = self.make_driver()
- expected_stderr = "MOCK running_pids: []\nMOCK popen: ['Xvfb', ':1', '-screen', '0', '800x600x24', '-nolisten', 'tcp']\n"
- self.assertDriverStartSuccessful(driver, expected_stderr=expected_stderr, expected_display=":1", pixel_tests=True)
+ expected_stderr = "MOCK run_command: ['ps', '-eo', 'comm,command'], cwd=None\nMOCK popen: ['Xvfb', ':0', '-screen', '0', '800x600x24', '-nolisten', 'tcp']\n"
+ self.assertDriverStartSuccessful(driver, expected_stderr=expected_stderr, expected_display=":0", pixel_tests=True)
self.cleanup_driver(driver)
def test_start_arbitrary_worker_number(self):
driver = self.make_driver(worker_number=17)
- expected_stderr = "MOCK running_pids: []\nMOCK popen: ['Xvfb', ':35', '-screen', '0', '800x600x24', '-nolisten', 'tcp']\n"
- self.assertDriverStartSuccessful(driver, expected_stderr=expected_stderr, expected_display=":35", pixel_tests=True)
+ expected_stderr = "MOCK run_command: ['ps', '-eo', 'comm,command'], cwd=None\nMOCK popen: ['Xvfb', ':0', '-screen', '0', '800x600x24', '-nolisten', 'tcp']\n"
+ self.assertDriverStartSuccessful(driver, expected_stderr=expected_stderr, expected_display=":0", pixel_tests=True)
self.cleanup_driver(driver)
- def test_start_existing_xorg_process(self):
- driver = self.make_driver(xorg_running=True)
- expected_stderr = "MOCK running_pids: [108]\nMOCK popen: ['Xvfb', ':1', '-screen', '0', '800x600x24', '-nolisten', 'tcp']\n"
- self.assertDriverStartSuccessful(driver, expected_stderr=expected_stderr, expected_display=":1")
+ def disabled_test_next_free_display(self):
+ output = "Xorg /usr/bin/X :0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch -background none\nXvfb Xvfb :1 -screen 0 800x600x24 -nolisten tcp"
+ executive = MockExecutive2(output)
+ driver = self.make_driver(executive=executive)
+ self.assertEqual(driver._next_free_display(), 2)
+ self.cleanup_driver(driver)
+ output = "X /usr/bin/X :0 vt7 -nolisten tcp -auth /var/run/xauth/A:0-8p7Ybb"
+ executive = MockExecutive2(output)
+ driver = self.make_driver(executive=executive)
+ self.assertEqual(driver._next_free_display(), 1)
+ self.cleanup_driver(driver)
+ output = "Xvfb Xvfb :0 -screen 0 800x600x24 -nolisten tcp"
+ executive = MockExecutive2(output)
+ driver = self.make_driver(executive=executive)
+ self.assertEqual(driver._next_free_display(), 1)
+ self.cleanup_driver(driver)
+ output = "Xvfb Xvfb :1 -screen 0 800x600x24 -nolisten tcp\nXvfb Xvfb :0 -screen 0 800x600x24 -nolisten tcp\nXvfb Xvfb :3 -screen 0 800x600x24 -nolisten tcp"
+ executive = MockExecutive2(output)
+ driver = self.make_driver(executive=executive)
+ self.assertEqual(driver._next_free_display(), 2)
+ self.cleanup_driver(driver)
+
+ def test_start_next_worker(self):
+ driver = self.make_driver()
+ driver._next_free_display = lambda: 0
+ expected_stderr = "MOCK popen: ['Xvfb', ':0', '-screen', '0', '800x600x24', '-nolisten', 'tcp']\n"
+ self.assertDriverStartSuccessful(driver, expected_stderr=expected_stderr, expected_display=":0", pixel_tests=True)
+ self.cleanup_driver(driver)
+ driver = self.make_driver()
+ driver._next_free_display = lambda: 3
+ expected_stderr = "MOCK popen: ['Xvfb', ':3', '-screen', '0', '800x600x24', '-nolisten', 'tcp']\n"
+ self.assertDriverStartSuccessful(driver, expected_stderr=expected_stderr, expected_display=":3", pixel_tests=True)
self.cleanup_driver(driver)
def test_stop(self):
diff --git a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
index e784cb61d..89522079c 100755
--- a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
+++ b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
@@ -129,6 +129,9 @@ def _set_up_derived_options(port, options):
if not options.child_processes:
options.child_processes = os.environ.get("WEBKIT_TEST_CHILD_PROCESSES",
str(port.default_child_processes()))
+ if not options.max_locked_shards:
+ options.max_locked_shards = int(os.environ.get("WEBKIT_TEST_MAX_LOCKED_SHARDS",
+ str(port.default_max_locked_shards())))
if not options.configuration:
options.configuration = port.default_configuration()
@@ -375,7 +378,11 @@ def parse_args(args=None):
optparse.make_option("--test-list", action="append",
help="read list of tests to run from file", metavar="FILE"),
optparse.make_option("--skipped", action="store", default="default",
- help="control how tests marked SKIP are run. 'default' == Skip, 'ignore' == Run them anyway, 'only' == only run the SKIP tests."),
+ help=("control how tests marked SKIP are run. "
+ "'default' == Skip tests unless explicitly listed on the command line, "
+ "'ignore' == Run them anyway, "
+ "'only' == only run the SKIP tests, "
+ "'always' == always skip, even if listed on the command line.")),
optparse.make_option("--force", dest="skipped", action="store_const", const='ignore',
help="Run all tests, even those marked SKIP in the test list (same as --skipped=ignore)"),
optparse.make_option("--time-out-ms",
@@ -412,7 +419,7 @@ def parse_args(args=None):
optparse.make_option("--no-retry-failures", action="store_false",
dest="retry_failures",
help="Don't re-try any tests that produce unexpected results."),
- optparse.make_option("--max-locked-shards", type="int", default=1,
+ optparse.make_option("--max-locked-shards", type="int", default=0,
help="Set the maximum number of locked shards"),
optparse.make_option("--additional-env-var", type="string", action="append", default=[],
help="Passes that environment variable to the tests (--additional-env-var=NAME=VALUE)"),
diff --git a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py
index 4afcc1466..85437449b 100755
--- a/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py
+++ b/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py
@@ -301,6 +301,12 @@ class MainTest(unittest.TestCase, StreamTestingMixin):
for batch in batch_tests_run:
self.assertTrue(len(batch) <= 2, '%s had too many tests' % ', '.join(batch))
+ def test_max_locked_shards(self):
+ if not self.should_test_processes:
+ return
+ _, _, regular_output, _ = logging_run(['--debug-rwt-logging', '--child-processes', '2'], shared_port=False)
+ self.assertTrue(any(['(1 locked)' in line for line in regular_output.buflist]))
+
def test_child_processes_2(self):
if self.should_test_processes:
_, _, regular_output, _ = logging_run(
@@ -310,7 +316,7 @@ class MainTest(unittest.TestCase, StreamTestingMixin):
def test_child_processes_min(self):
if self.should_test_processes:
_, _, regular_output, _ = logging_run(
- ['--debug-rwt-logging', '--child-processes', '2', 'passes'],
+ ['--debug-rwt-logging', '--child-processes', '2', '-i', 'passes/passes', 'passes'],
tests_included=True, shared_port=False)
self.assertTrue(any(['Running 1 ' in line for line in regular_output.buflist]))
@@ -418,6 +424,10 @@ class MainTest(unittest.TestCase, StreamTestingMixin):
self.assertEquals(get_tests_run(['--skipped=only', 'passes'], tests_included=True, flatten_batches=True),
['passes/skipped/skip.html'])
+ # Now check that we don't run anything.
+ self.assertEquals(get_tests_run(['--skipped=always', 'passes/skipped/skip.html'], tests_included=True, flatten_batches=True),
+ [])
+
def test_iterations(self):
tests_to_run = ['passes/image.html', 'passes/text.html']
tests_run = get_tests_run(['--iterations', '2'] + tests_to_run, tests_included=True, flatten_batches=True)
@@ -775,7 +785,7 @@ class MainTest(unittest.TestCase, StreamTestingMixin):
# These next tests test that we run the tests in ascending alphabetical
# order per directory. HTTP tests are sharded separately from other tests,
# so we have to test both.
- tests_run = get_tests_run(['passes'], tests_included=True, flatten_batches=True)
+ tests_run = get_tests_run(['-i', 'passes/passes', 'passes'], tests_included=True, flatten_batches=True)
self.assertEquals(tests_run, sorted(tests_run))
tests_run = get_tests_run(['http/tests/passes'], tests_included=True, flatten_batches=True)
@@ -922,6 +932,11 @@ class MainTest(unittest.TestCase, StreamTestingMixin):
# child process (e.g., on win32) and we need to make sure that works and we still
# see the verbose log output. However, we can't use logging_run() because using
# outputcapture to capture stdout and stderr latter results in a nonpicklable host.
+
+ # Test is flaky on Windows: https://bugs.webkit.org/show_bug.cgi?id=98559
+ if not self.should_test_processes:
+ return
+
options, parsed_args = parse_args(['--verbose', '--fully-parallel', '--child-processes', '2', 'passes/text.html', 'passes/image.html'], tests_included=True, print_nothing=False)
host = MockHost()
port_obj = host.port_factory.get(port_name=options.platform, options=options)
diff --git a/Tools/Scripts/webkitpy/layout_tests/servers/apache_http_server.py b/Tools/Scripts/webkitpy/layout_tests/servers/apache_http_server.py
index 7cd4af538..a616fab5b 100644
--- a/Tools/Scripts/webkitpy/layout_tests/servers/apache_http_server.py
+++ b/Tools/Scripts/webkitpy/layout_tests/servers/apache_http_server.py
@@ -54,7 +54,6 @@ class LayoutTestApacheHttpd(http_server_base.HttpServerBase):
self._name = 'httpd'
self._mappings = [{'port': 8000},
{'port': 8080},
- {'port': 8081},
{'port': 8443, 'sslcert': True}]
self._output_dir = output_dir
self._filesystem.maybe_make_directory(output_dir)
@@ -79,7 +78,6 @@ class LayoutTestApacheHttpd(http_server_base.HttpServerBase):
'-c', "\'Alias /js-test-resources \"%s\"'" % js_test_resources_dir,
'-c', "\'Alias /media-resources \"%s\"'" % media_resources_dir,
'-C', "\'Listen %s\'" % "127.0.0.1:8000",
- '-C', "\'Listen %s\'" % "127.0.0.1:8081",
'-c', "\'TypesConfig \"%s\"\'" % mime_types_path,
'-c', "\'CustomLog \"%s\" common\'" % access_log,
'-c', "\'ErrorLog \"%s\"\'" % error_log,