1363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#!/usr/bin/python 2363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 3363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger''' 4363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerCopyright 2012 Google Inc. 5363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 6363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerUse of this source code is governed by a BSD-style license that can be 7363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerfound in the LICENSE file. 8363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger''' 9363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 10363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger''' 11363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerRebaselines the given GM tests, on all bots and all configurations. 12363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger''' 13363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 1458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# System-level imports 1558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerimport argparse 160a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerimport json 1758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerimport os 1858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerimport re 1958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerimport subprocess 2058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerimport sys 2158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerimport urllib2 2258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 2358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# Imports from within Skia 2458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# 2558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# We need to add the 'gm' directory, so that we can import gm_json.py within 2658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# that directory. That script allows us to parse the actual-results.json file 2758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# written out by the GM tool. 2858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# Make sure that the 'gm' dir is in the PYTHONPATH, but add it at the *end* 2958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# so any dirs that are already in the PYTHONPATH will be preferred. 3058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# 3158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# This assumes that the 'gm' directory has been checked out as a sibling of 3258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# the 'tools' directory containing this script, which will be the case if 3358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# 'trunk' was checked out as a single unit. 3458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerGM_DIRECTORY = os.path.realpath( 3558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger os.path.join(os.path.dirname(os.path.dirname(__file__)), 'gm')) 3658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerif GM_DIRECTORY not in sys.path: 37e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger sys.path.append(GM_DIRECTORY) 3858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerimport gm_json 3958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 400a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger# TODO(epoger): In the long run, we want to build this list automatically, 410a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger# but for now we hard-code it until we can properly address 420a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger# https://code.google.com/p/skia/issues/detail?id=1544 430a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger# ('live query of builder list makes rebaseline.py slow to start up') 440a657bbc2c6fc9daf699942e023050536d5ec95fDerek SollenbergerTEST_BUILDERS = [ 4558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 'Test-Android-GalaxyNexus-SGX540-Arm7-Debug', 460a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Android-GalaxyNexus-SGX540-Arm7-Release', 470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Android-IntelRhb-SGX544-x86-Debug', 480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Android-IntelRhb-SGX544-x86-Release', 490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Android-Nexus10-MaliT604-Arm7-Debug', 500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Android-Nexus10-MaliT604-Arm7-Release', 510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Android-Nexus4-Adreno320-Arm7-Debug', 520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Android-Nexus4-Adreno320-Arm7-Release', 530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Android-Nexus7-Tegra3-Arm7-Debug', 5458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 'Test-Android-Nexus7-Tegra3-Arm7-Release', 550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Android-NexusS-SGX540-Arm7-Debug', 5658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 'Test-Android-NexusS-SGX540-Arm7-Release', 570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Android-Xoom-Tegra2-Arm7-Debug', 5858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 'Test-Android-Xoom-Tegra2-Arm7-Release', 590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-ChromeOS-Alex-GMA3150-x86-Debug', 600a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-ChromeOS-Alex-GMA3150-x86-Release', 610a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-ChromeOS-Daisy-MaliT604-Arm7-Debug', 620a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-ChromeOS-Daisy-MaliT604-Arm7-Release', 630a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-ChromeOS-Link-HD4000-x86_64-Debug', 640a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-ChromeOS-Link-HD4000-x86_64-Release', 650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.6-MacMini4.1-GeForce320M-x86-Debug', 660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.6-MacMini4.1-GeForce320M-x86-Release', 670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.6-MacMini4.1-GeForce320M-x86_64-Debug', 680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.6-MacMini4.1-GeForce320M-x86_64-Release', 690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.7-MacMini4.1-GeForce320M-x86-Debug', 700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.7-MacMini4.1-GeForce320M-x86-Release', 710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.7-MacMini4.1-GeForce320M-x86_64-Debug', 720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.7-MacMini4.1-GeForce320M-x86_64-Release', 730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.8-MacMini4.1-GeForce320M-x86-Debug', 740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.8-MacMini4.1-GeForce320M-x86-Release', 750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.8-MacMini4.1-GeForce320M-x86_64-Debug', 760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Mac10.8-MacMini4.1-GeForce320M-x86_64-Release', 770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Ubuntu12-ShuttleA-ATI5770-x86-Debug', 780a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Ubuntu12-ShuttleA-ATI5770-x86-Release', 790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Ubuntu12-ShuttleA-ATI5770-x86_64-Debug', 800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Ubuntu12-ShuttleA-ATI5770-x86_64-Release', 810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Ubuntu12-ShuttleA-HD2000-x86_64-Release-Valgrind', 820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Ubuntu12-ShuttleA-NoGPU-x86_64-Debug', 830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Ubuntu13-ShuttleA-HD2000-x86_64-Debug-ASAN', 840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Win7-ShuttleA-HD2000-x86-Debug', 850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Win7-ShuttleA-HD2000-x86-Debug-ANGLE', 860a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Win7-ShuttleA-HD2000-x86-Debug-DirectWrite', 870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Win7-ShuttleA-HD2000-x86-Release', 880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Win7-ShuttleA-HD2000-x86-Release-ANGLE', 890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Win7-ShuttleA-HD2000-x86-Release-DirectWrite', 900a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Win7-ShuttleA-HD2000-x86_64-Debug', 910a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Test-Win7-ShuttleA-HD2000-x86_64-Release', 920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger] 930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger# TODO: Get this from builder_name_schema in buildbot. 950a657bbc2c6fc9daf699942e023050536d5ec95fDerek SollenbergerTRYBOT_SUFFIX = '-Trybot' 9658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 9758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 9858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerclass _InternalException(Exception): 99e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger pass 10058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 10158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerclass ExceptionHandler(object): 1020a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger """ Object that handles exceptions, either raising them immediately or 1030a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger collecting them to display later on.""" 10458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 105e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # params: 106e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger def __init__(self, keep_going_on_failure=False): 1070a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger """ 1080a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger params: 1090a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger keep_going_on_failure: if False, report failures and quit right away; 1100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if True, collect failures until 1110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger ReportAllFailures() is called 1120a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger """ 113e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._keep_going_on_failure = keep_going_on_failure 114e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._failures_encountered = [] 115e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 1160a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger def RaiseExceptionOrContinue(self): 1170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger """ We have encountered an exception; either collect the info and keep 1180a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger going, or exit the program right away.""" 1190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # Get traceback information about the most recently raised exception. 1200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger exc_info = sys.exc_info() 121e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 122e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if self._keep_going_on_failure: 1230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger print >> sys.stderr, ('WARNING: swallowing exception %s' % 1240a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger repr(exc_info[1])) 1250a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger self._failures_encountered.append(exc_info) 126e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger else: 127e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger print >> sys.stderr, ( 1280a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger '\nHalting at first exception.\n' + 1290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Please file a bug to epoger@google.com at ' + 1300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'https://code.google.com/p/skia/issues/entry, containing the ' + 1310a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'command you ran and the following stack trace.\n\n' + 1320a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Afterwards, you can re-run with the --keep-going-on-failure ' + 1330a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'option set.\n') 1340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger raise exc_info[1], None, exc_info[2] 13558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 136e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger def ReportAllFailures(self): 137e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if self._failures_encountered: 138e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger print >> sys.stderr, ('Encountered %d failures (see above).' % 139e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger len(self._failures_encountered)) 1400a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger sys.exit(1) 14158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 14258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 14358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# Object that rebaselines a JSON expectations file (not individual image files). 14458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerclass JsonRebaseliner(object): 14558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 146e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # params: 147e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # expectations_root: root directory of all expectations JSON files 148e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # expectations_input_filename: filename (under expectations_root) of JSON 149e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # expectations file to read; typically 150e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # "expected-results.json" 151e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # expectations_output_filename: filename (under expectations_root) to 152e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # which updated expectations should be 153e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # written; typically the same as 154e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # expectations_input_filename, to overwrite 155e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # the old content 156e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # actuals_base_url: base URL from which to read actual-result JSON files 157e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # actuals_filename: filename (under actuals_base_url) from which to read a 158e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # summary of results; typically "actual-results.json" 159e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # exception_handler: reference to rebaseline.ExceptionHandler object 160e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # tests: list of tests to rebaseline, or None if we should rebaseline 161e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # whatever files the JSON results summary file tells us to 162e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # configs: which configs to run for each test, or None if we should 163e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # rebaseline whatever configs the JSON results summary file tells 164e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # us to 165e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # add_new: if True, add expectations for tests which don't have any yet 1660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # add_ignored: if True, add expectations for tests for which failures are 1670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # currently ignored 1680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # bugs: optional list of bug numbers which pertain to these expectations 1690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # notes: free-form text notes to add to all updated expectations 1700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # mark_unreviewed: if True, mark these expectations as NOT having been 1710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # reviewed by a human; otherwise, leave that field blank. 1720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # Currently, there is no way to make this script mark 1730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # expectations as reviewed-by-human=True. 1740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # TODO(epoger): Add that capability to a review tool. 1750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # mark_ignore_failure: if True, mark failures of a given test as being 1760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # ignored. 1770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # from_trybot: if True, read actual-result JSON files generated from a 1780a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # trybot run rather than a waterfall run. 179e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger def __init__(self, expectations_root, expectations_input_filename, 180e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger expectations_output_filename, actuals_base_url, 181e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger actuals_filename, exception_handler, 1820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger tests=None, configs=None, add_new=False, add_ignored=False, 1830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger bugs=None, notes=None, mark_unreviewed=None, 1840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger mark_ignore_failure=False, from_trybot=False): 185e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._expectations_root = expectations_root 186e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._expectations_input_filename = expectations_input_filename 187e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._expectations_output_filename = expectations_output_filename 188e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._tests = tests 189e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._configs = configs 190e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._actuals_base_url = actuals_base_url 191e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._actuals_filename = actuals_filename 192e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._exception_handler = exception_handler 193e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._add_new = add_new 1940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger self._add_ignored = add_ignored 1950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger self._bugs = bugs 1960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger self._notes = notes 1970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger self._mark_unreviewed = mark_unreviewed 1980a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger self._mark_ignore_failure = mark_ignore_failure; 1990a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if self._tests or self._configs: 2000a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger self._image_filename_re = re.compile(gm_json.IMAGE_FILENAME_PATTERN) 2010a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger else: 2020a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger self._image_filename_re = None 203e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._using_svn = os.path.isdir(os.path.join(expectations_root, '.svn')) 2040a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger self._from_trybot = from_trybot 205e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 206e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Executes subprocess.call(cmd). 207e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Raises an Exception if the command fails. 208e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger def _Call(self, cmd): 209e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if subprocess.call(cmd) != 0: 210e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger raise _InternalException('error running command: ' + ' '.join(cmd)) 211e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 212e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Returns the full contents of filepath, as a single string. 213e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # If filepath looks like a URL, try to read it that way instead of as 214e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # a path on local storage. 215e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # 216e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Raises _InternalException if there is a problem. 217e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger def _GetFileContents(self, filepath): 218e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if filepath.startswith('http:') or filepath.startswith('https:'): 219e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger try: 220e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger return urllib2.urlopen(filepath).read() 221e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger except urllib2.HTTPError as e: 222e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger raise _InternalException('unable to read URL %s: %s' % ( 223e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger filepath, e)) 224e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger else: 225e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger return open(filepath, 'r').read() 226e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 227e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Returns a dictionary of actual results from actual-results.json file. 228e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # 229e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # The dictionary returned has this format: 230e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # { 231e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # u'imageblur_565.png': [u'bitmap-64bitMD5', 3359963596899141322], 232e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # u'imageblur_8888.png': [u'bitmap-64bitMD5', 4217923806027861152], 233e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # u'shadertext3_8888.png': [u'bitmap-64bitMD5', 3713708307125704716] 234e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # } 235e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # 236e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # If the JSON actual result summary file cannot be loaded, logs a warning 237e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # message and returns None. 238e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # If the JSON actual result summary file can be loaded, but we have 239e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # trouble parsing it, raises an Exception. 240e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # 241e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # params: 242e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # json_url: URL pointing to a JSON actual result summary file 243e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # sections: a list of section names to include in the results, e.g. 244e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # [gm_json.JSONKEY_ACTUALRESULTS_FAILED, 245e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # gm_json.JSONKEY_ACTUALRESULTS_NOCOMPARISON] ; 246e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # if None, then include ALL sections. 247e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger def _GetActualResults(self, json_url, sections=None): 248e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger try: 249e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger json_contents = self._GetFileContents(json_url) 250e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger except _InternalException: 251e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger print >> sys.stderr, ( 252e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 'could not read json_url %s ; skipping this platform.' % 253e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger json_url) 254e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger return None 255e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger json_dict = gm_json.LoadFromString(json_contents) 256e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger results_to_return = {} 257e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger actual_results = json_dict[gm_json.JSONKEY_ACTUALRESULTS] 258e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if not sections: 259e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger sections = actual_results.keys() 260e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger for section in sections: 261e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger section_results = actual_results[section] 262e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if section_results: 263e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger results_to_return.update(section_results) 264e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger return results_to_return 265e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 266e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Rebaseline all tests/types we specified in the constructor, 2670a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # within this builder's subdirectory in expectations/gm . 268e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # 269e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # params: 270e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # builder : e.g. 'Test-Win7-ShuttleA-HD2000-x86-Release' 2710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger def RebaselineSubdir(self, builder): 272e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Read in the actual result summary, and extract all the tests whose 273e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # results we need to update. 2740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger results_builder = str(builder) 2750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if self._from_trybot: 2760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger results_builder = results_builder + TRYBOT_SUFFIX 2770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger actuals_url = '/'.join([self._actuals_base_url, results_builder, 278e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._actuals_filename]) 2790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # Only update results for tests that are currently failing. 2800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # We don't want to rewrite results for tests that are already succeeding, 2810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # because we don't want to add annotation fields (such as 2820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # JSONKEY_EXPECTEDRESULTS_BUGS) except for tests whose expectations we 2830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # are actually modifying. 2840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger sections = [gm_json.JSONKEY_ACTUALRESULTS_FAILED] 285e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if self._add_new: 286e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger sections.append(gm_json.JSONKEY_ACTUALRESULTS_NOCOMPARISON) 2870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if self._add_ignored: 2880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger sections.append(gm_json.JSONKEY_ACTUALRESULTS_FAILUREIGNORED) 289e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger results_to_update = self._GetActualResults(json_url=actuals_url, 290e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger sections=sections) 291e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 292e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Read in current expectations. 293e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger expectations_input_filepath = os.path.join( 2940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger self._expectations_root, builder, self._expectations_input_filename) 295e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger expectations_dict = gm_json.LoadFromFile(expectations_input_filepath) 2960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger expected_results = expectations_dict.get(gm_json.JSONKEY_EXPECTEDRESULTS) 2970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if not expected_results: 2980a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger expected_results = {} 2990a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger expectations_dict[gm_json.JSONKEY_EXPECTEDRESULTS] = expected_results 300e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 301e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Update the expectations in memory, skipping any tests/configs that 302e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # the caller asked to exclude. 303e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger skipped_images = [] 304e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if results_to_update: 305e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger for (image_name, image_results) in results_to_update.iteritems(): 3060a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if self._image_filename_re: 3070a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger (test, config) = self._image_filename_re.match(image_name).groups() 3080a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if self._tests: 3090a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if test not in self._tests: 3100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger skipped_images.append(image_name) 3110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger continue 3120a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if self._configs: 3130a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if config not in self._configs: 3140a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger skipped_images.append(image_name) 3150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger continue 316e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if not expected_results.get(image_name): 317e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger expected_results[image_name] = {} 3180a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger expected_results[image_name]\ 3190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger [gm_json.JSONKEY_EXPECTEDRESULTS_ALLOWEDDIGESTS]\ 3200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger = [image_results] 3210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if self._mark_unreviewed: 3220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger expected_results[image_name]\ 3230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger [gm_json.JSONKEY_EXPECTEDRESULTS_REVIEWED]\ 3240a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger = False 3250a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if self._mark_ignore_failure: 3260a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger expected_results[image_name]\ 3270a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger [gm_json.JSONKEY_EXPECTEDRESULTS_IGNOREFAILURE]\ 3280a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger = True 3290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if self._bugs: 3300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger expected_results[image_name]\ 3310a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger [gm_json.JSONKEY_EXPECTEDRESULTS_BUGS]\ 3320a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger = self._bugs 3330a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if self._notes: 3340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger expected_results[image_name]\ 3350a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger [gm_json.JSONKEY_EXPECTEDRESULTS_NOTES]\ 3360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger = self._notes 33758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 338e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Write out updated expectations. 339e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger expectations_output_filepath = os.path.join( 3400a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger self._expectations_root, builder, self._expectations_output_filename) 341e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger gm_json.WriteToFile(expectations_dict, expectations_output_filepath) 34258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 343e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Mark the JSON file as plaintext, so text-style diffs can be applied. 344e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger # Fixes https://code.google.com/p/skia/issues/detail?id=1442 345e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if self._using_svn: 346e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger self._Call(['svn', 'propset', '--quiet', 'svn:mime-type', 347e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 'text/x-json', expectations_output_filepath]) 34858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 34958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# main... 35058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 3510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerparser = argparse.ArgumentParser( 3520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger formatter_class=argparse.RawDescriptionHelpFormatter, 3530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger epilog='Here is the full set of builders we know about:' + 3540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger '\n '.join([''] + sorted(TEST_BUILDERS))) 35558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerparser.add_argument('--actuals-base-url', 3560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('base URL from which to read files containing JSON ' 3570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'summaries of actual GM results; defaults to ' 3580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger '%(default)s. To get a specific revision (useful for ' 3590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'trybots) replace "svn" with "svn-history/r123". ' 3600a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'If SKIMAGE is True, defaults to ' + 3610a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger gm_json.SKIMAGE_ACTUALS_BASE_URL), 36258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger default='http://skia-autogen.googlecode.com/svn/gm-actual') 36358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerparser.add_argument('--actuals-filename', 3640a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('filename (within builder-specific subdirectories ' 3650a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'of ACTUALS_BASE_URL) to read a summary of results ' 3660a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'from; defaults to %(default)s'), 36758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger default='actual-results.json') 36858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerparser.add_argument('--add-new', action='store_true', 3690a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('in addition to the standard behavior of ' 3700a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'updating expectations for failing tests, add ' 3710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'expectations for tests which don\'t have ' 3720a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'expectations yet.')) 3730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerparser.add_argument('--add-ignored', action='store_true', 3740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('in addition to the standard behavior of ' 3750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'updating expectations for failing tests, add ' 3760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'expectations for tests for which failures are ' 3770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'currently ignored.')) 3780a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerparser.add_argument('--bugs', metavar='BUG', type=int, nargs='+', 3790a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('Skia bug numbers (under ' 3800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'https://code.google.com/p/skia/issues/list ) which ' 3810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'pertain to this set of rebaselines.')) 3820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerparser.add_argument('--builders', metavar='BUILDER', nargs='+', 3830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('which platforms to rebaseline; ' 3840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'if unspecified, rebaseline all known platforms ' 3850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger '(see below for a list)')) 38658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# TODO(epoger): Add test that exercises --configs argument. 38758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerparser.add_argument('--configs', metavar='CONFIG', nargs='+', 3880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('which configurations to rebaseline, e.g. ' 3890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger '"--configs 565 8888", as a filter over the full set ' 3900a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'of results in ACTUALS_FILENAME; if unspecified, ' 3910a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'rebaseline *all* configs that are available.')) 39258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerparser.add_argument('--expectations-filename', 3930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('filename (under EXPECTATIONS_ROOT) to read ' 3940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'current expectations from, and to write new ' 3950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'expectations into (unless a separate ' 3960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'EXPECTATIONS_FILENAME_OUTPUT has been specified); ' 3970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'defaults to %(default)s'), 39858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger default='expected-results.json') 39958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerparser.add_argument('--expectations-filename-output', 4000a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('filename (under EXPECTATIONS_ROOT) to write ' 4010a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'updated expectations into; by default, overwrites ' 4020a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'the input file (EXPECTATIONS_FILENAME)'), 40358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger default='') 40458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerparser.add_argument('--expectations-root', 4050a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('root of expectations directory to update-- should ' 4060a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'contain one or more builder subdirectories. ' 4070a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'Defaults to %(default)s. If SKIMAGE is set, ' 4080a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger ' defaults to ' + gm_json.SKIMAGE_EXPECTATIONS_ROOT), 40958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger default=os.path.join('expectations', 'gm')) 41058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerparser.add_argument('--keep-going-on-failure', action='store_true', 4110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('instead of halting at the first error encountered, ' 4120a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'keep going and rebaseline as many tests as ' 4130a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'possible, and then report the full set of errors ' 4140a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'at the end')) 4150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerparser.add_argument('--notes', 4160a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('free-form text notes to add to all updated ' 4170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'expectations')) 41858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# TODO(epoger): Add test that exercises --tests argument. 41958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerparser.add_argument('--tests', metavar='TEST', nargs='+', 4200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('which tests to rebaseline, e.g. ' 4210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger '"--tests aaclip bigmatrix", as a filter over the ' 4220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'full set of results in ACTUALS_FILENAME; if ' 4230a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'unspecified, rebaseline *all* tests that are ' 4240a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'available.')) 4250a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerparser.add_argument('--unreviewed', action='store_true', 4260a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('mark all expectations modified by this run as ' 4270a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger '"%s": False' % 4280a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger gm_json.JSONKEY_EXPECTEDRESULTS_REVIEWED)) 4290a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerparser.add_argument('--ignore-failure', action='store_true', 4300a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('mark all expectations modified by this run as ' 4310a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger '"%s": True' % 4320a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger gm_json.JSONKEY_ACTUALRESULTS_FAILUREIGNORED)) 4330a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerparser.add_argument('--from-trybot', action='store_true', 4340a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('pull the actual-results.json file from the ' 4350a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'corresponding trybot, rather than the main builder')) 4360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerparser.add_argument('--skimage', action='store_true', 4370a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger help=('Rebaseline skimage results instead of gm. Defaults ' 4380a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'to False. If True, TESTS and CONFIGS are ignored, ' 4390a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'and ACTUALS_BASE_URL and EXPECTATIONS_ROOT are set ' 4400a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 'to alternate defaults, specific to skimage.')) 44158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerargs = parser.parse_args() 44258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerexception_handler = ExceptionHandler( 44358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger keep_going_on_failure=args.keep_going_on_failure) 4440a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerif args.builders: 4450a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builders = args.builders 446e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger missing_json_is_fatal = True 44758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerelse: 4480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builders = sorted(TEST_BUILDERS) 449e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger missing_json_is_fatal = False 4500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerif args.skimage: 4510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger # Use a different default if --skimage is specified. 4520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if args.actuals_base_url == parser.get_default('actuals_base_url'): 4530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger args.actuals_base_url = gm_json.SKIMAGE_ACTUALS_BASE_URL 4540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if args.expectations_root == parser.get_default('expectations_root'): 4550a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger args.expectations_root = gm_json.SKIMAGE_EXPECTATIONS_ROOT 4560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerfor builder in builders: 4570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if not builder in TEST_BUILDERS: 4580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger raise Exception(('unrecognized builder "%s"; ' + 459e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 'should be one of %s') % ( 4600a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger builder, TEST_BUILDERS)) 461e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 4620a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger expectations_json_file = os.path.join(args.expectations_root, builder, 463e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger args.expectations_filename) 464e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if os.path.isfile(expectations_json_file): 465e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger rebaseliner = JsonRebaseliner( 466e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger expectations_root=args.expectations_root, 467e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger expectations_input_filename=args.expectations_filename, 468e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger expectations_output_filename=(args.expectations_filename_output or 469e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger args.expectations_filename), 470e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger tests=args.tests, configs=args.configs, 471e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger actuals_base_url=args.actuals_base_url, 472e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger actuals_filename=args.actuals_filename, 473e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger exception_handler=exception_handler, 4740a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger add_new=args.add_new, add_ignored=args.add_ignored, 4750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger bugs=args.bugs, notes=args.notes, 4760a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger mark_unreviewed=args.unreviewed, 4770a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger mark_ignore_failure=args.ignore_failure, 4780a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger from_trybot=args.from_trybot) 47958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger try: 4800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger rebaseliner.RebaselineSubdir(builder=builder) 4810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger except: 4820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger exception_handler.RaiseExceptionOrContinue() 483e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger else: 4840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger try: 4850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger raise _InternalException('expectations_json_file %s not found' % 4860a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger expectations_json_file) 4870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger except: 4880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger exception_handler.RaiseExceptionOrContinue() 48958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 49058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerexception_handler.ReportAllFailures() 491