Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: tools/rebaseline.py

Issue 16093025: rebaseline.py: if --tests is not specified, get test list from actual-results.json (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: read_test_list_from_json_file Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gm/__init__.py ('k') | tools/tests/rebaseline/all/output-expected/stdout » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 import argparse 17 import argparse
17 import os 18 import os
18 import subprocess 19 import subprocess
19 import sys 20 import sys
21 import urllib2
22
23 # Imports from within Skia
24 #
25 # Make sure that they are in the PYTHONPATH, but add them at the *end*
26 # so any that are already in the PYTHONPATH will be preferred.
27 GM_DIRECTORY = os.path.realpath(
28 os.path.join(os.path.dirname(os.path.dirname(__file__)), 'gm'))
29 if GM_DIRECTORY not in sys.path:
30 sys.path.append(GM_DIRECTORY)
31 import gm_json
32
20 33
21 # Mapping of gm-expectations subdir (under 34 # Mapping of gm-expectations subdir (under
22 # https://skia.googlecode.com/svn/gm-expected/ ) 35 # https://skia.googlecode.com/svn/gm-expected/ )
23 # to builder name (see list at http://108.170.217.252:10117/builders ) 36 # to builder name (see list at http://108.170.217.252:10117/builders )
24 SUBDIR_MAPPING = { 37 SUBDIR_MAPPING = {
25 'base-shuttle-win7-intel-float': 38 'base-shuttle-win7-intel-float':
26 'Test-Win7-ShuttleA-HD2000-x86-Release', 39 'Test-Win7-ShuttleA-HD2000-x86-Release',
27 'base-shuttle-win7-intel-angle': 40 'base-shuttle-win7-intel-angle':
28 'Test-Win7-ShuttleA-HD2000-x86-Release-ANGLE', 41 'Test-Win7-ShuttleA-HD2000-x86-Release-ANGLE',
29 'base-shuttle-win7-intel-directwrite': 42 'base-shuttle-win7-intel-directwrite':
(...skipping 16 matching lines...) Expand all
46 'Test-Android-Nexus10-MaliT604-Arm7-Release', 59 'Test-Android-Nexus10-MaliT604-Arm7-Release',
47 } 60 }
48 61
49 62
50 class CommandFailedException(Exception): 63 class CommandFailedException(Exception):
51 pass 64 pass
52 65
53 class Rebaseliner(object): 66 class Rebaseliner(object):
54 67
55 # params: 68 # params:
56 # tests: list of tests to rebaseline 69 # tests: list of tests to rebaseline, or None if we should rebaseline
70 # whatever tests the actual-results.json file tells us to
71 # json_base_url: base URL from which to read json_filename
72 # json_filename: filename (under json_base_url) from which to read a
73 # summary of results
57 # configs: which configs to run for each test 74 # configs: which configs to run for each test
58 # subdirs: which platform subdirectories to rebaseline; if an empty list, 75 # subdirs: which platform subdirectories to rebaseline; if an empty list,
59 # rebaseline all platform subdirectories 76 # rebaseline all platform subdirectories
60 # dry_run: if True, instead of actually downloading files or adding 77 # dry_run: if True, instead of actually downloading files or adding
61 # files to checkout, display a list of operations that 78 # files to checkout, display a list of operations that
62 # we would normally perform 79 # we would normally perform
63 def __init__(self, tests, configs=[], subdirs=[], dry_run=False): 80 def __init__(self, tests, json_base_url, json_filename,
64 if not tests: 81 configs=[], subdirs=[], dry_run=False):
65 raise Exception('at least one test must be specified')
66 self._tests = tests 82 self._tests = tests
67 self._configs = configs 83 self._configs = configs
68 if not subdirs: 84 if not subdirs:
69 self._subdirs = sorted(SUBDIR_MAPPING.keys()) 85 self._subdirs = sorted(SUBDIR_MAPPING.keys())
70 else: 86 else:
71 self._subdirs = subdirs 87 self._subdirs = subdirs
88 self._json_base_url = json_base_url
89 self._json_filename = json_filename
72 self._dry_run = dry_run 90 self._dry_run = dry_run
73 self._is_svn_checkout = ( 91 self._is_svn_checkout = (
74 os.path.exists('.svn') or 92 os.path.exists('.svn') or
75 os.path.exists(os.path.join(os.pardir, '.svn'))) 93 os.path.exists(os.path.join(os.pardir, '.svn')))
76 self._is_git_checkout = ( 94 self._is_git_checkout = (
77 os.path.exists('.git') or 95 os.path.exists('.git') or
78 os.path.exists(os.path.join(os.pardir, '.git'))) 96 os.path.exists(os.path.join(os.pardir, '.git')))
79 97
80 # If dry_run is False, execute subprocess.call(cmd). 98 # If dry_run is False, execute subprocess.call(cmd).
81 # If dry_run is True, print the command we would have otherwise run. 99 # If dry_run is True, print the command we would have otherwise run.
(...skipping 12 matching lines...) Expand all
94 # so that we don't corrupt the existing file if it fails midway thru. 112 # so that we don't corrupt the existing file if it fails midway thru.
95 temp_filename = os.path.join(os.path.dirname(dest_filename), 113 temp_filename = os.path.join(os.path.dirname(dest_filename),
96 '.temp-' + os.path.basename(dest_filename)) 114 '.temp-' + os.path.basename(dest_filename))
97 115
98 # TODO(epoger): Replace calls to "curl"/"mv" (which will only work on 116 # TODO(epoger): Replace calls to "curl"/"mv" (which will only work on
99 # Unix) with a Python HTTP library (which should work cross-platform) 117 # Unix) with a Python HTTP library (which should work cross-platform)
100 self._Call([ 'curl', '--fail', '--silent', source_url, 118 self._Call([ 'curl', '--fail', '--silent', source_url,
101 '--output', temp_filename ]) 119 '--output', temp_filename ])
102 self._Call([ 'mv', temp_filename, dest_filename ]) 120 self._Call([ 'mv', temp_filename, dest_filename ])
103 121
122 # Returns the full contents of a URL, as a single string.
123 #
124 # Unlike standard URL handling, we allow relative "file:" URLs;
125 # for example, "file:one/two" resolves to the file ./one/two
126 # (relative to current working dir)
127 def _GetContentsOfUrl(self, url):
128 file_prefix = 'file:'
129 if url.startswith(file_prefix):
130 filename = url[len(file_prefix):]
131 return open(filename, 'r').read()
132 else:
133 return urllib2.urlopen(url).read()
134
135 # Returns a list of tests that require rebaselining.
136 #
137 # params:
138 # json_url: URL pointing to a JSON actual result summary file
139 #
140 # TODO(epoger): add a parameter indicating whether "no-comparison"
141 # results (those for which we don't have any expectations yet)
142 # should be rebaselined. For now, we only return failed expectations.
143 def _GetTestsToRebaseline(self, json_url):
144 print ('# Getting tests to rebaseline from JSON summary file %s ...'
145 % json_url)
146 json_contents = self._GetContentsOfUrl(json_url)
147 json_dict = gm_json.LoadFromString(json_contents)
148 actual_results = json_dict[gm_json.JSONKEY_ACTUALRESULTS]
149 failed_results = actual_results[gm_json.JSONKEY_ACTUALRESULTS_FAILED]
150 tests_to_rebaseline = failed_results.keys()
151 print '# ... found tests_to_rebaseline %s' % tests_to_rebaseline
152 return tests_to_rebaseline
153
104 # Rebaseline a single file. 154 # Rebaseline a single file.
105 def _RebaselineOneFile(self, expectations_subdir, builder_name, 155 def _RebaselineOneFile(self, expectations_subdir, builder_name,
106 infilename, outfilename): 156 infilename, outfilename):
107 url = ('http://skia-autogen.googlecode.com/svn/gm-actual/' + 157 url = ('http://skia-autogen.googlecode.com/svn/gm-actual/' +
108 expectations_subdir + '/' + builder_name + '/' + 158 expectations_subdir + '/' + builder_name + '/' +
109 expectations_subdir + '/' + infilename) 159 expectations_subdir + '/' + infilename)
110 160
111 # Try to download this file, but if that fails, keep going... 161 # Try to download this file, but if that fails, keep going...
112 # 162 #
113 # This not treated as a fatal failure because not all 163 # This not treated as a fatal failure because not all
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 infilename = test + '_' + config + '.png' 207 infilename = test + '_' + config + '.png'
158 print '# ' + infilename 208 print '# ' + infilename
159 outfilename = os.path.join(expectations_subdir, infilename); 209 outfilename = os.path.join(expectations_subdir, infilename);
160 self._RebaselineOneFile(expectations_subdir=expectations_subdir, 210 self._RebaselineOneFile(expectations_subdir=expectations_subdir,
161 builder_name=builder_name, 211 builder_name=builder_name,
162 infilename=infilename, 212 infilename=infilename,
163 outfilename=outfilename) 213 outfilename=outfilename)
164 214
165 # Rebaseline all platforms/tests/types we specified in the constructor. 215 # Rebaseline all platforms/tests/types we specified in the constructor.
166 def RebaselineAll(self): 216 def RebaselineAll(self):
167 for test in self._tests: 217 for subdir in self._subdirs:
168 for subdir in self._subdirs: 218 if not subdir in SUBDIR_MAPPING.keys():
169 if not subdir in SUBDIR_MAPPING.keys(): 219 raise Exception(('unrecognized platform subdir "%s"; ' +
170 raise Exception(('unrecognized platform subdir "%s"; ' + 220 'should be one of %s') % (
171 'should be one of %s') % ( 221 subdir, SUBDIR_MAPPING.keys()))
172 subdir, SUBDIR_MAPPING.keys())) 222 builder_name = SUBDIR_MAPPING[subdir]
173 builder_name = SUBDIR_MAPPING[subdir] 223 if self._tests:
epoger 2013/06/04 18:52:23 Patchset 3: If --tests has been specified, just us
224 tests = self._tests
225 else:
226 json_url = '/'.join([self._json_base_url,
227 subdir, builder_name, subdir,
228 self._json_filename])
229 tests = self._GetTestsToRebaseline(json_url=json_url)
230 for test in tests:
174 self._RebaselineOneTest(expectations_subdir=subdir, 231 self._RebaselineOneTest(expectations_subdir=subdir,
175 builder_name=builder_name, 232 builder_name=builder_name,
176 test=test) 233 test=test)
177 234
178 235
179 # main... 236 # main...
180 237
181 parser = argparse.ArgumentParser() 238 parser = argparse.ArgumentParser()
182 parser.add_argument('--configs', metavar='CONFIG', nargs='+', 239 parser.add_argument('--configs', metavar='CONFIG', nargs='+',
183 help='which configurations to rebaseline, e.g. ' + 240 help='which configurations to rebaseline, e.g. ' +
184 '"--configs 565 8888"; if unspecified, run a default ' + 241 '"--configs 565 8888"; if unspecified, run a default ' +
185 'set of configs') 242 'set of configs')
186 parser.add_argument('--dry_run', action='store_true', 243 parser.add_argument('--dry_run', action='store_true',
187 help='instead of actually downloading files or adding ' + 244 help='instead of actually downloading files or adding ' +
188 'files to checkout, display a list of operations that ' + 245 'files to checkout, display a list of operations that ' +
189 'we would normally perform') 246 'we would normally perform')
247 parser.add_argument('--json_base_url',
248 help='base URL from which to read JSON_FILENAME ' +
249 'files; defaults to %(default)s',
250 default='http://skia-autogen.googlecode.com/svn/gm-actual')
251 parser.add_argument('--json_filename',
252 help='filename (under JSON_BASE_URL) to read a summary ' +
253 'of results from; defaults to %(default)s',
254 default='actual-results.json')
190 parser.add_argument('--subdirs', metavar='SUBDIR', nargs='+', 255 parser.add_argument('--subdirs', metavar='SUBDIR', nargs='+',
191 help='which platform subdirectories to rebaseline; ' + 256 help='which platform subdirectories to rebaseline; ' +
192 'if unspecified, rebaseline all subdirs, same as ' + 257 'if unspecified, rebaseline all subdirs, same as ' +
193 '"--subdirs %s"' % ' '.join(sorted(SUBDIR_MAPPING.keys()))) 258 '"--subdirs %s"' % ' '.join(sorted(SUBDIR_MAPPING.keys())))
194 parser.add_argument('--tests', metavar='TEST', nargs='+', required=True, 259 parser.add_argument('--tests', metavar='TEST', nargs='+',
195 help='which tests to rebaseline, e.g. ' + 260 help='which tests to rebaseline, e.g. ' +
196 '"--tests aaclip bigmatrix"') 261 '"--tests aaclip bigmatrix"; if unspecified, then all ' +
262 'failing tests (according to the actual-results.json ' +
263 'file) will be rebaselined.')
197 args = parser.parse_args() 264 args = parser.parse_args()
198 rebaseliner = Rebaseliner(tests=args.tests, configs=args.configs, 265 rebaseliner = Rebaseliner(tests=args.tests, configs=args.configs,
199 subdirs=args.subdirs, dry_run=args.dry_run) 266 subdirs=args.subdirs, dry_run=args.dry_run,
267 json_base_url=args.json_base_url,
268 json_filename=args.json_filename)
200 rebaseliner.RebaselineAll() 269 rebaseliner.RebaselineAll()
OLDNEW
« no previous file with comments | « gm/__init__.py ('k') | tools/tests/rebaseline/all/output-expected/stdout » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698