| # Copyright (c) 2009 Google Inc. All rights reserved. |
| # Copyright (c) 2009 Apple Inc. All rights reserved. |
| # Copyright (c) 2012 Intel Corporation. All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are |
| # met: |
| # |
| # * Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # * Redistributions in binary form must reproduce the above |
| # copyright notice, this list of conditions and the following disclaimer |
| # in the documentation and/or other materials provided with the |
| # distribution. |
| # * Neither the name of Google Inc. nor the names of its |
| # contributors may be used to endorse or promote products derived from |
| # this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| import fnmatch |
| import re |
| |
| from optparse import make_option |
| |
| from webkitpy.common.system.crash_logs import CrashLogs |
| from webkitpy.tool.commands.command import Command |
| from webkitpy.layout_tests.models.test_expectations import TestExpectations |
| from webkitpy.layout_tests.port.factory import platform_options |
| |
| |
| class CrashLog(Command): |
| name = 'crash-log' |
| help_text = 'Print the newest crash log for the given process' |
| show_in_main_help = True |
| long_help = """Finds the newest crash log matching the given process name |
| and PID and prints it to stdout.""" |
| argument_names = 'PROCESS_NAME [PID]' |
| |
| def execute(self, options, args, tool): |
| crash_logs = CrashLogs(tool) |
| pid = None |
| if len(args) > 1: |
| pid = int(args[1]) |
| print crash_logs.find_newest_log(args[0], pid) |
| |
| |
| class PrintExpectations(Command): |
| name = 'print-expectations' |
| help_text = 'Print the expected result for the given test(s) on the given port(s)' |
| show_in_main_help = True |
| |
| def __init__(self): |
| options = [ |
| make_option('--all', action='store_true', default=False, |
| help='display the expectations for *all* tests'), |
| make_option('-x', '--exclude-keyword', action='append', default=[], |
| help='limit to tests not matching the given keyword (for example, ' |
| '"skip", "slow", or "crash". May specify multiple times'), |
| make_option('-i', '--include-keyword', action='append', default=[], |
| help='limit to tests with the given keyword (for example, "skip", ' |
| '"slow", or "crash". May specify multiple times'), |
| make_option('--csv', action='store_true', default=False, |
| help='Print a CSV-style report that includes the port name, bugs, ' |
| 'specifiers, tests, and expectations'), |
| make_option('-f', '--full', action='store_true', default=False, |
| help='Print a full TestExpectations-style line for every match'), |
| make_option('--paths', action='store_true', default=False, |
| help='display the paths for all applicable expectation files'), |
| ] + platform_options(use_globs=True) |
| |
| super(PrintExpectations, self).__init__(options=options) |
| self._expectation_models = {} |
| |
| def execute(self, options, args, tool): |
| if not options.paths and not args and not options.all: |
| print 'You must either specify one or more test paths or --all.' |
| return |
| |
| if options.platform: |
| port_names = fnmatch.filter(tool.port_factory.all_port_names(), options.platform) |
| if not port_names: |
| default_port = tool.port_factory.get(options.platform) |
| if default_port: |
| port_names = [default_port.name()] |
| else: |
| print "No port names match '%s'" % options.platform |
| return |
| else: |
| default_port = tool.port_factory.get(port_names[0]) |
| else: |
| default_port = tool.port_factory.get(options=options) |
| port_names = [default_port.name()] |
| |
| if options.paths: |
| files = default_port.expectations_files() |
| layout_tests_dir = default_port.layout_tests_dir() |
| for file in files: |
| if file.startswith(layout_tests_dir): |
| file = file.replace(layout_tests_dir, 'LayoutTests') |
| print file |
| return |
| |
| tests = set(default_port.tests(args)) |
| for port_name in port_names: |
| port = tool.port_factory.get(port_name, options) |
| model = TestExpectations(port, tests).model() |
| tests_to_print = self._filter_tests(options, model, tests) |
| lines = [model.get_expectation_line(test) for test in sorted(tests_to_print)] |
| if port_name != port_names[0]: |
| print |
| print '\n'.join(self._format_lines(options, port_name, lines)) |
| |
| def _filter_tests(self, options, model, tests): |
| filtered_tests = set() |
| if options.include_keyword: |
| for keyword in options.include_keyword: |
| filtered_tests.update(model.get_test_set_for_keyword(keyword)) |
| else: |
| filtered_tests = tests |
| |
| for keyword in options.exclude_keyword: |
| filtered_tests.difference_update(model.get_test_set_for_keyword(keyword)) |
| return filtered_tests |
| |
| def _format_lines(self, options, port_name, lines): |
| output = [] |
| if options.csv: |
| for line in lines: |
| output.append('%s,%s' % (port_name, line.to_csv())) |
| elif lines: |
| include_modifiers = options.full |
| include_expectations = options.full or len(options.include_keyword) != 1 or len(options.exclude_keyword) |
| output.append('// For %s' % port_name) |
| for line in lines: |
| output.append('%s' % line.to_string(None, include_modifiers, include_expectations, include_comment=False)) |
| return output |
| |
| |
| class PrintBaselines(Command): |
| name = 'print-baselines' |
| help_text = 'Prints the baseline locations for given test(s) on the given port(s)' |
| show_in_main_help = True |
| |
| def __init__(self): |
| options = [ |
| make_option('--all', action='store_true', default=False, |
| help='display the baselines for *all* tests'), |
| make_option('--csv', action='store_true', default=False, |
| help='Print a CSV-style report that includes the port name, test_name, ' |
| 'test platform, baseline type, baseline location, and baseline platform'), |
| make_option('--include-virtual-tests', action='store_true', |
| help='Include virtual tests'), |
| ] + platform_options(use_globs=True) |
| super(PrintBaselines, self).__init__(options=options) |
| self._platform_regexp = re.compile(r'platform/([^\/]+)/(.+)') |
| |
| def execute(self, options, args, tool): |
| if not args and not options.all: |
| print 'You must either specify one or more test paths or --all.' |
| return |
| |
| default_port = tool.port_factory.get() |
| if options.platform: |
| port_names = fnmatch.filter(tool.port_factory.all_port_names(), options.platform) |
| if not port_names: |
| print "No port names match '%s'" % options.platform |
| else: |
| port_names = [default_port.name()] |
| |
| if options.include_virtual_tests: |
| tests = sorted(default_port.tests(args)) |
| else: |
| tests = sorted(default_port.real_tests(args)) |
| |
| for port_name in port_names: |
| if port_name != port_names[0]: |
| print |
| if not options.csv: |
| print '// For %s' % port_name |
| port = tool.port_factory.get(port_name) |
| for test_name in tests: |
| self._print_baselines(options, port_name, test_name, port.expected_baselines_by_extension(test_name)) |
| |
| def _print_baselines(self, options, port_name, test_name, baselines): |
| for extension in sorted(baselines.keys()): |
| baseline_location = baselines[extension] |
| if baseline_location: |
| if options.csv: |
| print '%s,%s,%s,%s,%s,%s' % (port_name, test_name, self._platform_for_path(test_name), |
| extension[1:], baseline_location, self._platform_for_path(baseline_location)) |
| else: |
| print baseline_location |
| |
| def _platform_for_path(self, relpath): |
| platform_matchobj = self._platform_regexp.match(relpath) |
| if platform_matchobj: |
| return platform_matchobj.group(1) |
| return None |