OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 ''' | 3 ''' |
4 Copyright 2012 Google Inc. | 4 Copyright 2012 Google Inc. |
5 | 5 |
6 Use of this source code is governed by a BSD-style license that can be | 6 Use of this source code is governed by a BSD-style license that can be |
7 found in the LICENSE file. | 7 found in the LICENSE file. |
8 ''' | 8 ''' |
9 | 9 |
10 ''' | 10 ''' |
11 Rebaselines the given GM tests, on all bots and all configurations. | 11 Rebaselines the given GM tests, on all bots and all configurations. |
12 Must be run from the gm-expected directory. If run from a git or SVN | 12 Must be run from the gm-expected directory. If run from a git or SVN |
13 checkout, the files will be added to the staging area for commit. | 13 checkout, the files will be added to the staging area for commit. |
14 ''' | 14 ''' |
15 | 15 |
16 # System-level imports | 16 # System-level imports |
17 import argparse | 17 import argparse |
18 import os | 18 import os |
19 import subprocess | 19 import subprocess |
20 import sys | 20 import sys |
21 import urllib2 | 21 import urllib2 |
22 | 22 |
23 # Imports from within Skia | 23 # Imports from within Skia |
24 # | 24 # |
25 # Make sure that they are in the PYTHONPATH, but add them at the *end* | 25 # We need to add the 'gm' directory, so that we can import gm_json.py within |
26 # so any that are already in the PYTHONPATH will be preferred. | 26 # that directory. That script allows us to parse the actual-results.json file |
27 # written out by the GM tool. | |
28 # Make sure that the 'gm' dir is in the PYTHONPATH, but add ir at the *end* | |
29 # so any dirs that are already in the PYTHONPATH will be preferred. | |
30 # | |
31 # This assumes that the 'gm' directory has been checked out as a sibling of | |
32 # the 'tools' directory containing this script, which will be the case if | |
33 # 'trunk' was checked out as a single unit. | |
27 GM_DIRECTORY = os.path.realpath( | 34 GM_DIRECTORY = os.path.realpath( |
28 os.path.join(os.path.dirname(os.path.dirname(__file__)), 'gm')) | 35 os.path.join(os.path.dirname(os.path.dirname(__file__)), 'gm')) |
29 if GM_DIRECTORY not in sys.path: | 36 if GM_DIRECTORY not in sys.path: |
30 sys.path.append(GM_DIRECTORY) | 37 sys.path.append(GM_DIRECTORY) |
31 import gm_json | 38 import gm_json |
32 | 39 |
33 | 40 |
34 # Mapping of gm-expectations subdir (under | 41 # Mapping of gm-expectations subdir (under |
35 # https://skia.googlecode.com/svn/gm-expected/ ) | 42 # https://skia.googlecode.com/svn/gm-expected/ ) |
36 # to builder name (see list at http://108.170.217.252:10117/builders ) | 43 # to builder name (see list at http://108.170.217.252:10117/builders ) |
(...skipping 27 matching lines...) Expand all Loading... | |
64 pass | 71 pass |
65 | 72 |
66 class Rebaseliner(object): | 73 class Rebaseliner(object): |
67 | 74 |
68 # params: | 75 # params: |
69 # json_base_url: base URL from which to read json_filename | 76 # json_base_url: base URL from which to read json_filename |
70 # json_filename: filename (under json_base_url) from which to read a | 77 # json_filename: filename (under json_base_url) from which to read a |
71 # summary of results; typically "actual-results.json" | 78 # summary of results; typically "actual-results.json" |
72 # subdirs: which platform subdirectories to rebaseline; if not specified, | 79 # subdirs: which platform subdirectories to rebaseline; if not specified, |
73 # rebaseline all platform subdirectories | 80 # rebaseline all platform subdirectories |
74 # tests: list of tests to rebaseline, or None if we should rebaseline | 81 # tests: list of tests to rebaseline, as a filter applied to |
75 # whatever files the JSON results summary file tells us to | 82 # the list from the JSON file |
76 # configs: which configs to run for each test; this should only be | 83 # configs: which configs to run for each test, as a filter applied to |
77 # specified if the list of tests was also specified (otherwise, | 84 # the list from the JSON file |
78 # the JSON file will give us test names and configs) | |
79 # dry_run: if True, instead of actually downloading files or adding | 85 # dry_run: if True, instead of actually downloading files or adding |
80 # files to checkout, display a list of operations that | 86 # files to checkout, display a list of operations that |
81 # we would normally perform | 87 # we would normally perform |
82 def __init__(self, json_base_url, json_filename, | 88 def __init__(self, json_base_url, json_filename, |
83 subdirs=None, tests=None, configs=None, dry_run=False): | 89 subdirs=None, tests=None, configs=None, dry_run=False): |
84 if configs and not tests: | |
85 raise ValueError('configs should only be specified if tests ' + | |
86 'were specified also') | |
87 self._tests = tests | 90 self._tests = tests |
88 self._configs = configs | 91 self._configs = configs |
89 if not subdirs: | 92 if not subdirs: |
90 self._subdirs = sorted(SUBDIR_MAPPING.keys()) | 93 self._subdirs = sorted(SUBDIR_MAPPING.keys()) |
91 else: | 94 else: |
92 self._subdirs = subdirs | 95 self._subdirs = subdirs |
93 self._json_base_url = json_base_url | 96 self._json_base_url = json_base_url |
94 self._json_filename = json_filename | 97 self._json_filename = json_filename |
95 self._dry_run = dry_run | 98 self._dry_run = dry_run |
96 self._is_svn_checkout = ( | 99 self._is_svn_checkout = ( |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 return files_to_rebaseline | 169 return files_to_rebaseline |
167 | 170 |
168 # Rebaseline a single file. | 171 # Rebaseline a single file. |
169 def _RebaselineOneFile(self, expectations_subdir, builder_name, | 172 def _RebaselineOneFile(self, expectations_subdir, builder_name, |
170 infilename, outfilename): | 173 infilename, outfilename): |
171 print '# ' + infilename | 174 print '# ' + infilename |
172 url = ('http://skia-autogen.googlecode.com/svn/gm-actual/' + | 175 url = ('http://skia-autogen.googlecode.com/svn/gm-actual/' + |
173 expectations_subdir + '/' + builder_name + '/' + | 176 expectations_subdir + '/' + builder_name + '/' + |
174 expectations_subdir + '/' + infilename) | 177 expectations_subdir + '/' + infilename) |
175 | 178 |
176 # Try to download this file, but if that fails, keep going... | 179 # Try to download this file. |
177 # | 180 # |
178 # This not treated as a fatal failure because not all | 181 # If the download fails, this will raise an exception and halt the |
179 # platforms generate all configs (e.g., Android does not | 182 # rebaseline process. Since the JSON results summary told us that |
180 # generate PDF). | 183 # this file needed rebaselining, we ought to be able to download it... |
181 # | 184 self._DownloadFile(source_url=url, dest_filename=outfilename) |
182 # We could tweak the list of configs within this tool to | |
183 # reflect which combinations the bots actually generate, and | |
184 # then fail if any of those expected combinations are | |
185 # missing... but then this tool would become useless every | |
186 # time someone tweaked the configs on the bots without | |
187 # updating this script. | |
188 try: | |
189 self._DownloadFile(source_url=url, dest_filename=outfilename) | |
190 except CommandFailedException: | |
191 print '# Couldn\'t fetch ' + url | |
192 return | |
193 | 185 |
194 # Add this file to version control (if it isn't already). | 186 # Add this file to version control (if it isn't already). |
195 if self._is_svn_checkout: | 187 if self._is_svn_checkout: |
196 cmd = [ 'svn', 'add', '--quiet', outfilename ] | 188 cmd = [ 'svn', 'add', '--quiet', outfilename ] |
197 self._Call(cmd) | 189 self._Call(cmd) |
198 cmd = [ 'svn', 'propset', '--quiet', 'svn:mime-type', 'image/png', | 190 cmd = [ 'svn', 'propset', '--quiet', 'svn:mime-type', 'image/png', |
199 outfilename ]; | 191 outfilename ]; |
200 self._Call(cmd) | 192 self._Call(cmd) |
201 elif self._is_git_checkout: | 193 elif self._is_git_checkout: |
202 cmd = [ 'git', 'add', outfilename ] | 194 cmd = [ 'git', 'add', outfilename ] |
203 self._Call(cmd) | 195 self._Call(cmd) |
204 | 196 |
205 # Rebaseline the given configs for a single test. | |
206 # | |
207 # params: | |
208 # expectations_subdir | |
209 # builder_name | |
210 # test: a single test to rebaseline | |
211 def _RebaselineOneTest(self, expectations_subdir, builder_name, test): | |
212 if self._configs: | |
213 configs = self._configs | |
214 else: | |
215 if (expectations_subdir == 'base-shuttle-win7-intel-angle'): | |
216 configs = [ 'angle', 'anglemsaa16' ] | |
217 else: | |
218 configs = [ '565', '8888', 'gpu', 'pdf', 'mesa', 'msaa16', | |
219 'msaa4' ] | |
220 print '# ' + expectations_subdir + ':' | |
221 for config in configs: | |
222 infilename = test + '_' + config + '.png' | |
223 outfilename = os.path.join(expectations_subdir, infilename); | |
224 self._RebaselineOneFile(expectations_subdir=expectations_subdir, | |
225 builder_name=builder_name, | |
226 infilename=infilename, | |
227 outfilename=outfilename) | |
228 | |
229 # Rebaseline all platforms/tests/types we specified in the constructor. | 197 # Rebaseline all platforms/tests/types we specified in the constructor. |
230 def RebaselineAll(self): | 198 def RebaselineAll(self): |
231 for subdir in self._subdirs: | 199 for subdir in self._subdirs: |
232 if not subdir in SUBDIR_MAPPING.keys(): | 200 if not subdir in SUBDIR_MAPPING.keys(): |
233 raise Exception(('unrecognized platform subdir "%s"; ' + | 201 raise Exception(('unrecognized platform subdir "%s"; ' + |
234 'should be one of %s') % ( | 202 'should be one of %s') % ( |
235 subdir, SUBDIR_MAPPING.keys())) | 203 subdir, SUBDIR_MAPPING.keys())) |
236 builder_name = SUBDIR_MAPPING[subdir] | 204 builder_name = SUBDIR_MAPPING[subdir] |
237 if self._tests: | 205 json_url = '/'.join([self._json_base_url, |
epoger
2013/06/06 18:29:52
Patchset 3 deletes the code path that iterated ove
| |
238 for test in self._tests: | 206 subdir, builder_name, subdir, |
239 self._RebaselineOneTest(expectations_subdir=subdir, | 207 self._json_filename]) |
240 builder_name=builder_name, | 208 filenames = self._GetFilesToRebaseline(json_url=json_url) |
241 test=test) | 209 for filename in filenames: |
242 else: # get the raw list of files that need rebaselining from JSON | 210 outfilename = os.path.join(subdir, filename); |
243 json_url = '/'.join([self._json_base_url, | 211 self._RebaselineOneFile(expectations_subdir=subdir, |
244 subdir, builder_name, subdir, | 212 builder_name=builder_name, |
245 self._json_filename]) | 213 infilename=filename, |
246 filenames = self._GetFilesToRebaseline(json_url=json_url) | 214 outfilename=outfilename) |
247 for filename in filenames: | |
248 outfilename = os.path.join(subdir, filename); | |
249 self._RebaselineOneFile(expectations_subdir=subdir, | |
250 builder_name=builder_name, | |
251 infilename=filename, | |
252 outfilename=outfilename) | |
253 | 215 |
254 # main... | 216 # main... |
255 | 217 |
256 parser = argparse.ArgumentParser() | 218 parser = argparse.ArgumentParser() |
257 parser.add_argument('--configs', metavar='CONFIG', nargs='+', | 219 parser.add_argument('--configs', metavar='CONFIG', nargs='+', |
258 help='which configurations to rebaseline, e.g. ' + | 220 help='which configurations to rebaseline, e.g. ' + |
259 '"--configs 565 8888"; if unspecified, run a default ' + | 221 '"--configs 565 8888", as a filter over the configs ' + |
260 'set of configs. This should ONLY be specified if ' + | 222 'which JSON_FILENAME tells us need rebaselining; ' + |
261 '--tests has also been specified.') | 223 'if unspecified, then rebaseline all the configs that ' + |
262 parser.add_argument('--dry_run', action='store_true', | 224 'JSON_FILENAME tells us need rebaselining.') |
225 parser.add_argument('--dry-run', action='store_true', | |
263 help='instead of actually downloading files or adding ' + | 226 help='instead of actually downloading files or adding ' + |
264 'files to checkout, display a list of operations that ' + | 227 'files to checkout, display a list of operations that ' + |
265 'we would normally perform') | 228 'we would normally perform') |
266 parser.add_argument('--json_base_url', | 229 parser.add_argument('--json-base-url', |
267 help='base URL from which to read JSON_FILENAME ' + | 230 help='base URL from which to read JSON_FILENAME ' + |
268 'files; defaults to %(default)s', | 231 'files; defaults to %(default)s', |
269 default='http://skia-autogen.googlecode.com/svn/gm-actual') | 232 default='http://skia-autogen.googlecode.com/svn/gm-actual') |
270 parser.add_argument('--json_filename', | 233 parser.add_argument('--json-filename', |
271 help='filename (under JSON_BASE_URL) to read a summary ' + | 234 help='filename (under JSON_BASE_URL) to read a summary ' + |
272 'of results from; defaults to %(default)s', | 235 'of results from; defaults to %(default)s', |
273 default='actual-results.json') | 236 default='actual-results.json') |
274 parser.add_argument('--subdirs', metavar='SUBDIR', nargs='+', | 237 parser.add_argument('--subdirs', metavar='SUBDIR', nargs='+', |
275 help='which platform subdirectories to rebaseline; ' + | 238 help='which platform subdirectories to rebaseline; ' + |
276 'if unspecified, rebaseline all subdirs, same as ' + | 239 'if unspecified, rebaseline all subdirs, same as ' + |
277 '"--subdirs %s"' % ' '.join(sorted(SUBDIR_MAPPING.keys()))) | 240 '"--subdirs %s"' % ' '.join(sorted(SUBDIR_MAPPING.keys()))) |
278 parser.add_argument('--tests', metavar='TEST', nargs='+', | 241 parser.add_argument('--tests', metavar='TEST', nargs='+', |
279 help='which tests to rebaseline, e.g. ' + | 242 help='which tests to rebaseline, e.g. ' + |
280 '"--tests aaclip bigmatrix"; if unspecified, then all ' + | 243 '"--tests aaclip bigmatrix", as a filter over the tests ' + |
281 'failing tests (according to the actual-results.json ' + | 244 'which JSON_FILENAME tells us need rebaselining; ' + |
282 'file) will be rebaselined.') | 245 'if unspecified, then rebaseline all the tests that ' + |
246 'JSON_FILENAME tells us need rebaselining.') | |
283 args = parser.parse_args() | 247 args = parser.parse_args() |
284 rebaseliner = Rebaseliner(tests=args.tests, configs=args.configs, | 248 rebaseliner = Rebaseliner(tests=args.tests, configs=args.configs, |
285 subdirs=args.subdirs, dry_run=args.dry_run, | 249 subdirs=args.subdirs, dry_run=args.dry_run, |
286 json_base_url=args.json_base_url, | 250 json_base_url=args.json_base_url, |
287 json_filename=args.json_filename) | 251 json_filename=args.json_filename) |
288 rebaseliner.RebaselineAll() | 252 rebaseliner.RebaselineAll() |
OLD | NEW |