|  | # 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 |