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

Side by Side Diff: tools/rebaseline.py

Issue 17379004: rebaseline.py: split image-based rebaselining, which will go away soon, into its own script (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: move_ImageRebaseliner_into_other_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 | « no previous file | tools/rebaseline_imagefiles.py » ('j') | tools/rebaseline_imagefiles.py » ('J')
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 # System-level imports
17 import argparse 17 import argparse
18 import os 18 import os
19 import re 19 import re
20 import subprocess 20 import subprocess
21 import sys 21 import sys
22 import urllib2 22 import urllib2
23 23
24 # Imports from local directory
25 import rebaseline_imagefiles
26
24 # Imports from within Skia 27 # Imports from within Skia
25 # 28 #
26 # We need to add the 'gm' directory, so that we can import gm_json.py within 29 # We need to add the 'gm' directory, so that we can import gm_json.py within
27 # that directory. That script allows us to parse the actual-results.json file 30 # that directory. That script allows us to parse the actual-results.json file
28 # written out by the GM tool. 31 # written out by the GM tool.
29 # Make sure that the 'gm' dir is in the PYTHONPATH, but add it at the *end* 32 # Make sure that the 'gm' dir is in the PYTHONPATH, but add it at the *end*
30 # so any dirs that are already in the PYTHONPATH will be preferred. 33 # so any dirs that are already in the PYTHONPATH will be preferred.
31 # 34 #
32 # This assumes that the 'gm' directory has been checked out as a sibling of 35 # This assumes that the 'gm' directory has been checked out as a sibling of
33 # the 'tools' directory containing this script, which will be the case if 36 # the 'tools' directory containing this script, which will be the case if
34 # 'trunk' was checked out as a single unit. 37 # 'trunk' was checked out as a single unit.
35 GM_DIRECTORY = os.path.realpath( 38 GM_DIRECTORY = os.path.realpath(
36 os.path.join(os.path.dirname(os.path.dirname(__file__)), 'gm')) 39 os.path.join(os.path.dirname(os.path.dirname(__file__)), 'gm'))
37 if GM_DIRECTORY not in sys.path: 40 if GM_DIRECTORY not in sys.path:
38 sys.path.append(GM_DIRECTORY) 41 sys.path.append(GM_DIRECTORY)
39 import gm_json 42 import gm_json
40 43
41
42 # Mapping of gm-expectations subdir (under 44 # Mapping of gm-expectations subdir (under
43 # https://skia.googlecode.com/svn/gm-expected/ ) 45 # https://skia.googlecode.com/svn/gm-expected/ )
44 # to builder name (see list at http://108.170.217.252:10117/builders ) 46 # to builder name (see list at http://108.170.217.252:10117/builders )
45 SUBDIR_MAPPING = { 47 SUBDIR_MAPPING = {
46 'base-shuttle-win7-intel-float': 48 'base-shuttle-win7-intel-float':
47 'Test-Win7-ShuttleA-HD2000-x86-Release', 49 'Test-Win7-ShuttleA-HD2000-x86-Release',
48 'base-shuttle-win7-intel-angle': 50 'base-shuttle-win7-intel-angle':
49 'Test-Win7-ShuttleA-HD2000-x86-Release-ANGLE', 51 'Test-Win7-ShuttleA-HD2000-x86-Release-ANGLE',
50 'base-shuttle-win7-intel-directwrite': 52 'base-shuttle-win7-intel-directwrite':
51 'Test-Win7-ShuttleA-HD2000-x86-Release-DirectWrite', 53 'Test-Win7-ShuttleA-HD2000-x86-Release-DirectWrite',
(...skipping 12 matching lines...) Expand all
64 'base-android-xoom': 66 'base-android-xoom':
65 'Test-Android-Xoom-Tegra2-Arm7-Release', 67 'Test-Android-Xoom-Tegra2-Arm7-Release',
66 'base-android-nexus-10': 68 'base-android-nexus-10':
67 'Test-Android-Nexus10-MaliT604-Arm7-Release', 69 'Test-Android-Nexus10-MaliT604-Arm7-Release',
68 } 70 }
69 71
70 72
71 class CommandFailedException(Exception): 73 class CommandFailedException(Exception):
72 pass 74 pass
73 75
74 class Rebaseliner(object): 76 # Object that rebaselines a JSON expectations file (not individual image files).
77 #
78 # TODO(epoger): Most of this is just the code from the old ImageRebaseliner...
79 # some of it will need to be updated in order to properly rebaseline JSON files.
80 # There is a lot of code duplicated between here and ImageRebaseliner, but
81 # that's fine because we will delete ImageRebaseliner soon.
82 class JsonRebaseliner(object):
75 83
76 # params: 84 # params:
77 # json_base_url: base URL from which to read json_filename 85 # json_base_url: base URL from which to read json_filename
78 # json_filename: filename (under json_base_url) from which to read a 86 # json_filename: filename (under json_base_url) from which to read a
79 # summary of results; typically "actual-results.json" 87 # summary of results; typically "actual-results.json"
80 # subdirs: which platform subdirectories to rebaseline; if not specified,
81 # rebaseline all platform subdirectories
82 # tests: list of tests to rebaseline, or None if we should rebaseline 88 # tests: list of tests to rebaseline, or None if we should rebaseline
83 # whatever files the JSON results summary file tells us to 89 # whatever files the JSON results summary file tells us to
84 # configs: which configs to run for each test; this should only be 90 # configs: which configs to run for each test; this should only be
85 # specified if the list of tests was also specified (otherwise, 91 # specified if the list of tests was also specified (otherwise,
86 # the JSON file will give us test names and configs) 92 # the JSON file will give us test names and configs)
87 # dry_run: if True, instead of actually downloading files or adding 93 # dry_run: if True, instead of actually downloading files or adding
88 # files to checkout, display a list of operations that 94 # files to checkout, display a list of operations that
89 # we would normally perform 95 # we would normally perform
90 # add_new: if True, add expectations for tests which don't have any yet 96 # add_new: if True, add expectations for tests which don't have any yet
97 # missing_json_is_fatal: whether to halt execution if we cannot read a
98 # JSON actual result summary file
91 def __init__(self, json_base_url, json_filename, 99 def __init__(self, json_base_url, json_filename,
92 subdirs=None, tests=None, configs=None, dry_run=False, 100 tests=None, configs=None, dry_run=False,
93 add_new=False): 101 add_new=False, missing_json_is_fatal=False):
102 raise ValueError('JsonRebaseliner not yet implemented') # TODO(epoger)
94 if configs and not tests: 103 if configs and not tests:
95 raise ValueError('configs should only be specified if tests ' + 104 raise ValueError('configs should only be specified if tests ' +
96 'were specified also') 105 'were specified also')
97 self._tests = tests 106 self._tests = tests
98 self._configs = configs 107 self._configs = configs
99 if not subdirs:
100 self._subdirs = sorted(SUBDIR_MAPPING.keys())
101 self._missing_json_is_fatal = False
102 else:
103 self._subdirs = subdirs
104 self._missing_json_is_fatal = True
105 self._json_base_url = json_base_url 108 self._json_base_url = json_base_url
106 self._json_filename = json_filename 109 self._json_filename = json_filename
107 self._dry_run = dry_run 110 self._dry_run = dry_run
108 self._add_new = add_new 111 self._add_new = add_new
112 self._missing_json_is_fatal = missing_json_is_fatal
109 self._googlestorage_gm_actuals_root = ( 113 self._googlestorage_gm_actuals_root = (
110 'http://chromium-skia-gm.commondatastorage.googleapis.com/gm') 114 'http://chromium-skia-gm.commondatastorage.googleapis.com/gm')
111 self._testname_pattern = re.compile('(\S+)_(\S+).png') 115 self._testname_pattern = re.compile('(\S+)_(\S+).png')
112 self._is_svn_checkout = ( 116 self._is_svn_checkout = (
113 os.path.exists('.svn') or 117 os.path.exists('.svn') or
114 os.path.exists(os.path.join(os.pardir, '.svn'))) 118 os.path.exists(os.path.join(os.pardir, '.svn')))
115 self._is_git_checkout = ( 119 self._is_git_checkout = (
116 os.path.exists('.git') or 120 os.path.exists('.git') or
117 os.path.exists(os.path.join(os.pardir, '.git'))) 121 os.path.exists(os.path.join(os.pardir, '.git')))
118 122
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 print '# ' + expectations_subdir + ':' 336 print '# ' + expectations_subdir + ':'
333 for config in configs: 337 for config in configs:
334 infilename = test + '_' + config + '.png' 338 infilename = test + '_' + config + '.png'
335 outfilename = os.path.join(expectations_subdir, infilename); 339 outfilename = os.path.join(expectations_subdir, infilename);
336 self._RebaselineOneFile(expectations_subdir=expectations_subdir, 340 self._RebaselineOneFile(expectations_subdir=expectations_subdir,
337 builder_name=builder_name, 341 builder_name=builder_name,
338 infilename=infilename, 342 infilename=infilename,
339 outfilename=outfilename, 343 outfilename=outfilename,
340 all_results=all_results) 344 all_results=all_results)
341 345
342 # Rebaseline all platforms/tests/types we specified in the constructor. 346 # Rebaseline all tests/types we specified in the constructor,
343 def RebaselineAll(self): 347 # within this gm-expectations subdir.
344 for subdir in self._subdirs: 348 #
345 if not subdir in SUBDIR_MAPPING.keys(): 349 # params:
346 raise Exception(('unrecognized platform subdir "%s"; ' + 350 # subdir : e.g. 'base-shuttle-win7-intel-float'
347 'should be one of %s') % ( 351 # builder : e.g. 'Test-Win7-ShuttleA-HD2000-x86-Release'
348 subdir, SUBDIR_MAPPING.keys())) 352 def RebaselineSubdir(self, subdir, builder):
349 builder_name = SUBDIR_MAPPING[subdir] 353 json_url = '/'.join([self._json_base_url,
350 json_url = '/'.join([self._json_base_url, 354 subdir, builder, subdir,
351 subdir, builder_name, subdir, 355 self._json_filename])
352 self._json_filename]) 356 all_results = self._GetActualResults(json_url=json_url)
353 all_results = self._GetActualResults(json_url=json_url)
354 357
355 if self._tests: 358 if self._tests:
356 for test in self._tests: 359 for test in self._tests:
357 self._RebaselineOneTest(expectations_subdir=subdir, 360 self._RebaselineOneTest(expectations_subdir=subdir,
358 builder_name=builder_name, 361 builder_name=builder,
359 test=test, all_results=all_results) 362 test=test, all_results=all_results)
360 else: # get the raw list of files that need rebaselining from JSON 363 else: # get the raw list of files that need rebaselining from JSON
361 filenames = self._GetFilesToRebaseline(json_url=json_url, 364 filenames = self._GetFilesToRebaseline(json_url=json_url,
362 add_new=self._add_new) 365 add_new=self._add_new)
363 for filename in filenames: 366 for filename in filenames:
364 outfilename = os.path.join(subdir, filename); 367 outfilename = os.path.join(subdir, filename);
365 self._RebaselineOneFile(expectations_subdir=subdir, 368 self._RebaselineOneFile(expectations_subdir=subdir,
366 builder_name=builder_name, 369 builder_name=builder,
367 infilename=filename, 370 infilename=filename,
368 outfilename=outfilename, 371 outfilename=outfilename,
369 all_results=all_results) 372 all_results=all_results)
370 373
371 # main... 374 # main...
372 375
373 parser = argparse.ArgumentParser() 376 parser = argparse.ArgumentParser()
374 parser.add_argument('--add-new', action='store_true', 377 parser.add_argument('--add-new', action='store_true',
375 help='in addition to the standard behavior of ' + 378 help='in addition to the standard behavior of ' +
376 'updating expectations for failing tests, add ' + 379 'updating expectations for failing tests, add ' +
377 'expectations for tests which don\'t have expectations ' + 380 'expectations for tests which don\'t have expectations ' +
378 'yet.') 381 'yet.')
379 parser.add_argument('--configs', metavar='CONFIG', nargs='+', 382 parser.add_argument('--configs', metavar='CONFIG', nargs='+',
(...skipping 16 matching lines...) Expand all
396 parser.add_argument('--subdirs', metavar='SUBDIR', nargs='+', 399 parser.add_argument('--subdirs', metavar='SUBDIR', nargs='+',
397 help='which platform subdirectories to rebaseline; ' + 400 help='which platform subdirectories to rebaseline; ' +
398 'if unspecified, rebaseline all subdirs, same as ' + 401 'if unspecified, rebaseline all subdirs, same as ' +
399 '"--subdirs %s"' % ' '.join(sorted(SUBDIR_MAPPING.keys()))) 402 '"--subdirs %s"' % ' '.join(sorted(SUBDIR_MAPPING.keys())))
400 parser.add_argument('--tests', metavar='TEST', nargs='+', 403 parser.add_argument('--tests', metavar='TEST', nargs='+',
401 help='which tests to rebaseline, e.g. ' + 404 help='which tests to rebaseline, e.g. ' +
402 '"--tests aaclip bigmatrix"; if unspecified, then all ' + 405 '"--tests aaclip bigmatrix"; if unspecified, then all ' +
403 'failing tests (according to the actual-results.json ' + 406 'failing tests (according to the actual-results.json ' +
404 'file) will be rebaselined.') 407 'file) will be rebaselined.')
405 args = parser.parse_args() 408 args = parser.parse_args()
406 rebaseliner = Rebaseliner(tests=args.tests, configs=args.configs, 409 if args.subdirs:
407 subdirs=args.subdirs, dry_run=args.dry_run, 410 subdirs = args.subdirs
408 json_base_url=args.json_base_url, 411 missing_json_is_fatal = True
409 json_filename=args.json_filename, 412 else:
410 add_new=args.add_new) 413 subdirs = sorted(SUBDIR_MAPPING.keys())
411 rebaseliner.RebaselineAll() 414 missing_json_is_fatal = False
415 for subdir in subdirs:
416 if not subdir in SUBDIR_MAPPING.keys():
417 raise Exception(('unrecognized platform subdir "%s"; ' +
418 'should be one of %s') % (
419 subdir, SUBDIR_MAPPING.keys()))
420 builder = SUBDIR_MAPPING[subdir]
421
422 # Soon, we will be instantiating different Rebaseliner objects depending
423 # on whether we are rebaselining an expected-results.json file, or
424 # individual image files. Different gm-expected subdirectories may move
425 # from individual image files to JSON-format expectations at different
426 # times, so we need to make this determination per subdirectory.
427 #
428 # See https://goto.google.com/ChecksumTransitionDetail
429 rebaseliner = rebaseline_imagefiles.ImageRebaseliner(
430 tests=args.tests, configs=args.configs,
431 dry_run=args.dry_run,
432 json_base_url=args.json_base_url,
433 json_filename=args.json_filename,
434 add_new=args.add_new,
435 missing_json_is_fatal=missing_json_is_fatal)
436 rebaseliner.RebaselineSubdir(subdir=subdir, builder=builder)
OLDNEW
« no previous file with comments | « no previous file | tools/rebaseline_imagefiles.py » ('j') | tools/rebaseline_imagefiles.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698