OLD | NEW |
| (Empty) |
1 # Copyright (c) 2009 Google Inc. All rights reserved. | |
2 # Copyright (c) 2009 Apple Inc. All rights reserved. | |
3 # Copyright (c) 2012 Intel Corporation. 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 import fnmatch | |
32 import logging | |
33 import re | |
34 | |
35 from optparse import make_option | |
36 | |
37 from webkitpy.common.system.crashlogs import CrashLogs | |
38 from webkitpy.tool.multicommandtool import AbstractDeclarativeCommand | |
39 from webkitpy.layout_tests.models.test_expectations import TestExpectations | |
40 from webkitpy.layout_tests.port import platform_options | |
41 | |
42 _log = logging.getLogger(__name__) | |
43 | |
44 | |
45 class CrashLog(AbstractDeclarativeCommand): | |
46 name = "crash-log" | |
47 help_text = "Print the newest crash log for the given process" | |
48 show_in_main_help = True | |
49 long_help = """Finds the newest crash log matching the given process name | |
50 and PID and prints it to stdout.""" | |
51 argument_names = "PROCESS_NAME [PID]" | |
52 | |
53 def execute(self, options, args, tool): | |
54 crash_logs = CrashLogs(tool) | |
55 pid = None | |
56 if len(args) > 1: | |
57 pid = int(args[1]) | |
58 print crash_logs.find_newest_log(args[0], pid) | |
59 | |
60 | |
61 class PrintExpectations(AbstractDeclarativeCommand): | |
62 name = 'print-expectations' | |
63 help_text = 'Print the expected result for the given test(s) on the given po
rt(s)' | |
64 show_in_main_help = True | |
65 | |
66 def __init__(self): | |
67 options = [ | |
68 make_option('--all', action='store_true', default=False, | |
69 help='display the expectations for *all* tests'), | |
70 make_option('-x', '--exclude-keyword', action='append', default=[], | |
71 help='limit to tests not matching the given keyword (for
example, "skip", "slow", or "crash". May specify multiple times'), | |
72 make_option('-i', '--include-keyword', action='append', default=[], | |
73 help='limit to tests with the given keyword (for example
, "skip", "slow", or "crash". May specify multiple times'), | |
74 make_option('--csv', action='store_true', default=False, | |
75 help='Print a CSV-style report that includes the port na
me, bugs, specifiers, tests, and expectations'), | |
76 make_option('-f', '--full', action='store_true', default=False, | |
77 help='Print a full TestExpectations-style line for every
match'), | |
78 make_option('--paths', action='store_true', default=False, | |
79 help='display the paths for all applicable expectation f
iles'), | |
80 ] + platform_options(use_globs=True) | |
81 | |
82 AbstractDeclarativeCommand.__init__(self, options=options) | |
83 self._expectation_models = {} | |
84 | |
85 def execute(self, options, args, tool): | |
86 if not options.paths and not args and not options.all: | |
87 print "You must either specify one or more test paths or --all." | |
88 return | |
89 | |
90 if options.platform: | |
91 port_names = fnmatch.filter(tool.port_factory.all_port_names(), opti
ons.platform) | |
92 if not port_names: | |
93 default_port = tool.port_factory.get(options.platform) | |
94 if default_port: | |
95 port_names = [default_port.name()] | |
96 else: | |
97 print "No port names match '%s'" % options.platform | |
98 return | |
99 else: | |
100 default_port = tool.port_factory.get(port_names[0]) | |
101 else: | |
102 default_port = tool.port_factory.get(options=options) | |
103 port_names = [default_port.name()] | |
104 | |
105 if options.paths: | |
106 files = default_port.expectations_files() | |
107 layout_tests_dir = default_port.layout_tests_dir() | |
108 for file in files: | |
109 if file.startswith(layout_tests_dir): | |
110 file = file.replace(layout_tests_dir, 'tests') | |
111 print file | |
112 return | |
113 | |
114 tests = set(default_port.tests(args)) | |
115 for port_name in port_names: | |
116 model = self._model(options, port_name, tests) | |
117 tests_to_print = self._filter_tests(options, model, tests) | |
118 lines = [model.get_expectation_line(test) for test in sorted(tests_t
o_print)] | |
119 if port_name != port_names[0]: | |
120 print | |
121 print '\n'.join(self._format_lines(options, port_name, lines)) | |
122 | |
123 def _filter_tests(self, options, model, tests): | |
124 filtered_tests = set() | |
125 if options.include_keyword: | |
126 for keyword in options.include_keyword: | |
127 filtered_tests.update(model.get_test_set_for_keyword(keyword)) | |
128 else: | |
129 filtered_tests = tests | |
130 | |
131 for keyword in options.exclude_keyword: | |
132 filtered_tests.difference_update(model.get_test_set_for_keyword(keyw
ord)) | |
133 return filtered_tests | |
134 | |
135 def _format_lines(self, options, port_name, lines): | |
136 output = [] | |
137 if options.csv: | |
138 for line in lines: | |
139 output.append("%s,%s" % (port_name, line.to_csv())) | |
140 elif lines: | |
141 include_modifiers = options.full | |
142 include_expectations = options.full or len(options.include_keyword)
!= 1 or len(options.exclude_keyword) | |
143 output.append("// For %s" % port_name) | |
144 for line in lines: | |
145 output.append("%s" % line.to_string(None, include_modifiers, inc
lude_expectations, include_comment=False)) | |
146 return output | |
147 | |
148 def _model(self, options, port_name, tests): | |
149 port = self._tool.port_factory.get(port_name, options) | |
150 return TestExpectations(port, tests).model() | |
151 | |
152 | |
153 class PrintBaselines(AbstractDeclarativeCommand): | |
154 name = 'print-baselines' | |
155 help_text = 'Prints the baseline locations for given test(s) on the given po
rt(s)' | |
156 show_in_main_help = True | |
157 | |
158 def __init__(self): | |
159 options = [ | |
160 make_option('--all', action='store_true', default=False, | |
161 help='display the baselines for *all* tests'), | |
162 make_option('--csv', action='store_true', default=False, | |
163 help='Print a CSV-style report that includes the port na
me, test_name, test platform, baseline type, baseline location, and baseline pla
tform'), | |
164 make_option('--include-virtual-tests', action='store_true', | |
165 help='Include virtual tests'), | |
166 ] + platform_options(use_globs=True) | |
167 AbstractDeclarativeCommand.__init__(self, options=options) | |
168 self._platform_regexp = re.compile('platform/([^\/]+)/(.+)') | |
169 | |
170 def execute(self, options, args, tool): | |
171 if not args and not options.all: | |
172 print "You must either specify one or more test paths or --all." | |
173 return | |
174 | |
175 default_port = tool.port_factory.get() | |
176 if options.platform: | |
177 port_names = fnmatch.filter(tool.port_factory.all_port_names(), opti
ons.platform) | |
178 if not port_names: | |
179 print "No port names match '%s'" % options.platform | |
180 else: | |
181 port_names = [default_port.name()] | |
182 | |
183 if options.include_virtual_tests: | |
184 tests = sorted(default_port.tests(args)) | |
185 else: | |
186 # FIXME: make real_tests() a public method. | |
187 tests = sorted(default_port._real_tests(args)) | |
188 | |
189 for port_name in port_names: | |
190 if port_name != port_names[0]: | |
191 print | |
192 if not options.csv: | |
193 print "// For %s" % port_name | |
194 port = tool.port_factory.get(port_name) | |
195 for test_name in tests: | |
196 self._print_baselines(options, port_name, test_name, port.expect
ed_baselines_by_extension(test_name)) | |
197 | |
198 def _print_baselines(self, options, port_name, test_name, baselines): | |
199 for extension in sorted(baselines.keys()): | |
200 baseline_location = baselines[extension] | |
201 if baseline_location: | |
202 if options.csv: | |
203 print "%s,%s,%s,%s,%s,%s" % (port_name, test_name, self._pla
tform_for_path(test_name), | |
204 extension[1:], baseline_locatio
n, self._platform_for_path(baseline_location)) | |
205 else: | |
206 print baseline_location | |
207 | |
208 def _platform_for_path(self, relpath): | |
209 platform_matchobj = self._platform_regexp.match(relpath) | |
210 if platform_matchobj: | |
211 return platform_matchobj.group(1) | |
212 return None | |
OLD | NEW |