blob: c1214463de027e37f487e970a18bd5f0506368de [file] [log] [blame]
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""A wrapper script to run layout tests on the buildbots.
Runs the run-webkit-tests script found in third_party/WebKit/Tools/Scripts above
this script. For a complete list of command-line options, pass '--help' on the
command line.
To pass additional options to run-webkit-tests without having them interpreted
as options for this script, include them in an '--options="..."' argument. In
addition, a list of one or more tests or test directories, specified relative
to the main webkit test directory, may be passed on the command line.
"""
import json
import optparse
import os
import re
import sys
from common import chromium_utils
from slave import build_directory
from slave import slave_utils
def layout_test(options, args):
"""Parse options and call run-webkit-tests, using Python from the tree."""
build_dir = os.path.abspath(options.build_dir)
dumprendertree_exe = 'DumpRenderTree.exe'
if options.driver_name:
dumprendertree_exe = '%s.exe' % options.driver_name
# Disable the page heap in case it got left enabled by some previous process.
try:
slave_utils.SetPageHeap(build_dir, dumprendertree_exe, False)
except chromium_utils.PathNotFound:
# If we don't have gflags.exe, report it but don't worry about it.
print 'Warning: Couldn\'t disable page heap, if it was already enabled.'
blink_scripts_dir = chromium_utils.FindUpward(build_dir,
'third_party', 'WebKit', 'Tools', 'Scripts')
run_blink_tests = os.path.join(blink_scripts_dir, 'run-webkit-tests')
command = [run_blink_tests,
'--no-show-results',
'--no-new-test-results',
'--full-results-html', # For the dashboards.
'--clobber-old-results', # Clobber test results before each run.
'--exit-after-n-failures', '5000',
'--exit-after-n-crashes-or-timeouts', '100',
]
# TODO(dpranke): we can switch to always using --debug-rwt-logging
# after all the bots have WebKit r124789 or later.
capture_obj = slave_utils.RunCommandCaptureFilter()
slave_utils.RunPythonCommandInBuildDir(build_dir, options.target,
[run_blink_tests, '--help'],
filter_obj=capture_obj)
if '--debug-rwt-logging' in ''.join(capture_obj.lines):
command.append('--debug-rwt-logging')
else:
command.append('--verbose')
if options.results_directory:
# Prior to the fix in https://bugs.webkit.org/show_bug.cgi?id=58272,
# run_blink_tests expects the results directory to be relative to
# the configuration directory (e.g., src/webkit/Release). The
# parameter is given to us relative to build_dir, which is where we
# will run the command from.
#
# When 58272 is landed, run_blink_tests will support absolute file
# paths as well as paths relative to CWD for non-Chromium ports and
# paths relative to the configuration dir for Chromium ports. As
# a transitional fix, we convert to an absolute dir, but once the
# hack in 58272 is removed, we can use results_dir as-is.
if not os.path.isabs(options.results_directory):
if options.results_directory.startswith('../../'):
options.results_directory = options.results_directory[6:]
options.results_directory = os.path.abspath(
os.path.join(os.getcwd(), options.results_directory))
chromium_utils.RemoveDirectory(options.results_directory)
command.extend(['--results-directory', options.results_directory])
if options.target:
command.extend(['--target', options.target])
if options.platform:
command.extend(['--platform', options.platform])
if options.skipped:
command.extend(['--skipped', options.skipped])
if options.no_pixel_tests:
command.append('--no-pixel-tests')
if options.enable_wptserve:
command.append('--enable-wptserve')
if options.batch_size:
command.extend(['--batch-size', options.batch_size])
if options.run_part:
command.extend(['--run-part', options.run_part])
if options.builder_name:
command.extend(['--builder-name', options.builder_name])
if options.build_number:
command.extend(['--build-number', options.build_number])
command.extend(['--master-name', slave_utils.GetActiveMaster() or ''])
if options.step_name:
command.extend(['--step-name', options.step_name])
# On Windows, look for the target in an exact location.
if sys.platform == 'win32':
command.extend(['--build-directory', build_dir])
if options.test_results_server:
command.extend(['--test-results-server', options.test_results_server])
if options.enable_pageheap:
command.append('--time-out-ms=120000')
if options.time_out_ms:
command.extend(['--time-out-ms', options.time_out_ms])
for filename in options.additional_expectations:
command.append('--additional-expectations=%s' % filename)
if options.driver_name:
command.append('--driver-name=%s' % options.driver_name)
for additional_drt_flag in options.additional_drt_flag:
command.append('--additional-drt-flag=%s' % additional_drt_flag)
for test_list in options.test_list:
command += ['--test-list', test_list]
if options.enable_leak_detection:
command.append('--enable-leak-detection')
# The list of tests is given as arguments.
if options.options:
command.extend(options.options.split(' '))
command.extend(args)
# Nuke anything that appears to be stale chrome items in the temporary
# directory from previous test runs (i.e.- from crashes or unittest leaks).
slave_utils.RemoveChromeTemporaryFiles()
try:
if options.enable_pageheap:
slave_utils.SetPageHeap(build_dir, dumprendertree_exe, True)
# Run the the tests
return slave_utils.RunPythonCommandInBuildDir(build_dir, options.target,
command)
finally:
if options.enable_pageheap:
slave_utils.SetPageHeap(build_dir, dumprendertree_exe, False)
if options.json_test_results:
results_dir = options.results_directory
results_json = os.path.join(results_dir, "failing_results.json")
# If the json results file was not produced, then we produce no output
# file too and rely on a recipe to handle this as invalid result.
if os.path.isfile(results_json):
with open(results_json, 'rb') as f:
data = f.read()
# data is in the form of:
# ADD_RESULTS(<json object>);
# but use a regex match to also support a raw json object.
m = re.match(r'[^({]*' # From the beginning, take any except '(' or '{'
r'(?:'
r'\((.*)\);' # Expect '(<json>);'
r'|' # or
r'({.*})' # '<json object>'
r')$', data)
assert m is not None
data = m.group(1) or m.group(2)
json_data = json.loads(data)
assert isinstance(json_data, dict)
with open(options.json_test_results, 'wb') as f:
f.write(data)
def main():
option_parser = optparse.OptionParser()
option_parser.add_option('-o', '--results-directory', default='',
help='output results directory')
option_parser.add_option('--build-dir', default='webkit', help='ignored')
option_parser.add_option('--target', default='',
help='DumpRenderTree build configuration (Release or Debug)')
option_parser.add_option('--options', default='',
help='additional options to pass to run-webkit-tests')
option_parser.add_option('--platform', default='',
help=('Platform value passed directly to run-webkit-tests.'))
option_parser.add_option('--skipped', default='',
help='option for handling Skipped, passed through to run-webkit-tests.')
option_parser.add_option('--no-pixel-tests', action='store_true',
default=False,
help='disable pixel-to-pixel PNG comparisons')
option_parser.add_option('--enable-pageheap', action='store_true',
default=False, help='Enable page heap checking')
option_parser.add_option('--batch-size',
default=None,
help=('Run a the tests in batches (n), after every '
'n tests, the test shell is relaunched.'))
option_parser.add_option('--run-part',
default=None,
help=('Run a specified part (n:l), the nth of lth'
', of the layout tests'))
option_parser.add_option('--builder-name',
default=None,
help='The name of the builder running this script.')
option_parser.add_option('--step-name',
default=None,
help='The name of the step running this script.')
option_parser.add_option('--build-number',
default=None,
help=('The build number of the builder running'
'this script.'))
option_parser.add_option('--test-results-server',
help=('If specified, upload results json files to '
'this appengine server.'))
option_parser.add_option('--additional-expectations', action='append',
default=[],
help=('Path to a test_expectations file '
'that will override previous expectations. '
'Specify multiple times for multiple sets '
'of overrides.'))
option_parser.add_option('--enable-wptserve', action='store_true',
default=None,
help=('Enable running web-platform-tests'
'using WPTserve instead of Apache.'))
# TODO(dpranke): remove this after we fix the flag in the chromium command.
option_parser.add_option('--additional-expectations-file',
dest='additional_expectations',
action='append', default=[],
help=('DEPRECATED. '
'Same as --additional-expectations'))
option_parser.add_option('--time-out-ms',
action='store', default=None,
help='Set the timeout for each (non-SLOW) test')
option_parser.add_option('--driver-name',
help=('If specified, alternative DumpRenderTree '
'binary to use'))
# TODO(dpranke): Remove additional-drt-flag as it should not be used
# any more.
option_parser.add_option('--additional-driver-flag',
'--additional-drt-flag',
dest='additional_drt_flag',
action='append', default=[],
help=('If specified, additional command line flag '
'to pass to DumpRenderTree. Specify multiple '
'times to add multiple flags.'))
option_parser.add_option('--json-test-results',
help=('Path to write json results to allow '
'TryJob recipe to know how to ignore '
'expected failures.'))
option_parser.add_option('--test-list', action='append', metavar='FILE',
default=[],
help='Read list of tests to run from file.')
option_parser.add_option('--enable-leak-detection', action='store_true',
default=False, help='Enable the leak detection')
options, args = option_parser.parse_args()
options.build_dir = build_directory.GetBuildOutputDirectory()
# Disable pageheap checking except on Windows.
if sys.platform != 'win32':
options.enable_pageheap = False
return layout_test(options, args)
if '__main__' == __name__:
sys.exit(main())