rebaseline_server: make intermediate JSON specify base urls for diff images

BUG=skia:1919,skia:2230
NOTREECHECKS=True
NOTRY=True
R=rmistry@google.com

Author: epoger@google.com

Review URL: https://codereview.chromium.org/196533021

git-svn-id: http://skia.googlecode.com/svn/trunk@13830 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2014-03-17 14:22:02 +00:00
parent 1d1f2347d3
commit d1c85d2920
8 changed files with 97 additions and 50 deletions

View File

@ -9,6 +9,10 @@ found in the LICENSE file.
ImagePairSet class; see its docstring below.
"""
# System-level imports
import posixpath
# Local imports
import column
# Keys used within dictionary representation of ImagePairSet.
@ -16,10 +20,15 @@ import column
KEY__EXTRACOLUMNHEADERS = 'extraColumnHeaders'
KEY__IMAGEPAIRS = 'imagePairs'
KEY__IMAGESETS = 'imageSets'
KEY__IMAGESETS__BASE_URL = 'baseUrl'
KEY__IMAGESETS__DESCRIPTION = 'description'
KEY__IMAGESETS__FIELD__BASE_URL = 'baseUrl'
KEY__IMAGESETS__FIELD__DESCRIPTION = 'description'
KEY__IMAGESETS__SET__DIFFS = 'diffs'
KEY__IMAGESETS__SET__IMAGE_A = 'imageA'
KEY__IMAGESETS__SET__IMAGE_B = 'imageB'
KEY__IMAGESETS__SET__WHITEDIFFS = 'whiteDiffs'
DEFAULT_DESCRIPTIONS = ('setA', 'setB')
DIFF_BASE_URL = '/static/generated-images'
class ImagePairSet(object):
@ -42,16 +51,18 @@ class ImagePairSet(object):
self._extra_column_tallies = {} # maps column_id -> values
# -> instances_per_value
self._image_pair_dicts = []
self._image_base_url = None
self._diff_base_url = DIFF_BASE_URL
def add_image_pair(self, image_pair):
"""Adds an ImagePair; this may be repeated any number of times."""
# Special handling when we add the first ImagePair...
if not self._image_pair_dicts:
self._base_url = image_pair.base_url
self._image_base_url = image_pair.base_url
if image_pair.base_url != self._base_url:
if image_pair.base_url != self._image_base_url:
raise Exception('added ImagePair with base_url "%s" instead of "%s"' % (
image_pair.base_url, self._base_url))
image_pair.base_url, self._image_base_url))
self._image_pair_dicts.append(image_pair.as_dict())
extra_columns_dict = image_pair.extra_columns_dict
if extra_columns_dict:
@ -127,14 +138,29 @@ class ImagePairSet(object):
Uses the KEY__* constants as keys.
"""
key_description = KEY__IMAGESETS__FIELD__DESCRIPTION
key_base_url = KEY__IMAGESETS__FIELD__BASE_URL
return {
KEY__EXTRACOLUMNHEADERS: self._column_headers_as_dict(),
KEY__IMAGEPAIRS: self._image_pair_dicts,
KEY__IMAGESETS: [{
KEY__IMAGESETS__BASE_URL: self._base_url,
KEY__IMAGESETS__DESCRIPTION: self._descriptions[0],
}, {
KEY__IMAGESETS__BASE_URL: self._base_url,
KEY__IMAGESETS__DESCRIPTION: self._descriptions[1],
}],
KEY__IMAGESETS: {
KEY__IMAGESETS__SET__IMAGE_A: {
key_description: self._descriptions[0],
key_base_url: self._image_base_url,
},
KEY__IMAGESETS__SET__IMAGE_B: {
key_description: self._descriptions[1],
key_base_url: self._image_base_url,
},
KEY__IMAGESETS__SET__DIFFS: {
key_description: 'color difference per channel',
key_base_url: posixpath.join(
self._diff_base_url, 'diffs'),
},
KEY__IMAGESETS__SET__WHITEDIFFS: {
key_description: 'differing pixels in white',
key_base_url: posixpath.join(
self._diff_base_url, 'whitediffs'),
},
},
}

View File

@ -106,16 +106,24 @@ class ImagePairSetTest(unittest.TestCase):
IMAGEPAIR_2_AS_DICT,
IMAGEPAIR_3_AS_DICT,
],
'imageSets': [
{
'imageSets': {
'imageA': {
'baseUrl': BASE_URL_1,
'description': SET_A_DESCRIPTION,
},
{
'imageB': {
'baseUrl': BASE_URL_1,
'description': SET_B_DESCRIPTION,
},
],
'diffs': {
'baseUrl': '/static/generated-images/diffs',
'description': 'color difference per channel',
},
'whiteDiffs': {
'baseUrl': '/static/generated-images/whitediffs',
'description': 'differing pixels in white',
},
},
}
image_pair_set = imagepairset.ImagePairSet(

View File

@ -38,7 +38,7 @@ import imagepairset
# Keys used to link an image to a particular GM test.
# NOTE: Keep these in sync with static/constants.js
REBASELINE_SERVER_SCHEMA_VERSION_NUMBER = 1
REBASELINE_SERVER_SCHEMA_VERSION_NUMBER = 2
KEY__EXPECTATIONS__BUGS = gm_json.JSONKEY_EXPECTEDRESULTS_BUGS
KEY__EXPECTATIONS__IGNOREFAILURE = gm_json.JSONKEY_EXPECTEDRESULTS_IGNOREFAILURE
KEY__EXPECTATIONS__REVIEWED = gm_json.JSONKEY_EXPECTEDRESULTS_REVIEWED

View File

@ -330,6 +330,8 @@ class HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
now = int(time.time())
response_dict = {
results_mod.KEY__HEADER: {
results_mod.KEY__HEADER__SCHEMA_VERSION: (
results_mod.REBASELINE_SERVER_SCHEMA_VERSION_NUMBER),
results_mod.KEY__HEADER__IS_STILL_LOADING: True,
results_mod.KEY__HEADER__TIME_UPDATED: now,
results_mod.KEY__HEADER__TIME_NEXT_UPDATE_AVAILABLE: (

View File

@ -34,11 +34,15 @@ module.constant('constants', (function() {
KEY__EXTRACOLUMNHEADERS: 'extraColumnHeaders',
KEY__IMAGEPAIRS: 'imagePairs',
KEY__IMAGESETS: 'imageSets',
KEY__IMAGESETS__BASE_URL: 'baseUrl',
KEY__IMAGESETS__DESCRIPTION: 'description',
KEY__IMAGESETS__FIELD__BASE_URL: 'baseUrl',
KEY__IMAGESETS__FIELD__DESCRIPTION: 'description',
KEY__IMAGESETS__SET__DIFFS: 'diffs',
KEY__IMAGESETS__SET__IMAGE_A: 'imageA',
KEY__IMAGESETS__SET__IMAGE_B: 'imageB',
KEY__IMAGESETS__SET__WHITEDIFFS: 'whiteDiffs',
// NOTE: Keep these in sync with ../results.py
REBASELINE_SERVER_SCHEMA_VERSION_NUMBER: 1,
REBASELINE_SERVER_SCHEMA_VERSION_NUMBER: 2,
KEY__EXPECTATIONS__BUGS: 'bugs',
KEY__EXPECTATIONS__IGNOREFAILURE: 'ignore-failure',
KEY__EXPECTATIONS__REVIEWED: 'reviewed-by-human',

View File

@ -63,8 +63,7 @@ Loader.controller(
$scope.constants = constants;
$scope.windowTitle = "Loading GM Results...";
$scope.resultsToLoad = $location.search().resultsToLoad;
$scope.loadingMessage = "Loading results from '" + $scope.resultsToLoad +
"', please wait...";
$scope.loadingMessage = "please wait...";
/**
* On initial page load, load a full dictionary of results.
@ -74,7 +73,13 @@ Loader.controller(
$http.get($scope.resultsToLoad).success(
function(data, status, header, config) {
var dataHeader = data[constants.KEY__HEADER];
if (dataHeader[constants.KEY__HEADER__IS_STILL_LOADING]) {
if (dataHeader[constants.KEY__HEADER__SCHEMA_VERSION] !=
constants.REBASELINE_SERVER_SCHEMA_VERSION_NUMBER) {
$scope.loadingMessage = "ERROR: Got JSON file with schema version "
+ dataHeader[constants.KEY__HEADER__SCHEMA_VERSION]
+ " but expected schema version "
+ constants.REBASELINE_SERVER_SCHEMA_VERSION_NUMBER;
} else if (dataHeader[constants.KEY__HEADER__IS_STILL_LOADING]) {
// Apply the server's requested reload delay to local time,
// so we will wait the right number of seconds regardless of clock
// skew between client and server.
@ -84,19 +89,13 @@ Loader.controller(
var timeNow = new Date().getTime();
var timeToReload = timeNow + reloadDelayInSeconds * 1000;
$scope.loadingMessage =
"Server is still loading results; will retry at " +
"server is still loading results; will retry at " +
$scope.localTimeString(timeToReload / 1000);
$timeout(
function(){location.reload();},
timeToReload - timeNow);
} else if (dataHeader[constants.KEY__HEADER__SCHEMA_VERSION] !=
constants.REBASELINE_SERVER_SCHEMA_VERSION_NUMBER) {
$scope.loadingMessage = "ERROR: Got JSON file with schema version "
+ dataHeader[constants.KEY__HEADER__SCHEMA_VERSION]
+ " but expected schema version "
+ constants.REBASELINE_SERVER_SCHEMA_VERSION_NUMBER;
} else {
$scope.loadingMessage = "Processing data, please wait...";
$scope.loadingMessage = "processing data, please wait...";
$scope.header = dataHeader;
$scope.extraColumnHeaders = data[constants.KEY__EXTRACOLUMNHEADERS];
@ -172,8 +171,7 @@ Loader.controller(
}
).error(
function(data, status, header, config) {
$scope.loadingMessage = "Failed to load results from '"
+ $scope.resultsToLoad + "'";
$scope.loadingMessage = "FAILED to load.";
$scope.windowTitle = "Failed to Load GM Results";
}
);

View File

@ -18,7 +18,8 @@
</a>
</h2>
<em>
<em ng-show="!extraColumnHeaders"><!-- show until data is loaded -->
Loading results from <a href="{{resultsToLoad}}">{{resultsToLoad}}</a> ...
{{loadingMessage}}
</em>
@ -31,7 +32,7 @@
</div>
<div ng-show="header[constants.KEY__HEADER__TIME_UPDATED]">
Results current as of {{localTimeString(header[constants.KEY__HEADER__TIME_UPDATED])}}
Results from <a href="{{resultsToLoad}}">{{resultsToLoad}}</a> current as of {{localTimeString(header[constants.KEY__HEADER__TIME_UPDATED])}}
</div>
<div><!-- tabs -->
@ -242,10 +243,10 @@
bugs
</th>
<th width="{{imageSize}}">
{{imageSets[0][constants.KEY__IMAGESETS__DESCRIPTION]}}
{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
</th>
<th width="{{imageSize}}">
{{imageSets[1][constants.KEY__IMAGESETS__DESCRIPTION]}}
{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
</th>
<th width="{{imageSize}}">
<input type="radio"
@ -341,10 +342,10 @@
<!-- image A -->
<td valign="bottom" width="{{imageSize}}">
<div ng-if="imagePair[constants.KEY__IMAGE_A_URL] != null">
<a href="{{imageSets[0][constants.KEY__IMAGESETS__BASE_URL]}}/{{imagePair[constants.KEY__IMAGE_A_URL]}}" target="_blank">View Image</a><br/>
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGE_A_URL]}}" target="_blank">View Image</a><br/>
<img ng-if="showThumbnails"
width="{{imageSize}}"
src="{{imageSets[0][constants.KEY__IMAGESETS__BASE_URL]}}/{{imagePair[constants.KEY__IMAGE_A_URL]}}" />
src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGE_A_URL]}}" />
</div>
<div ng-show="imagePair[constants.KEY__IMAGE_A_URL] == null"
style="text-align:center">
@ -355,10 +356,10 @@
<!-- image B -->
<td valign="bottom" width="{{imageSize}}">
<div ng-if="imagePair[constants.KEY__IMAGE_B_URL] != null">
<a href="{{imageSets[1][constants.KEY__IMAGESETS__BASE_URL]}}/{{imagePair[constants.KEY__IMAGE_B_URL]}}" target="_blank">View Image</a><br/>
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGE_B_URL]}}" target="_blank">View Image</a><br/>
<img ng-if="showThumbnails"
width="{{imageSize}}"
src="{{imageSets[1][constants.KEY__IMAGESETS__BASE_URL]}}/{{imagePair[constants.KEY__IMAGE_B_URL]}}" />
src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGE_B_URL]}}" />
</div>
<div ng-show="imagePair[constants.KEY__IMAGE_B_URL] == null"
style="text-align:center">
@ -374,10 +375,10 @@
{{imagePair[constants.KEY__DIFFERENCE_DATA][constants.KEY__DIFFERENCE_DATA__PERCENT_DIFF_PIXELS].toFixed(4)}}%
({{imagePair[constants.KEY__DIFFERENCE_DATA][constants.KEY__DIFFERENCE_DATA__NUM_DIFF_PIXELS]}})
<br/>
<a href="/static/generated-images/whitediffs/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
<img ng-if="showThumbnails"
width="{{imageSize}}"
src="/static/generated-images/whitediffs/{{getImageDiffRelativeUrl(imagePair)}}" />
src="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
</div>
<div ng-show="!imagePair[constants.KEY__IS_DIFFERENT]"
style="text-align:center">
@ -393,11 +394,11 @@
{{imagePair[constants.KEY__DIFFERENCE_DATA][constants.KEY__DIFFERENCE_DATA__PERCEPTUAL_DIFF].toFixed(4)}}%
{{imagePair[constants.KEY__DIFFERENCE_DATA][constants.KEY__DIFFERENCE_DATA__MAX_DIFF_PER_CHANNEL]}}
<br/>
<a href="/static/generated-images/diffs/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
<img ng-if="showThumbnails"
ng-style="{backgroundColor: pixelDiffBgColor}"
width="{{imageSize}}"
src="/static/generated-images/diffs/{{getImageDiffRelativeUrl(imagePair)}}"/>
src="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
</div>
<div ng-show="!imagePair[constants.KEY__IS_DIFFERENT]"
style="text-align:center">

View File

@ -52,7 +52,7 @@
"dataHash": "2099241024256114776",
"isEditable": false,
"isExported": true,
"schemaVersion": 1,
"schemaVersion": 2,
"timeNextUpdateAvailable": null,
"timeUpdated": 12345678,
"type": "all"
@ -541,14 +541,22 @@
"isDifferent": false
}
],
"imageSets": [
{
"imageSets": {
"diffs": {
"baseUrl": "/static/generated-images/diffs",
"description": "color difference per channel"
},
"imageA": {
"baseUrl": "http://chromium-skia-gm.commondatastorage.googleapis.com/gm",
"description": "expected image"
},
{
"imageB": {
"baseUrl": "http://chromium-skia-gm.commondatastorage.googleapis.com/gm",
"description": "actual image"
},
"whiteDiffs": {
"baseUrl": "/static/generated-images/whitediffs",
"description": "differing pixels in white"
}
]
}
}