REGRESSION (r226485): Many new wasm leaks detected by the leaks bot
[WebKit-https.git] / Tools / Scripts / webkitpy / layout_tests / run_webkit_tests.py
1 # Copyright (C) 2010 Google Inc. All rights reserved.
2 # Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged
3 # Copyright (C) 2011, 2016 Apple Inc. All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
9 #     * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 #     * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
14 # distribution.
15 #     * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 from __future__ import print_function
32 import logging
33 import optparse
34 import os
35 import sys
36 import traceback
37
38 from webkitpy.common.host import Host
39 from webkitpy.layout_tests.controllers.manager import Manager
40 from webkitpy.layout_tests.models.test_run_results import INTERRUPTED_EXIT_STATUS
41 from webkitpy.port import configuration_options, platform_options
42 from webkitpy.layout_tests.views import buildbot_results
43 from webkitpy.layout_tests.views import printing
44
45
46 _log = logging.getLogger(__name__)
47
48
49 # This is a randomly chosen exit code that can be tested against to
50 # indicate that an unexpected exception occurred.
51 EXCEPTIONAL_EXIT_STATUS = 254
52
53
54 def main(argv, stdout, stderr):
55     options, args = parse_args(argv)
56
57     if options.platform and 'test' in options.platform:
58         # It's a bit lame to import mocks into real code, but this allows the user
59         # to run tests against the test platform interactively, which is useful for
60         # debugging test failures.
61         from webkitpy.common.host_mock import MockHost
62         host = MockHost()
63     else:
64         host = Host()
65
66     if options.lint_test_files:
67         from webkitpy.layout_tests.lint_test_expectations import lint
68         return lint(host, options, stderr)
69
70     try:
71         port = host.port_factory.get(options.platform, options)
72     except NotImplementedError as e:
73         # FIXME: is this the best way to handle unsupported port names?
74         print(str(e), file=stderr)
75         return EXCEPTIONAL_EXIT_STATUS
76
77     if options.print_expectations:
78         return _print_expectations(port, options, args, stderr)
79
80     try:
81         # Force all tests to use a smaller stack so that stack overflow tests can run faster.
82         stackSizeInBytes = int(1.5 * 1024 * 1024)
83         options.additional_env_var.append('JSC_maxPerThreadStackUsage=' + str(stackSizeInBytes))
84         options.additional_env_var.append('__XPC_JSC_maxPerThreadStackUsage=' + str(stackSizeInBytes))
85         run_details = run(port, options, args, stderr)
86         if run_details.exit_code != -1 and not run_details.initial_results.keyboard_interrupted:
87             bot_printer = buildbot_results.BuildBotPrinter(stdout, options.debug_rwt_logging)
88             bot_printer.print_results(run_details)
89
90         return run_details.exit_code
91     # We still need to handle KeyboardInterrupt, at least for webkitpy unittest cases.
92     except KeyboardInterrupt:
93         return INTERRUPTED_EXIT_STATUS
94     except BaseException as e:
95         if isinstance(e, Exception):
96             print('\n%s raised: %s' % (e.__class__.__name__, str(e)), file=stderr)
97             traceback.print_exc(file=stderr)
98         return EXCEPTIONAL_EXIT_STATUS
99
100
101 def parse_args(args):
102     option_group_definitions = []
103
104     option_group_definitions.append(("Platform options", platform_options()))
105     option_group_definitions.append(("Configuration options", configuration_options()))
106     option_group_definitions.append(("Printing Options", printing.print_options()))
107
108     option_group_definitions.append(("Feature Switches", [
109         optparse.make_option("--complex-text", action="store_true", default=False,
110             help="Use the complex text code path for all text (OS X and Windows only)"),
111         optparse.make_option("--accelerated-drawing", action="store_true", default=False,
112             help="Use accelerated drawing (OS X only)"),
113         optparse.make_option("--remote-layer-tree", action="store_true", default=False,
114             help="Use the remote layer tree drawing model (OS X WebKit2 only)"),
115     ]))
116
117     option_group_definitions.append(("WebKit Options", [
118         optparse.make_option("--gc-between-tests", action="store_true", default=False,
119             help="Force garbage collection between each test"),
120         optparse.make_option("-l", "--leaks", action="store_true", default=False,
121             help="Enable leaks checking (OS X and Gtk+ only)"),
122         optparse.make_option("-g", "--guard-malloc", action="store_true", default=False,
123             help="Enable Guard Malloc (OS X only)"),
124         optparse.make_option("--threaded", action="store_true", default=False,
125             help="Run a concurrent JavaScript thread with each test"),
126         optparse.make_option("--dump-render-tree", "-1", action="store_false", default=True, dest="webkit_test_runner",
127             help="Use DumpRenderTree rather than WebKitTestRunner."),
128         # FIXME: We should merge this w/ --build-directory and only have one flag.
129         optparse.make_option("--root", action="store",
130             help="Path to a directory containing the executables needed to run tests."),
131     ]))
132
133     option_group_definitions.append(("Results Options", [
134         optparse.make_option("-p", "--pixel", "--pixel-tests", action="store_true",
135             dest="pixel_tests", help="Enable pixel-to-pixel PNG comparisons"),
136         optparse.make_option("--no-pixel", "--no-pixel-tests", action="store_false",
137             dest="pixel_tests", help="Disable pixel-to-pixel PNG comparisons"),
138         optparse.make_option("--no-sample-on-timeout", action="store_false", default=True,
139             dest="sample_on_timeout", help="Don't run sample on timeout (OS X only)"),
140         optparse.make_option("--no-ref-tests", action="store_true",
141             dest="no_ref_tests", help="Skip all ref tests"),
142         optparse.make_option("--tolerance",
143             help="Ignore image differences less than this percentage (some "
144                 "ports may ignore this option)", type="float"),
145         optparse.make_option("--results-directory", help="Location of test results"),
146         optparse.make_option("--build-directory",
147             help="Path to the directory under which build files are kept (should not include configuration)"),
148         optparse.make_option("--add-platform-exceptions", action="store_true", default=False,
149             help="Save generated results into the *most-specific-platform* directory rather than the *generic-platform* directory"),
150         optparse.make_option("--new-baseline", action="store_true",
151             default=False, help="Save generated results as new baselines "
152                  "into the *most-specific-platform* directory, overwriting whatever's "
153                  "already there. Equivalent to --reset-results --add-platform-exceptions"),
154         optparse.make_option("--reset-results", action="store_true",
155             default=False, help="Reset expectations to the "
156                  "generated results in their existing location."),
157         optparse.make_option("--no-new-test-results", action="store_false",
158             dest="new_test_results", default=True,
159             help="Don't create new baselines when no expected results exist"),
160         optparse.make_option("--treat-ref-tests-as-pixel-tests", action="store_true", default=False,
161             help="Run ref tests, but treat them as if they were traditional pixel tests"),
162
163         #FIXME: we should support a comma separated list with --pixel-test-directory as well.
164         optparse.make_option("--pixel-test-directory", action="append", default=[], dest="pixel_test_directories",
165             help="A directory where it is allowed to execute tests as pixel tests. "
166                  "Specify multiple times to add multiple directories. "
167                  "This option implies --pixel-tests. If specified, only those tests "
168                  "will be executed as pixel tests that are located in one of the "
169                  "directories enumerated with the option. Some ports may ignore this "
170                  "option while others can have a default value that can be overridden here."),
171
172         optparse.make_option("--skip-failing-tests", action="store_true",
173             default=False, help="Skip tests that are expected to fail. "
174                  "Note: When using this option, you might miss new crashes "
175                  "in these tests."),
176         optparse.make_option("--additional-drt-flag", action="append",
177             default=[], help="Additional command line flag to pass to DumpRenderTree "
178                  "Specify multiple times to add multiple flags."),
179         optparse.make_option("--driver-name", type="string",
180             help="Alternative DumpRenderTree binary to use"),
181         optparse.make_option("--additional-platform-directory", action="append",
182             default=[], help="Additional directory where to look for test "
183                  "baselines (will take precendence over platform baselines). "
184                  "Specify multiple times to add multiple search path entries."),
185         optparse.make_option("--additional-expectations", action="append", default=[],
186             help="Path to a test_expectations file that will override previous expectations. "
187                  "Specify multiple times for multiple sets of overrides."),
188         optparse.make_option("--compare-port", action="store", default=None,
189             help="Use the specified port's baselines first"),
190         optparse.make_option("--no-show-results", action="store_false",
191             default=True, dest="show_results",
192             help="Don't launch a browser with results after the tests "
193                  "are done"),
194         optparse.make_option("--full-results-html", action="store_true",
195             default=False,
196             help="Show all failures in results.html, rather than only regressions"),
197         optparse.make_option("--clobber-old-results", action="store_true",
198             default=False, help="Clobbers test results from previous runs."),
199         optparse.make_option("--http", action="store_true", dest="http",
200             default=True, help="Run HTTP and WebSocket tests (default)"),
201         optparse.make_option("--no-http", action="store_false", dest="http",
202             help="Don't run HTTP and WebSocket tests"),
203         optparse.make_option("--no-http-servers", action="store_false", dest="start_http_servers_if_needed",
204             default=True, help="Don't start HTTP servers"),
205         optparse.make_option("--ignore-metrics", action="store_true", dest="ignore_metrics",
206             default=False, help="Ignore rendering metrics related information from test "
207             "output, only compare the structure of the rendertree."),
208         optparse.make_option("--nocheck-sys-deps", action="store_true",
209             default=False,
210             help="Don't check the system dependencies (themes)"),
211         optparse.make_option("--java", action="store_true",
212             default=False,
213             help="Build java support files"),
214         optparse.make_option("--layout-tests-directory", action="store", default=None,
215             help="Override the default layout test directory.", dest="layout_tests_dir")
216     ]))
217
218     option_group_definitions.append(("Testing Options", [
219         optparse.make_option("--build", dest="build",
220             action="store_true", default=True,
221             help="Check to ensure the DumpRenderTree build is up-to-date "
222                  "(default)."),
223         optparse.make_option("--no-build", dest="build",
224             action="store_false", help="Don't check to see if the "
225                                        "DumpRenderTree build is up-to-date."),
226         optparse.make_option("-n", "--dry-run", action="store_true",
227             default=False,
228             help="Do everything but actually run the tests or upload results."),
229         optparse.make_option("--wrapper",
230             help="wrapper command to insert before invocations of "
231                  "DumpRenderTree or WebKitTestRunner; option is split on whitespace before "
232                  "running. (Example: --wrapper='valgrind --smc-check=all')"),
233         optparse.make_option("-i", "--ignore-tests", action="append", default=[],
234             help="directories or test to ignore (may specify multiple times)"),
235         optparse.make_option("--test-list", action="append",
236             help="read list of tests to run from file", metavar="FILE"),
237         optparse.make_option("--skipped", action="store", default="default",
238             help=("control how tests marked SKIP are run. "
239                  "'default' == Skip tests unless explicitly listed on the command line, "
240                  "'ignore' == Run them anyway, "
241                  "'only' == only run the SKIP tests, "
242                  "'always' == always skip, even if listed on the command line.")),
243         optparse.make_option("--force", action="store_true", default=False,
244             help="Run all tests with PASS as expected result, even those marked SKIP in the test list (implies --skipped=ignore)"),
245         optparse.make_option("--time-out-ms",
246             help="Set the timeout for each test"),
247         optparse.make_option("--order", action="store", default="natural",
248             help=("determine the order in which the test cases will be run. "
249                   "'none' == use the order in which the tests were listed either in arguments or test list, "
250                   "'natural' == use the natural order (default), "
251                   "'random' == randomize the test order.")),
252         optparse.make_option("--run-chunk",
253             help=("Run a specified chunk (n:l), the nth of len l, "
254                  "of the layout tests")),
255         optparse.make_option("--run-part", help=("Run a specified part (n:m), "
256                   "the nth of m parts, of the layout tests")),
257         optparse.make_option("--batch-size",
258             help=("Run a the tests in batches (n), after every n tests, "
259                   "DumpRenderTree is relaunched."), type="int", default=None),
260         optparse.make_option("--run-singly", action="store_true",
261             default=False, help="run a separate DumpRenderTree for each test (implies --verbose)"),
262         optparse.make_option("--child-processes",
263             help="Number of DumpRenderTrees to run in parallel."),
264         # FIXME: Display default number of child processes that will run.
265         optparse.make_option("-f", "--fully-parallel", action="store_true",
266             help="run all tests in parallel"),
267         optparse.make_option("--exit-after-n-failures", type="int", default=None,
268             help="Exit after the first N failures instead of running all "
269             "tests"),
270         optparse.make_option("--exit-after-n-crashes-or-timeouts", type="int",
271             default=None, help="Exit after the first N crashes instead of "
272             "running all tests"),
273         optparse.make_option("--iterations", type="int", default=1, help="Number of times to run the set of tests (e.g. ABCABCABC)"),
274         optparse.make_option("--repeat-each", type="int", default=1, help="Number of times to run each test (e.g. AAABBBCCC)"),
275         optparse.make_option("--retry-failures", action="store_true",
276             default=True,
277             help="Re-try any tests that produce unexpected results (default)"),
278         optparse.make_option("--no-retry-failures", action="store_false",
279             dest="retry_failures",
280             help="Don't re-try any tests that produce unexpected results."),
281         optparse.make_option("--max-locked-shards", type="int", default=0,
282             help="Set the maximum number of locked shards"),
283         optparse.make_option("--additional-env-var", type="string", action="append", default=[],
284             help="Passes that environment variable to the tests (--additional-env-var=NAME=VALUE)"),
285         optparse.make_option("--profile", action="store_true",
286             help="Output per-test profile information."),
287         optparse.make_option("--profiler", action="store",
288             help="Output per-test profile information, using the specified profiler."),
289         optparse.make_option("--no-timeout", action="store_true", default=False, help="Disable test timeouts"),
290         optparse.make_option('--display-server', choices=['xvfb', 'xorg', 'weston', 'wayland'], default='xvfb',
291             help='"xvfb": Use a virtualized X11 server. "xorg": Use the current X11 session. '
292                  '"weston": Use a virtualized Weston server. "wayland": Use the current wayland session.'),
293     ]))
294
295     option_group_definitions.append(("iOS Options", [
296         optparse.make_option('--no-install', action='store_const', const=False, default=True, dest='install',
297             help='Skip install step for device and simulator testing'),
298         optparse.make_option('--version', help='Specify the version of iOS to be used. By default, this will adopt the runtime for iOS Simulator.'),
299         optparse.make_option('--device-type', help='iOS Simulator device type identifier (default: i386 -> iPhone 5, x86_64 -> iPhone 5s)'),
300         optparse.make_option('--dedicated-simulators', action="store_true", default=False,
301             help="If set, dedicated iOS simulators will always be created.  If not set, the script will attempt to use any currently running simulator."),
302         optparse.make_option('--show-touches', action="store_true", default=False, help="If set, a small dot will be shown where the generated touches are. Helpful for debugging touch tests."),
303     ]))
304
305     option_group_definitions.append(("Miscellaneous Options", [
306         optparse.make_option("--lint-test-files", action="store_true",
307         default=False, help=("Makes sure the test files parse for all "
308                             "configurations. Does not run any tests.")),
309         optparse.make_option("--print-expectations", action="store_true",
310         default=False, help=("Print the expected outcome for the given test, or all tests listed in TestExpectations. "
311                             "Does not run any tests.")),
312     ]))
313
314     option_group_definitions.append(("Web Platform Test Server Options", [
315         optparse.make_option("--wptserver-doc-root", type="string", help=("Set web platform server document root, relative to LayoutTests directory")),
316     ]))
317
318     # FIXME: Move these into json_results_generator.py
319     option_group_definitions.append(("Result JSON Options", [
320         optparse.make_option("--master-name", help="The name of the buildbot master."),
321         optparse.make_option("--builder-name", default="",
322             help=("The name of the builder shown on the waterfall running this script. e.g. Apple MountainLion Release WK2 (Tests).")),
323         optparse.make_option("--build-name", default="DUMMY_BUILD_NAME",
324             help=("The name of the builder used in its path, e.g. webkit-rel.")),
325         optparse.make_option("--build-slave", default="DUMMY_BUILD_SLAVE",
326             help=("The name of the buildslave used. e.g. apple-macpro-6.")),
327         optparse.make_option("--build-number", default="DUMMY_BUILD_NUMBER",
328             help=("The build number of the builder running this script.")),
329         optparse.make_option("--test-results-server", action="append", default=[],
330             help=("If specified, upload results json files to this appengine server.")),
331         optparse.make_option("--results-server-host", action="append", default=[],
332             help=("If specified, upload results JSON file to this results server.")),
333         optparse.make_option("--additional-repository-name",
334             help=("The name of an additional subversion or git checkout")),
335         optparse.make_option("--additional-repository-path",
336             help=("The path to an additional subversion or git checkout (requires --additional-repository-name)")),
337         optparse.make_option("--allowed-host", type="string", action="append", default=[],
338             help=("If specified, tests are allowed to make requests to the specified hostname."))
339     ]))
340
341     option_parser = optparse.OptionParser(usage="%prog [options] [<path>...]")
342
343     for group_name, group_options in option_group_definitions:
344         option_group = optparse.OptionGroup(option_parser, group_name)
345         option_group.add_options(group_options)
346         option_parser.add_option_group(option_group)
347
348     return option_parser.parse_args(args)
349
350
351 def _print_expectations(port, options, args, logging_stream):
352     logger = logging.getLogger()
353     logger.setLevel(logging.DEBUG if options.debug_rwt_logging else logging.INFO)
354     try:
355         printer = printing.Printer(port, options, logging_stream, logger=logger)
356
357         _set_up_derived_options(port, options)
358         manager = Manager(port, options, printer)
359
360         exit_code = manager.print_expectations(args)
361         _log.debug("Printing expectations completed, Exit status: %d", exit_code)
362         return exit_code
363     except Exception as error:
364         _log.error('Error printing expectations: {}'.format(error))
365     finally:
366         printer.cleanup()
367         return -1
368
369
370 def _set_up_derived_options(port, options):
371     """Sets the options values that depend on other options values."""
372     if not options.child_processes:
373         options.child_processes = os.environ.get("WEBKIT_TEST_CHILD_PROCESSES",
374                                                  str(port.default_child_processes()))
375
376     if not options.configuration:
377         options.configuration = port.default_configuration()
378
379     if options.pixel_tests is None:
380         options.pixel_tests = port.default_pixel_tests()
381
382     if not options.time_out_ms:
383         options.time_out_ms = str(port.default_timeout_ms())
384
385     options.slow_time_out_ms = str(5 * int(options.time_out_ms))
386
387     if options.additional_platform_directory:
388         additional_platform_directories = []
389         for path in options.additional_platform_directory:
390             additional_platform_directories.append(port.host.filesystem.abspath(path))
391         options.additional_platform_directory = additional_platform_directories
392
393     if options.force:
394         if options.skipped not in ('ignore', 'default'):
395             _log.warning("--force overrides --skipped=%s" % (options.skipped))
396         options.skipped = 'ignore'
397
398     if not options.http and options.skipped in ('ignore', 'only'):
399         _log.warning("--force/--skipped=%s overrides --no-http." % (options.skipped))
400         options.http = True
401
402     if options.ignore_metrics and (options.new_baseline or options.reset_results):
403         _log.warning("--ignore-metrics has no effect with --new-baselines or with --reset-results")
404
405     if options.new_baseline:
406         options.reset_results = True
407         options.add_platform_exceptions = True
408
409     if options.pixel_test_directories:
410         options.pixel_tests = True
411         varified_dirs = set()
412         pixel_test_directories = options.pixel_test_directories
413         for directory in pixel_test_directories:
414             # FIXME: we should support specifying the directories all the ways we support it for additional
415             # arguments specifying which tests and directories to run. We should also move the logic for that
416             # to Port.
417             filesystem = port.host.filesystem
418             if not filesystem.isdir(filesystem.join(port.layout_tests_dir(), directory)):
419                 _log.warning("'%s' was passed to --pixel-test-directories, which doesn't seem to be a directory" % str(directory))
420             else:
421                 varified_dirs.add(directory)
422
423         options.pixel_test_directories = list(varified_dirs)
424
425     if options.run_singly:
426         options.verbose = True
427
428     # The GTK+ and WPE ports only support WebKit2 so they always use WKTR.
429     if options.platform in ["gtk", "wpe"]:
430         options.webkit_test_runner = True
431
432     if options.leaks:
433         options.additional_env_var.append("JSC_usePoisoning=0")
434         options.additional_env_var.append("__XPC_JSC_usePoisoning=0")
435
436 def run(port, options, args, logging_stream):
437     logger = logging.getLogger()
438     logger.setLevel(logging.DEBUG if options.debug_rwt_logging else logging.INFO)
439
440     try:
441         printer = printing.Printer(port, options, logging_stream, logger=logger)
442
443         _set_up_derived_options(port, options)
444         manager = Manager(port, options, printer)
445         printer.print_config(port.results_directory())
446
447         run_details = manager.run(args)
448         _log.debug("Testing completed, Exit status: %d" % run_details.exit_code)
449         return run_details
450     finally:
451         printer.cleanup()
452
453 if __name__ == '__main__':
454     sys.exit(main(sys.argv[1:], sys.stdout, sys.stderr))